@@ -16,7 +16,7 @@ use borrow::{BorrowFrom, BorrowFromMut};
16
16
use clone:: Clone ;
17
17
use cmp;
18
18
use hash:: { Hash , Hasher } ;
19
- use iter:: { Iterator , IteratorExt , ExactSizeIterator , count} ;
19
+ use iter:: { Iterator , IteratorExt , count} ;
20
20
use marker:: { Copy , Sized } ;
21
21
use mem:: { self , min_align_of, size_of} ;
22
22
use num:: { Int , UnsignedInt } ;
@@ -72,30 +72,26 @@ pub struct RawTable<K, V> {
72
72
middle : Unique < ( K , V ) > ,
73
73
}
74
74
75
- struct RawBucket < K , V , M > {
75
+ struct RawBucket < K , V > {
76
76
hash : * mut Option < SafeHash > ,
77
77
kval : * mut ( K , V ) ,
78
78
}
79
79
80
- impl < K , V , M > Copy for RawBucket < K , V , M > { }
80
+ impl < K , V > Copy for RawBucket < K , V > { }
81
81
82
82
#[ derive( Clone ) ]
83
83
pub struct TableRef < M > ( pub M ) ;
84
84
85
85
impl < M : Copy > Copy for TableRef < M > { }
86
86
87
- struct BareBucket < K , V , M > {
88
- raw : RawBucket < K , V , M > ,
87
+ pub struct Bucket < K , V , M , S = ( ) > {
88
+ raw : RawBucket < K , V > ,
89
89
idx : usize ,
90
90
capacity : usize ,
91
91
table : TableRef < M > ,
92
92
}
93
93
94
- impl < K , V , M : Copy > Copy for BareBucket < K , V , M > { }
95
-
96
- pub struct Bucket < K , V , M , S = ( ) > ( BareBucket < K , V , M > ) ;
97
-
98
- impl < K , V , M : Copy , S > Copy for Bucket < K , V , M , S > { }
94
+ impl < K , V , M : Copy , S > Copy for Bucket < K , V , M , S > where RawTable < K , V > : BorrowFrom < M > { }
99
95
100
96
mod bucket {
101
97
pub enum Empty { }
@@ -173,75 +169,61 @@ impl<K, V, M> DerefMut for TableRef<M> where RawTable<K, V>: BorrowFromMut<M> {
173
169
}
174
170
}
175
171
176
- impl < K , V , M > RawBucket < K , V , M > {
177
- unsafe fn offset ( self , count : int ) -> RawBucket < K , V , M > {
172
+ impl < K , V > RawBucket < K , V > {
173
+ unsafe fn offset ( self , count : int ) -> RawBucket < K , V > {
178
174
RawBucket {
179
175
hash : self . hash . offset ( count) ,
180
176
kval : self . kval . offset ( count) ,
181
177
}
182
178
}
183
179
}
184
180
185
- impl < ' t , K , V , M : ' t > RawBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
186
- pub fn into_refs ( self ) -> ( & ' t K , & ' t V ) {
187
- let & ( ref k, ref v) = unsafe {
188
- & * self . kval
189
- } ;
190
- ( k, v)
191
- }
192
- }
193
-
194
- impl < ' t , K , V , M > RawBucket < K , V , M >
195
- where RawTable < K , V > : BorrowFromMut < M > , M : ' t
196
- {
197
- pub fn into_mut_refs ( self ) -> ( & ' t mut K , & ' t mut V ) {
198
- let & mut ( ref mut k, ref mut v) = unsafe {
199
- & mut * self . kval
200
- } ;
201
- ( k, v)
202
- }
203
- }
204
-
205
181
// Chain buckets! This is perfectly safe as long as operations on one
206
182
// `Bucket` can't invalidate other `Bucket`s.
207
- impl < K , V , M > BorrowFrom < Bucket < K , V , M > > for RawTable < K , V >
183
+ impl < K , V , M , S > BorrowFrom < Bucket < K , V , M , S > > for RawTable < K , V >
208
184
where RawTable < K , V > : BorrowFrom < M >
209
185
{
210
- fn borrow_from ( bucket : & Bucket < K , V , M > ) -> & RawTable < K , V > {
211
- BorrowFrom :: borrow_from ( & bucket. 0 . table . 0 )
186
+ fn borrow_from ( bucket : & Bucket < K , V , M , S > ) -> & RawTable < K , V > {
187
+ BorrowFrom :: borrow_from ( & bucket. table . 0 )
212
188
}
213
189
}
214
190
215
- impl < K , V , M > BorrowFromMut < Bucket < K , V , M > > for RawTable < K , V >
191
+ impl < K , V , M , S > BorrowFromMut < Bucket < K , V , M , S > > for RawTable < K , V >
216
192
where RawTable < K , V > : BorrowFromMut < M >
217
193
{
218
- fn borrow_from_mut ( bucket : & mut Bucket < K , V , M > ) -> & mut RawTable < K , V > {
219
- BorrowFromMut :: borrow_from_mut ( & mut bucket. 0 . table . 0 )
194
+ fn borrow_from_mut ( bucket : & mut Bucket < K , V , M , S > ) -> & mut RawTable < K , V > {
195
+ BorrowFromMut :: borrow_from_mut ( & mut bucket. table . 0 )
220
196
}
221
197
}
222
198
199
+ pub trait Put { }
200
+ impl < K , V > Put for RawTable < K , V > { }
201
+ impl < ' t , K , V > Put for & ' t mut RawTable < K , V > { }
202
+ impl < K , V , M : Put > Put for Bucket < K , V , M > { }
203
+ impl < K , V , M : Put > Put for FullBucket < K , V , M > { }
204
+
223
205
// Buckets hold references to the table.
224
206
impl < K , V , M , S > Bucket < K , V , M , S > {
225
207
/// Borrow a reference to the table.
226
208
pub fn table ( & self ) -> & M {
227
- & self . 0 . table . 0
209
+ & self . table . 0
228
210
}
229
211
/// Move out the reference to the table.
230
212
pub fn into_table ( self ) -> M {
231
- self . 0 . table . 0
213
+ self . table . 0
232
214
}
233
215
/// Get the raw index.
234
216
pub fn index ( & self ) -> usize {
235
- self . 0 . idx
217
+ self . idx
236
218
}
237
219
/// Turn the bucket into an iterator over full buckets.
238
220
pub fn into_iter ( self ) -> RawFullBuckets < K , V , M > {
239
221
RawFullBuckets {
240
- raw : self . 0 . raw ,
222
+ raw : self . raw ,
241
223
hashes_end : unsafe {
242
- self . 0 . raw . hash . offset ( self . 0 . capacity as isize - self . index ( ) as isize )
224
+ self . raw . hash . offset ( self . capacity as isize - self . index ( ) as isize )
243
225
} ,
244
- table : self . 0 . table ,
226
+ table : self . table ,
245
227
}
246
228
}
247
229
}
@@ -256,20 +238,17 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
256
238
{
257
239
let table = TableRef ( table) ;
258
240
let capacity = table. capacity ( ) ;
259
- let ib_index = ib_index & ( table. capacity ( ) - 1 ) ;
260
- let bb = BareBucket {
261
- raw : unsafe {
262
- table. first_bucket_raw ( ) . offset ( ib_index as isize )
263
- } ,
264
- idx : ib_index,
241
+ let idx = ib_index & ( capacity - 1 ) ;
242
+ let bucket: Bucket < K , V , M > = Bucket {
243
+ raw : unsafe { table. first_bucket_raw ( ) . offset ( idx as isize ) } ,
244
+ idx : idx,
265
245
capacity : capacity,
266
246
table : table,
267
247
} ;
268
-
269
248
if capacity == 0 {
270
- Err ( Bucket ( bb ) )
249
+ Err ( bucket . unsafe_cast ( ) )
271
250
} else {
272
- Ok ( Bucket ( bb ) )
251
+ Ok ( bucket . unsafe_cast ( ) )
273
252
}
274
253
}
275
254
@@ -279,9 +258,9 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
279
258
280
259
/// Narrows down the range of iteration, which must be a power of 2.
281
260
pub fn iter_to ( mut self , limit : usize ) -> Bucket < K , V , M > {
282
- assert ! ( limit <= self . 0 . table. capacity( ) ) ;
261
+ assert ! ( limit <= self . table. capacity( ) ) ;
283
262
assert ! ( limit. is_power_of_two( ) ) ;
284
- self . 0 . capacity = limit;
263
+ self . capacity = limit;
285
264
self
286
265
}
287
266
@@ -290,69 +269,69 @@ impl<K, V, M> Bucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
290
269
/// the appropriate types to call most of the other functions in
291
270
/// this module.
292
271
pub fn peek ( self ) -> BucketState < K , V , M > {
293
- match unsafe { * self . 0 . raw . hash } {
294
- None => Empty ( Bucket ( self . 0 ) ) ,
295
- _ => Full ( Bucket ( self . 0 ) ) ,
272
+ match unsafe { * self . raw . hash } {
273
+ None => Empty ( self . unsafe_cast ( ) ) ,
274
+ _ => Full ( self . unsafe_cast ( ) ) ,
296
275
}
297
276
}
298
277
299
278
/// Modifies the bucket pointer in place to make it point to the next slot.
300
279
pub fn next ( & mut self ) {
301
- self . 0 . idx += 1 ;
280
+ self . idx += 1 ;
302
281
303
- let dist = if self . 0 . idx & ( self . 0 . capacity - 1 ) == 0 {
304
- 1 i - self . 0 . capacity as int
282
+ let dist = if self . idx & ( self . capacity - 1 ) == 0 {
283
+ 1 i - self . capacity as int
305
284
} else {
306
285
1
307
286
} ;
308
287
309
288
unsafe {
310
- self . 0 . raw = self . 0 . raw . offset ( dist) ;
289
+ self . raw = self . raw . offset ( dist) ;
311
290
}
312
291
}
313
292
}
314
293
315
- impl < K , V , M > Bucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > {
316
- /// A combination of `peek` and `take` which doesn't consume the bucket.
317
- pub fn peek_take ( & mut self ) -> Option < ( K , V ) > {
318
- unsafe {
319
- if * self . 0 . raw . hash != None {
320
- * self . 0 . raw . hash = None ;
321
- self . 0 . table . size -= 1 ;
322
- let ( k, v) = ptr:: read ( self . 0 . raw . kval ) ;
323
- Some ( ( k, v) )
324
- } else {
325
- None
326
- }
294
+ impl < K , V , M , S > Bucket < K , V , M , S > where RawTable < K , V > : BorrowFrom < M > {
295
+ #[ inline]
296
+ fn unsafe_cast < S2 > ( self ) -> Bucket < K , V , M , S2 > {
297
+ Bucket {
298
+ raw : self . raw ,
299
+ idx : self . idx ,
300
+ capacity : self . capacity ,
301
+ table : self . table ,
327
302
}
328
303
}
329
- }
330
304
331
- impl < K , V , M , S > Bucket < K , V , M , S > where RawTable < K , V > : BorrowFrom < M > {
305
+ #[ inline]
306
+ pub fn into_bucket ( self ) -> Bucket < K , V , M > {
307
+ self . unsafe_cast ( )
308
+ }
309
+
332
310
#[ inline]
333
311
pub fn into_next ( self ) -> Bucket < K , V , M > {
334
312
let mut bucket = self . into_bucket ( ) ;
335
313
bucket. next ( ) ;
336
314
bucket
337
315
}
338
316
339
- #[ inline]
340
- pub fn into_bucket ( self ) -> Bucket < K , V , M > {
341
- Bucket ( self . 0 )
317
+ pub fn stash ( self ) -> Bucket < K , V , Bucket < K , V , M , S > , S > {
318
+ Bucket {
319
+ raw : self . raw ,
320
+ idx : self . idx ,
321
+ capacity : self . capacity ,
322
+ table : TableRef ( self ) ,
323
+ }
342
324
}
343
325
}
344
326
345
327
impl < K , V , M > EmptyBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
346
328
pub fn gap_peek ( self ) -> Option < GapThenFull < K , V , M > > {
347
- let gap = Bucket ( BareBucket {
329
+ let gap = Bucket {
348
330
table : TableRef ( ( ) ) ,
349
- idx : self . 0 . idx ,
350
- capacity : self . 0 . capacity ,
351
- raw : RawBucket {
352
- hash : self . 0 . raw . hash ,
353
- kval : self . 0 . raw . kval ,
354
- } ,
355
- } ) ;
331
+ idx : self . idx ,
332
+ capacity : self . capacity ,
333
+ raw : self . raw ,
334
+ } ;
356
335
357
336
match self . into_next ( ) . peek ( ) {
358
337
Full ( bucket) => {
@@ -366,7 +345,7 @@ impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
366
345
}
367
346
}
368
347
369
- impl < K , V , M > EmptyBucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > {
348
+ impl < K , V , M > EmptyBucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > , M : Put {
370
349
/// Puts given key and value pair, along with the key's hash,
371
350
/// into this bucket in the hashtable. Note how `self` is 'moved' into
372
351
/// this function, because this slot will no longer be empty when
@@ -377,17 +356,17 @@ impl<K, V, M> EmptyBucket<K, V, M> where RawTable<K, V>: BorrowFromMut<M> {
377
356
pub fn put ( mut self , hash : SafeHash , key : K , value : V )
378
357
-> FullBucket < K , V , M > {
379
358
unsafe {
380
- * self . 0 . raw . hash = Some ( hash) ;
381
- ptr:: write ( self . 0 . raw . kval , ( key, value) ) ;
359
+ * self . raw . hash = Some ( hash) ;
360
+ ptr:: write ( self . raw . kval , ( key, value) ) ;
382
361
}
383
362
384
- self . 0 . table . size += 1 ;
363
+ self . table . size += 1 ;
385
364
386
- Bucket ( self . 0 )
365
+ self . unsafe_cast ( )
387
366
}
388
367
}
389
368
390
- impl < K , V , M > FullBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
369
+ impl < ' t , K , V , M : ' t > FullBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
391
370
/// Get the distance between this bucket and the 'ideal' location
392
371
/// as determined by the key's hash stored in it.
393
372
///
@@ -397,58 +376,53 @@ impl<K, V, M> FullBucket<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
397
376
// Calculates the distance one has to travel when going from
398
377
// `hash mod capacity` onwards to `idx mod capacity`, wrapping around
399
378
// if the destination is not reached before the end of the table.
400
- ( self . 0 . idx - * * self . read ( ) . 0 as usize ) & ( self . 0 . capacity - 1 )
379
+ ( self . idx - * * self . read ( ) . 0 as usize ) & ( self . capacity - 1 )
401
380
}
402
381
403
382
/// Gets references to the key and value at a given index.
404
383
pub fn read ( & self ) -> ( & SafeHash , & K , & V ) {
405
384
let ( & ref h, & ( ref k, ref v) ) = unsafe {
406
- ( & * ( self . 0 . raw . hash as * mut SafeHash ) , & * self . 0 . raw . kval )
407
- } ;
408
- ( h, k, v)
409
- }
410
- }
411
-
412
- impl < K , V , M > FullBucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > {
413
- /// Removes this bucket's key and value from the hashtable.
414
- ///
415
- /// This works similarly to `put`, building an `EmptyBucket` out of the
416
- /// taken bucket.
417
- pub fn take ( mut self ) -> ( EmptyBucket < K , V , M > , K , V ) {
418
- self . 0 . table . size -= 1 ;
419
-
420
- unsafe {
421
- * self . 0 . raw . hash = None ;
422
- let ( k, v) = ptr:: read ( self . 0 . raw . kval ) ;
423
- ( Bucket ( self . 0 ) , k, v)
424
- }
425
- }
426
-
427
- /// Gets mutable references to the key and value at a given index.
428
- pub fn read_mut ( & mut self ) -> ( & mut SafeHash , & mut K , & mut V ) {
429
- let ( & mut ref mut h, & mut ( ref mut k, ref mut v) ) = unsafe {
430
- ( & mut * ( self . 0 . raw . hash as * mut SafeHash ) , & mut * self . 0 . raw . kval )
385
+ ( & * ( self . raw . hash as * mut SafeHash ) , & * self . raw . kval )
431
386
} ;
432
387
( h, k, v)
433
388
}
434
- }
435
-
436
- impl < ' t , K , V , M : ' t > FullBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
437
389
/// Exchange a bucket state for immutable references into the table.
438
390
/// Because the underlying reference to the table is also consumed,
439
391
/// no further changes to the structure of the table are possible;
440
392
/// in exchange for this, the returned references have a longer lifetime
441
393
/// than the references returned by `read()`.
442
394
pub fn into_refs ( self ) -> ( & ' t K , & ' t V ) {
443
- self . 0 . raw . into_refs ( )
395
+ unsafe { ( & ( * self . raw . kval ) . 0 , & ( * self . raw . kval ) . 1 ) }
444
396
}
445
397
}
446
398
447
399
impl < ' t , K , V , M : ' t > FullBucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > {
400
+ /// Gets mutable references to the key and value at a given index.
401
+ pub fn read_mut ( & mut self ) -> ( & mut SafeHash , & mut K , & mut V ) {
402
+ let ( & mut ref mut h, & mut ( ref mut k, ref mut v) ) = unsafe {
403
+ ( & mut * ( self . raw . hash as * mut SafeHash ) , & mut * self . raw . kval )
404
+ } ;
405
+ ( h, k, v)
406
+ }
407
+
448
408
/// This works similarly to `into_refs`, exchanging a bucket state
449
409
/// for mutable references into the table.
450
410
pub fn into_mut_refs ( self ) -> ( & ' t mut K , & ' t mut V ) {
451
- self . 0 . raw . into_mut_refs ( )
411
+ unsafe { ( & mut ( * self . raw . kval ) . 0 , & mut ( * self . raw . kval ) . 1 ) }
412
+ }
413
+
414
+ /// Removes this bucket's key and value from the hashtable.
415
+ ///
416
+ /// This works similarly to `put`, building an `EmptyBucket` out of the
417
+ /// taken bucket.
418
+ pub fn take ( mut self ) -> ( EmptyBucket < K , V , M > , K , V ) {
419
+ self . table . size -= 1 ;
420
+
421
+ unsafe {
422
+ * self . raw . hash = None ;
423
+ let ( k, v) = ptr:: read ( self . raw . kval ) ;
424
+ ( self . unsafe_cast ( ) , k, v)
425
+ }
452
426
}
453
427
}
454
428
@@ -460,19 +434,16 @@ impl<K, V, M> GapThenFull<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
460
434
461
435
pub fn shift ( mut self ) -> Option < GapThenFull < K , V , M > > {
462
436
unsafe {
463
- * self . gap . 0 . raw . hash = mem:: replace ( & mut * self . full . 0 . raw . hash , None ) ;
464
- copy_nonoverlapping_memory ( self . gap . 0 . raw . kval , self . full . 0 . raw . kval , 1 ) ;
437
+ * self . gap . raw . hash = mem:: replace ( & mut * self . full . raw . hash , None ) ;
438
+ copy_nonoverlapping_memory ( self . gap . raw . kval , self . full . raw . kval , 1 ) ;
465
439
}
466
440
467
- let Bucket ( BareBucket { raw : prev_raw, idx : prev_idx, .. } ) = self . full ;
441
+ let Bucket { raw : prev_raw, idx : prev_idx, .. } = self . full ;
468
442
469
443
match self . full . into_next ( ) . peek ( ) {
470
444
Full ( bucket) => {
471
- self . gap . 0 . raw = RawBucket {
472
- hash : prev_raw. hash ,
473
- kval : prev_raw. kval ,
474
- } ;
475
- self . gap . 0 . idx = prev_idx;
445
+ self . gap . raw = prev_raw;
446
+ self . gap . idx = prev_idx;
476
447
477
448
self . full = bucket;
478
449
@@ -485,27 +456,43 @@ impl<K, V, M> GapThenFull<K, V, M> where RawTable<K, V>: BorrowFrom<M> {
485
456
486
457
impl < K , V > RawTable < K , V > {
487
458
/// Does not initialize the buckets.
488
- unsafe fn new_uninitialized ( capacity : uint ) -> RawTable < K , V > {
489
- if capacity == 0 {
490
- return RawTable {
491
- size : 0 ,
492
- capacity : 0 ,
493
- middle : Unique :: null ( ) ,
494
- } ;
495
- }
459
+ pub fn new_uninitialized ( capacity : uint ) -> PartialRawTable < K , V > {
460
+ unsafe {
461
+ let table = if capacity == 0 {
462
+ RawTable {
463
+ size : 0 ,
464
+ capacity : 0 ,
465
+ middle : Unique :: null ( ) ,
466
+ }
467
+ } else {
468
+ let hashes = allocate ( checked_size_generic :: < K , V > ( capacity) , align :: < K , V > ( ) ) ;
469
+ if hashes. is_null ( ) { :: alloc:: oom ( ) }
496
470
497
- let hashes = allocate ( checked_size_generic :: < K , V > ( capacity) , align :: < K , V > ( ) ) ;
498
- if hashes. is_null ( ) { :: alloc:: oom ( ) }
471
+ RawTable {
472
+ capacity : capacity,
473
+ size : 0 ,
474
+ middle : Unique ( ( hashes as * mut ( K , V ) ) . offset ( capacity as isize ) ) ,
475
+ }
476
+ } ;
499
477
500
- RawTable {
501
- capacity : capacity,
502
- size : 0 ,
503
- middle : Unique ( ( hashes as * mut ( K , V ) ) . offset ( capacity as isize ) ) ,
478
+ PartialRawTable {
479
+ front : table. first_bucket_raw ( ) ,
480
+ back : table. first_bucket_raw ( ) ,
481
+ front_num : 0 ,
482
+ back_num : capacity,
483
+ table : table,
484
+ }
504
485
}
505
486
}
506
487
488
+ /// Creates a new raw table from a given capacity. All buckets are
489
+ /// initially empty.
490
+ pub fn new ( capacity : usize ) -> RawTable < K , V > {
491
+ RawTable :: new_uninitialized ( capacity) . unwrap ( )
492
+ }
493
+
507
494
#[ inline]
508
- unsafe fn first_bucket_raw < M > ( & self ) -> RawBucket < K , V , M > {
495
+ unsafe fn first_bucket_raw ( & self ) -> RawBucket < K , V > {
509
496
if self . capacity ( ) == 0 {
510
497
RawBucket {
511
498
hash : ptr:: null_mut ( ) ,
@@ -519,16 +506,6 @@ impl<K, V> RawTable<K, V> {
519
506
}
520
507
}
521
508
522
- /// Creates a new raw table from a given capacity. All buckets are
523
- /// initially empty.
524
- pub fn new ( capacity : usize ) -> RawTable < K , V > {
525
- unsafe {
526
- let table = RawTable :: new_uninitialized ( capacity) ;
527
- zero_memory ( table. middle . ptr as * mut Option < SafeHash > , capacity) ;
528
- table
529
- }
530
- }
531
-
532
509
pub fn grow_inplace ( & mut self , capacity : uint ) -> bool {
533
510
assert ! ( capacity. is_power_of_two( ) ) ;
534
511
assert ! ( capacity >= self . capacity) ;
@@ -580,13 +557,6 @@ impl<K, V> RawTable<K, V> {
580
557
pub fn size ( & self ) -> usize {
581
558
self . size
582
559
}
583
-
584
- pub fn into_iter ( self ) -> IntoIter < K , V > {
585
- // Replace the marker regardless of lifetime bounds on parameters.
586
- IntoIter {
587
- iter : Bucket :: raw_full_buckets ( self ) ,
588
- }
589
- }
590
560
}
591
561
592
562
/// Rounds up to a multiple of a power of two. Returns the closest multiple
@@ -631,26 +601,24 @@ fn align<K, V>() -> usize {
631
601
}
632
602
633
603
/// A newtyped RawBucket. Not copyable.
634
- pub struct RawFullBucket < K , V , M > ( RawBucket < K , V , M > ) ;
604
+ pub struct RawFullBucket < K , V , M > ( RawBucket < K , V > ) ;
635
605
636
- impl < K , V , M > Deref for RawFullBucket < K , V , M > {
637
- type Target = RawBucket < K , V , M > ;
638
-
639
- fn deref ( & self ) -> & RawBucket < K , V , M > {
640
- & self . 0
606
+ impl < ' t , K , V , M : ' t > RawFullBucket < K , V , M > where RawTable < K , V > : BorrowFrom < M > {
607
+ pub fn into_refs ( self ) -> ( & ' t K , & ' t V ) {
608
+ unsafe { ( & ( * self . 0 . kval ) . 0 , & ( * self . 0 . kval ) . 1 ) }
641
609
}
642
610
}
643
611
644
- impl < K , V , M > DerefMut for RawFullBucket < K , V , M > {
645
- fn deref_mut ( & mut self ) -> & mut RawBucket < K , V , M > {
646
- & mut self . 0
612
+ impl < ' t , K , V , M : ' t > RawFullBucket < K , V , M > where RawTable < K , V > : BorrowFromMut < M > {
613
+ pub fn into_mut_refs ( self ) -> ( & ' t mut K , & ' t mut V ) {
614
+ unsafe { ( & mut ( * self . 0 . kval ) . 0 , & mut ( * self . 0 . kval ) . 1 ) }
647
615
}
648
616
}
649
617
650
618
/// A raw iterator. The basis for some other iterators in this module. Although
651
619
/// this interface is safe, it's not used outside this module.
652
620
pub struct RawFullBuckets < K , V , M > {
653
- raw : RawBucket < K , V , M > ,
621
+ raw : RawBucket < K , V > ,
654
622
hashes_end : * mut Option < SafeHash > ,
655
623
table : TableRef < M > ,
656
624
}
@@ -685,99 +653,100 @@ impl<K, V, M> Iterator for RawFullBuckets<K, V, M> {
685
653
}
686
654
}
687
655
688
- /// Iterator over the entries in a table, consuming the table.
689
- pub struct IntoIter < K , V > {
690
- iter : RawFullBuckets < K , V , RawTable < K , V > >
691
- }
692
-
693
- impl < K , V > Iterator for IntoIter < K , V > {
694
- type Item = ( SafeHash , K , V ) ;
695
-
696
- fn next ( & mut self ) -> Option < ( SafeHash , K , V ) > {
697
- self . iter . next ( ) . map ( |bucket| {
698
- self . iter . table . size -= 1 ;
699
- unsafe {
700
- let ( k , v ) = ptr:: read ( bucket. kval ) ;
701
- ( * ( bucket . hash as * mut SafeHash ) , k , v )
656
+ # [ unsafe_destructor ]
657
+ impl < K , V > Drop for RawTable < K , V > {
658
+ fn drop ( & mut self ) {
659
+ if self . middle . ptr . is_null ( ) {
660
+ return ;
661
+ }
662
+ // Check if the size is 0, so we don't do a useless scan when
663
+ // dropping empty tables such as on resize.
664
+ // Avoid double drop of elements that have been already moved out.
665
+ unsafe {
666
+ if self . size != 0 {
667
+ for bucket in Bucket :: raw_full_buckets ( & mut * self ) {
668
+ ptr:: read ( bucket. 0 . kval ) ;
669
+ }
702
670
}
703
- } )
704
- }
705
671
706
- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
707
- let size = self . iter . table . size ( ) ;
708
- ( size , Some ( size ) )
672
+ let ptr = self . middle . ptr . offset ( - ( self . capacity as isize ) ) as * mut u8 ;
673
+ deallocate ( ptr , size_generic :: < K , V > ( self . capacity ) , align :: < K , V > ( ) ) ;
674
+ }
709
675
}
710
676
}
711
- impl < K , V > ExactSizeIterator for IntoIter < K , V > {
712
- fn len ( & self ) -> usize { self . iter . table . size ( ) }
713
- }
714
677
715
- #[ unsafe_destructor]
716
- impl < K , V > Drop for IntoIter < K , V > {
717
- fn drop ( & mut self ) {
718
- for _ in self { }
719
- }
678
+ pub struct PartialRawTable < K , V > {
679
+ table : RawTable < K , V > ,
680
+ front : RawBucket < K , V > ,
681
+ back : RawBucket < K , V > ,
682
+ front_num : usize ,
683
+ back_num : usize ,
720
684
}
721
685
722
- impl < K : Clone , V : Clone > Clone for RawTable < K , V > {
723
- fn clone ( & self ) -> RawTable < K , V > {
686
+ impl < K , V > PartialRawTable < K , V > {
687
+ pub fn new ( table : RawTable < K , V > ) -> PartialRawTable < K , V > {
724
688
unsafe {
725
- let mut new_ht = RawTable :: new_uninitialized ( self . capacity ( ) ) ;
689
+ PartialRawTable {
690
+ front : table. first_bucket_raw ( ) ,
691
+ back : table. first_bucket_raw ( ) . offset ( table. capacity ( ) as isize ) ,
692
+ front_num : 0 ,
693
+ back_num : 0 ,
694
+ table : table,
695
+ }
696
+ }
697
+ }
726
698
727
- {
728
- let cap = self . capacity ( ) ;
729
- let mut buckets = if let Ok ( buckets) = Bucket :: at_index ( self , 0 ) {
730
- buckets
699
+ pub fn push_back ( & mut self , bucket : Option < ( SafeHash , K , V ) > ) {
700
+ unsafe {
701
+ if self . back_num != 0 {
702
+ self . back_num -= 1 ;
703
+ let back = ptr:: replace ( & mut self . back , self . back . offset ( 1 ) ) ;
704
+ if let Some ( ( h, k, v) ) = bucket {
705
+ * back. hash = Some ( h) ;
706
+ ptr:: write ( back. kval , ( k, v) ) ;
707
+ self . table . size += 1 ;
731
708
} else {
732
- return new_ht;
733
- } ;
734
- let mut new_buckets = Bucket :: at_index ( & mut new_ht, 0 ) . ok ( ) . unwrap ( ) ;
735
- while buckets. index ( ) != cap {
736
- match buckets. peek ( ) {
737
- Full ( full) => {
738
- let ( h, k, v) = {
739
- let ( h, k, v) = full. read ( ) ;
740
- ( * h, k. clone ( ) , v. clone ( ) )
741
- } ;
742
- * new_buckets. 0 . raw . hash = Some ( h) ;
743
- ptr:: write ( new_buckets. 0 . raw . kval , ( k, v) ) ;
744
- }
745
- Empty ( ..) => {
746
- * new_buckets. 0 . raw . hash = None ;
747
- }
748
- }
749
- new_buckets. next ( ) ;
750
- buckets. next ( ) ;
709
+ * back. hash = None ;
751
710
}
752
- } ;
753
-
754
- new_ht. size = self . size ( ) ;
755
-
756
- new_ht
711
+ }
757
712
}
758
713
}
759
- }
760
714
761
- #[ unsafe_destructor]
762
- impl < K , V > Drop for RawTable < K , V > {
763
- fn drop ( & mut self ) {
764
- if self . middle . ptr . is_null ( ) {
765
- return ;
766
- }
767
- // Check if the size is 0, so we don't do a useless scan when
768
- // dropping empty tables such as on resize.
769
- // Avoid double drop of elements that have been already moved out.
715
+ pub fn take_front ( & mut self ) -> Option < ( SafeHash , K , V ) > {
770
716
unsafe {
771
- if self . size != 0 {
772
- for bucket in Bucket :: raw_full_buckets ( & mut * self ) {
773
- ptr:: read ( bucket. kval ) ;
717
+ while self . front . hash != self . back . hash {
718
+ self . front_num += 1 ;
719
+ let front = ptr:: replace ( & mut self . front , self . front . offset ( 1 ) ) ;
720
+ if let Some ( h) = * front. hash {
721
+ self . table . size -= 1 ;
722
+ let ( k, v) = ptr:: read ( front. kval ) ;
723
+ return Some ( ( h, k, v) ) ;
774
724
}
775
725
}
776
726
}
777
727
728
+ None
729
+ }
730
+
731
+ pub fn unwrap ( self ) -> RawTable < K , V > {
778
732
unsafe {
779
- let ptr = self . middle . ptr . offset ( -( self . capacity as isize ) ) as * mut u8 ;
780
- deallocate ( ptr, size_generic :: < K , V > ( self . capacity ) , align :: < K , V > ( ) ) ;
733
+ zero_memory ( self . table . first_bucket_raw ( ) . hash , self . front_num ) ;
734
+ zero_memory ( self . back . hash , self . back_num ) ;
735
+ let table = ptr:: read ( & self . table ) ;
736
+ mem:: forget ( self ) ;
737
+ table
781
738
}
782
739
}
740
+
741
+ pub fn size ( & self ) -> usize {
742
+ self . table . size ( )
743
+ }
744
+ }
745
+
746
+ #[ unsafe_destructor]
747
+ impl < K , V > Drop for PartialRawTable < K , V > {
748
+ fn drop ( & mut self ) {
749
+ while let Some ( _) = self . take_front ( ) { }
750
+ debug_assert_eq ! ( self . table. size, 0 ) ;
751
+ }
783
752
}
0 commit comments