@@ -12,6 +12,7 @@ pub trait HashSequence {
1212pub trait HashSeqBuilder {
1313 type Seq : HashSequence ;
1414
15+ /// Returns a bit mask indicating which buckets have at least one hash.
1516 fn bit_mask ( & self ) -> u64 ;
1617 /// Return a HashSequence instance which is seeded with the given bit position
1718 /// and the seed of this builder.
@@ -66,7 +67,7 @@ struct BucketIterator<H: HashSequence> {
6667 hasher : H ,
6768 n : usize ,
6869 is_first : bool ,
69- bit : u64 , // A bitmask with a single bit set.
70+ bit : u64 , // A bitmask with a single bit set.
7071}
7172
7273impl < H : HashSequence > BucketIterator < H > {
@@ -199,20 +200,30 @@ pub struct ConsistentHasher<H: HashSeqBuilder> {
199200 builder : H ,
200201}
201202
202- impl < H : HashSeqBuilder + Clone > ConsistentHasher < H > {
203+ impl < H : HashSeqBuilder > ConsistentHasher < H > {
203204 pub fn new ( builder : H ) -> Self {
204205 Self { builder }
205206 }
206207
207- pub fn prev ( & self , n : usize ) -> Option < usize > {
208+ pub fn prev ( & self , n : usize ) -> Option < usize >
209+ where
210+ H : Clone ,
211+ {
208212 let mut sampler = ConsistentHashRevIterator :: new ( n, self . builder . clone ( ) ) ;
209213 sampler. next ( )
210214 }
211215
212- pub fn next ( & self , n : usize ) -> Option < usize > {
216+ pub fn next ( & self , n : usize ) -> Option < usize >
217+ where
218+ H : Clone ,
219+ {
213220 let mut sampler = ConsistentHashIterator :: new ( n, self . builder . clone ( ) ) ;
214221 sampler. next ( )
215222 }
223+
224+ pub fn into_prev ( self , n : usize ) -> Option < usize > {
225+ ConsistentHashRevIterator :: new ( n, self . builder ) . next ( )
226+ }
216227}
217228
218229/// Implementation of a consistent choose k hashing algorithm.
@@ -231,27 +242,38 @@ impl<H: ManySeqBuilder> ConsistentChooseKHasher<H> {
231242 Self { builder, k }
232243 }
233244
234- // TODO: Implement this as an iterator!
235- pub fn prev ( & self , mut n : usize , samples : & mut Vec < usize > ) {
236- let mut samplers: Vec < _ > = ( 0 ..self . k )
237- . map ( |i| ConsistentHashRevIterator :: new ( n - i, self . builder . seq_builder ( i) ) . peekable ( ) )
238- . collect ( ) ;
245+ pub fn prev ( & self , n : usize ) -> Vec < usize > {
246+ let mut res = Vec :: with_capacity ( self . k ) ;
247+ self . prev_with_vec ( n, & mut res) ;
248+ res
249+ }
250+
251+ pub fn prev_with_vec ( & self , mut n : usize , samples : & mut Vec < usize > ) {
252+ assert ! ( n >= self . k, "n must be at least k" ) ;
239253 samples. clear ( ) ;
254+ for i in 0 ..self . k {
255+ samples. push (
256+ ConsistentHasher :: new ( self . builder . seq_builder ( i) )
257+ . into_prev ( n - i)
258+ . expect ( "must not fail" )
259+ + i,
260+ ) ;
261+ }
240262 for i in ( 0 ..self . k ) . rev ( ) {
241- let mut max = 0 ;
242- for k in 0 ..=i {
243- while samplers[ k] . peek ( ) >= Some ( & ( n - k) ) && n - k > 0 {
244- samplers[ k] . next ( ) ;
263+ n = samples[ 0 ..=i] . iter ( ) . copied ( ) . max ( ) . expect ( "" ) ;
264+ samples[ i] = n;
265+ for j in 0 ..i {
266+ if samples[ j] == n {
267+ samples[ j] = ConsistentHasher :: new ( self . builder . seq_builder ( j) )
268+ . into_prev ( n - j)
269+ . expect ( "must not fail" )
270+ + j;
245271 }
246- max = max. max ( samplers[ k] . peek ( ) . unwrap ( ) + k) ;
247272 }
248- samples. push ( max) ;
249- n = max;
250273 }
251274 }
252275}
253276
254-
255277#[ cfg( test) ]
256278mod tests {
257279 use std:: hash:: DefaultHasher ;
@@ -327,6 +349,7 @@ mod tests {
327349 }
328350 }
329351 println ! ( "{stats:?}" ) ;
352+ assert_eq ! ( stats, vec![ 10 , 12 , 6 , 6 , 6 , 5 , 9 , 10 ] ) ;
330353 // Test consistency when increasing k!
331354 for k in 1 ..10 {
332355 for n in k + 1 ..20 {
0 commit comments