22
33use std:: { marker:: PhantomData , sync:: Arc } ;
44
5- use crate :: Method ;
5+ use crate :: { build_hasher :: ReproducibleBuildHasher , Method } ;
66
77mod bitchunks;
88mod buckets;
@@ -30,8 +30,9 @@ use once_cell::sync::Lazy;
3030/// Those conversions can be shared across multiple geo filter instances. This way, the
3131/// conversions can also be optimized via e.g. lookup tables without paying the cost with every
3232/// new geo filter instance again and again.
33- pub trait GeoConfig < M : Method > : Clone + Eq + Sized + Send + Sync {
33+ pub trait GeoConfig < M : Method > : Clone + Eq + Sized {
3434 type BucketType : IsBucketType + ' static ;
35+ type BuildHasher : ReproducibleBuildHasher ;
3536
3637 /// The number of most-significant bits that are stored sparsely as positions.
3738 fn max_msb_len ( & self ) -> usize ;
@@ -79,9 +80,16 @@ pub trait GeoConfig<M: Method>: Clone + Eq + Sized + Send + Sync {
7980/// Instantiating this type may panic if `T` is too small to hold the maximum possible
8081/// bucket id determined by `B`, or `B` is larger than the largest statically defined
8182/// lookup table.
82- #[ derive( Clone , Eq , PartialEq ) ]
83- pub struct FixedConfig < M : Method , T , const B : usize , const BYTES : usize , const MSB : usize > {
84- _phantom : PhantomData < ( M , T ) > ,
83+ #[ derive( Clone ) ]
84+ pub struct FixedConfig <
85+ M : Method ,
86+ T ,
87+ const B : usize ,
88+ const BYTES : usize ,
89+ const MSB : usize ,
90+ H : ReproducibleBuildHasher ,
91+ > {
92+ _phantom : PhantomData < ( M , T , H ) > ,
8593}
8694
8795impl <
9098 const B : usize ,
9199 const BYTES : usize ,
92100 const MSB : usize ,
93- > GeoConfig < M > for FixedConfig < M , T , B , BYTES , MSB >
101+ H : ReproducibleBuildHasher ,
102+ > GeoConfig < M > for FixedConfig < M , T , B , BYTES , MSB , H >
94103{
95104 type BucketType = T ;
105+ type BuildHasher = H ;
96106
97107 #[ inline]
98108 fn max_msb_len ( & self ) -> usize {
@@ -148,42 +158,76 @@ impl<
148158 const B : usize ,
149159 const BYTES : usize ,
150160 const MSB : usize ,
151- > Default for FixedConfig < M , T , B , BYTES , MSB >
161+ H : ReproducibleBuildHasher ,
162+ > Default for FixedConfig < M , T , B , BYTES , MSB , H >
152163{
153164 fn default ( ) -> Self {
154165 assert_bucket_type_large_enough :: < T > ( B ) ;
155166 assert_buckets_within_estimation_bound ( B , BYTES * BITS_PER_BYTE ) ;
167+
156168 assert ! (
157169 B < M :: get_lookups( ) . len( ) ,
158170 "B = {} is not available for fixed config, requires B < {}" ,
159171 B ,
160172 M :: get_lookups( ) . len( )
161173 ) ;
174+
162175 Self {
163176 _phantom : PhantomData ,
164177 }
165178 }
166179}
167180
181+ impl <
182+ M : Method + Lookups ,
183+ T : IsBucketType ,
184+ const B : usize ,
185+ const BYTES : usize ,
186+ const MSB : usize ,
187+ H : ReproducibleBuildHasher ,
188+ > PartialEq for FixedConfig < M , T , B , BYTES , MSB , H >
189+ {
190+ fn eq ( & self , _other : & Self ) -> bool {
191+ H :: debug_assert_hashers_eq ( ) ;
192+
193+ // The values of the fixed config are provided at compile time
194+ // so no runtime computation is required
195+ true
196+ }
197+ }
198+
199+ impl <
200+ M : Method + Lookups ,
201+ T : IsBucketType ,
202+ const B : usize ,
203+ const BYTES : usize ,
204+ const MSB : usize ,
205+ H : ReproducibleBuildHasher ,
206+ > Eq for FixedConfig < M , T , B , BYTES , MSB , H >
207+ {
208+ }
209+
168210/// Geometric filter configuration using dynamic lookup tables.
169211#[ derive( Clone ) ]
170- pub struct VariableConfig < M : Method , T > {
212+ pub struct VariableConfig < M : Method , T , H : ReproducibleBuildHasher > {
171213 b : usize ,
172214 bytes : usize ,
173215 msb : usize ,
174- _phantom : PhantomData < ( M , T ) > ,
216+ _phantom : PhantomData < ( M , T , H ) > ,
175217 lookup : Arc < Lookup > ,
176218}
177219
178- impl < M : Method , T > Eq for VariableConfig < M , T > { }
220+ impl < M : Method , T , H : ReproducibleBuildHasher > Eq for VariableConfig < M , T , H > { }
179221
180- impl < M : Method , T > PartialEq for VariableConfig < M , T > {
222+ impl < M : Method , T , H : ReproducibleBuildHasher > PartialEq for VariableConfig < M , T , H > {
181223 fn eq ( & self , other : & Self ) -> bool {
224+ H :: debug_assert_hashers_eq ( ) ;
225+
182226 self . b == other. b && self . bytes == other. bytes && self . msb == other. msb
183227 }
184228}
185229
186- impl < M : Method + Lookups , T : IsBucketType > VariableConfig < M , T > {
230+ impl < M : Method + Lookups , T : IsBucketType , H : ReproducibleBuildHasher > VariableConfig < M , T , H > {
187231 /// Returns a new configuration value. See [`FixedConfig`] for the meaning
188232 /// of the parameters. This functions computes a new lookup table every time
189233 /// it is invoked, so make sure to share the resulting value as much as possible.
@@ -205,8 +249,11 @@ impl<M: Method + Lookups, T: IsBucketType> VariableConfig<M, T> {
205249 }
206250}
207251
208- impl < M : Method , T : IsBucketType + ' static > GeoConfig < M > for VariableConfig < M , T > {
252+ impl < M : Method , T : IsBucketType + ' static , H : ReproducibleBuildHasher > GeoConfig < M >
253+ for VariableConfig < M , T , H >
254+ {
209255 type BucketType = T ;
256+ type BuildHasher = H ;
210257
211258 #[ inline]
212259 fn max_msb_len ( & self ) -> usize {
0 commit comments