Coverage Report

Created: 2025-07-01 06:04

/rust/registry/src/index.crates.io-6f17d22bba15001f/hashbrown-0.15.4/src/table.rs
Line
Count
Source (jump to first uncovered line)
1
use core::{fmt, iter::FusedIterator, marker::PhantomData};
2
3
use crate::{
4
    raw::{
5
        Allocator, Bucket, Global, InsertSlot, RawDrain, RawExtractIf, RawIntoIter, RawIter,
6
        RawIterHash, RawTable,
7
    },
8
    TryReserveError,
9
};
10
11
/// Low-level hash table with explicit hashing.
12
///
13
/// The primary use case for this type over [`HashMap`] or [`HashSet`] is to
14
/// support types that do not implement the [`Hash`] and [`Eq`] traits, but
15
/// instead require additional data not contained in the key itself to compute a
16
/// hash and compare two elements for equality.
17
///
18
/// Examples of when this can be useful include:
19
/// - An `IndexMap` implementation where indices into a `Vec` are stored as
20
///   elements in a `HashTable<usize>`. Hashing and comparing the elements
21
///   requires indexing the associated `Vec` to get the actual value referred to
22
///   by the index.
23
/// - Avoiding re-computing a hash when it is already known.
24
/// - Mutating the key of an element in a way that doesn't affect its hash.
25
///
26
/// To achieve this, `HashTable` methods that search for an element in the table
27
/// require a hash value and equality function to be explicitly passed in as
28
/// arguments. The method will then iterate over the elements with the given
29
/// hash and call the equality function on each of them, until a match is found.
30
///
31
/// In most cases, a `HashTable` will not be exposed directly in an API. It will
32
/// instead be wrapped in a helper type which handles the work of calculating
33
/// hash values and comparing elements.
34
///
35
/// Due to its low-level nature, this type provides fewer guarantees than
36
/// [`HashMap`] and [`HashSet`]. Specifically, the API allows you to shoot
37
/// yourself in the foot by having multiple elements with identical keys in the
38
/// table. The table itself will still function correctly and lookups will
39
/// arbitrarily return one of the matching elements. However you should avoid
40
/// doing this because it changes the runtime of hash table operations from
41
/// `O(1)` to `O(k)` where `k` is the number of duplicate entries.
42
///
43
/// [`HashMap`]: super::HashMap
44
/// [`HashSet`]: super::HashSet
45
/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
46
/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
47
pub struct HashTable<T, A = Global>
48
where
49
    A: Allocator,
50
{
51
    pub(crate) raw: RawTable<T, A>,
52
}
53
54
impl<T> HashTable<T, Global> {
55
    /// Creates an empty `HashTable`.
56
    ///
57
    /// The hash table is initially created with a capacity of 0, so it will not allocate until it
58
    /// is first inserted into.
59
    ///
60
    /// # Examples
61
    ///
62
    /// ```
63
    /// use hashbrown::HashTable;
64
    /// let mut table: HashTable<&str> = HashTable::new();
65
    /// assert_eq!(table.len(), 0);
66
    /// assert_eq!(table.capacity(), 0);
67
    /// ```
68
0
    pub const fn new() -> Self {
69
0
        Self {
70
0
            raw: RawTable::new(),
71
0
        }
72
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::new
Unexecuted instantiation: <hashbrown::table::HashTable<_>>::new
73
74
    /// Creates an empty `HashTable` with the specified capacity.
75
    ///
76
    /// The hash table will be able to hold at least `capacity` elements without
77
    /// reallocating. If `capacity` is 0, the hash table will not allocate.
78
    ///
79
    /// # Examples
80
    ///
81
    /// ```
82
    /// use hashbrown::HashTable;
83
    /// let mut table: HashTable<&str> = HashTable::with_capacity(10);
84
    /// assert_eq!(table.len(), 0);
85
    /// assert!(table.capacity() >= 10);
86
    /// ```
87
0
    pub fn with_capacity(capacity: usize) -> Self {
88
0
        Self {
89
0
            raw: RawTable::with_capacity(capacity),
90
0
        }
91
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::with_capacity
Unexecuted instantiation: <hashbrown::table::HashTable<_>>::with_capacity
92
}
93
94
impl<T, A> HashTable<T, A>
95
where
96
    A: Allocator,
97
{
98
    /// Creates an empty `HashTable` using the given allocator.
99
    ///
100
    /// The hash table is initially created with a capacity of 0, so it will not allocate until it
101
    /// is first inserted into.
102
    ///
103
    /// # Examples
104
    ///
105
    /// ```
106
    /// # #[cfg(feature = "nightly")]
107
    /// # fn test() {
108
    /// use bumpalo::Bump;
109
    /// use hashbrown::{HashTable, DefaultHashBuilder};
110
    /// use std::hash::BuildHasher;
111
    ///
112
    /// let bump = Bump::new();
113
    /// let mut table = HashTable::new_in(&bump);
114
    /// let hasher = DefaultHashBuilder::default();
115
    /// let hasher = |val: &_| hasher.hash_one(val);
116
    ///
117
    /// // The created HashTable holds none elements
118
    /// assert_eq!(table.len(), 0);
119
    ///
120
    /// // The created HashTable also doesn't allocate memory
121
    /// assert_eq!(table.capacity(), 0);
122
    ///
123
    /// // Now we insert element inside created HashTable
124
    /// table.insert_unique(hasher(&"One"), "One", hasher);
125
    /// // We can see that the HashTable holds 1 element
126
    /// assert_eq!(table.len(), 1);
127
    /// // And it also allocates some capacity
128
    /// assert!(table.capacity() > 1);
129
    /// # }
130
    /// # fn main() {
131
    /// #     #[cfg(feature = "nightly")]
132
    /// #     test()
133
    /// # }
134
    /// ```
135
0
    pub const fn new_in(alloc: A) -> Self {
136
0
        Self {
137
0
            raw: RawTable::new_in(alloc),
138
0
        }
139
0
    }
140
141
    /// Creates an empty `HashTable` with the specified capacity using the given allocator.
142
    ///
143
    /// The hash table will be able to hold at least `capacity` elements without
144
    /// reallocating. If `capacity` is 0, the hash table will not allocate.
145
    ///
146
    /// # Examples
147
    ///
148
    /// ```
149
    /// # #[cfg(feature = "nightly")]
150
    /// # fn test() {
151
    /// use bumpalo::Bump;
152
    /// use hashbrown::{HashTable, DefaultHashBuilder};
153
    /// use std::hash::BuildHasher;
154
    ///
155
    /// let bump = Bump::new();
156
    /// let mut table = HashTable::with_capacity_in(5, &bump);
157
    /// let hasher = DefaultHashBuilder::default();
158
    /// let hasher = |val: &_| hasher.hash_one(val);
159
    ///
160
    /// // The created HashTable holds none elements
161
    /// assert_eq!(table.len(), 0);
162
    /// // But it can hold at least 5 elements without reallocating
163
    /// let empty_map_capacity = table.capacity();
164
    /// assert!(empty_map_capacity >= 5);
165
    ///
166
    /// // Now we insert some 5 elements inside created HashTable
167
    /// table.insert_unique(hasher(&"One"), "One", hasher);
168
    /// table.insert_unique(hasher(&"Two"), "Two", hasher);
169
    /// table.insert_unique(hasher(&"Three"), "Three", hasher);
170
    /// table.insert_unique(hasher(&"Four"), "Four", hasher);
171
    /// table.insert_unique(hasher(&"Five"), "Five", hasher);
172
    ///
173
    /// // We can see that the HashTable holds 5 elements
174
    /// assert_eq!(table.len(), 5);
175
    /// // But its capacity isn't changed
176
    /// assert_eq!(table.capacity(), empty_map_capacity)
177
    /// # }
178
    /// # fn main() {
179
    /// #     #[cfg(feature = "nightly")]
180
    /// #     test()
181
    /// # }
182
    /// ```
183
0
    pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
184
0
        Self {
185
0
            raw: RawTable::with_capacity_in(capacity, alloc),
186
0
        }
187
0
    }
188
189
    /// Returns a reference to the underlying allocator.
190
0
    pub fn allocator(&self) -> &A {
191
0
        self.raw.allocator()
192
0
    }
193
194
    /// Returns a reference to an entry in the table with the given hash and
195
    /// which satisfies the equality function passed.
196
    ///
197
    /// This method will call `eq` for all entries with the given hash, but may
198
    /// also call it for entries with a different hash. `eq` should only return
199
    /// true for the desired entry, at which point the search is stopped.
200
    ///
201
    /// # Examples
202
    ///
203
    /// ```
204
    /// # #[cfg(feature = "nightly")]
205
    /// # fn test() {
206
    /// use hashbrown::{HashTable, DefaultHashBuilder};
207
    /// use std::hash::BuildHasher;
208
    ///
209
    /// let mut table = HashTable::new();
210
    /// let hasher = DefaultHashBuilder::default();
211
    /// let hasher = |val: &_| hasher.hash_one(val);
212
    /// table.insert_unique(hasher(&1), 1, hasher);
213
    /// table.insert_unique(hasher(&2), 2, hasher);
214
    /// table.insert_unique(hasher(&3), 3, hasher);
215
    /// assert_eq!(table.find(hasher(&2), |&val| val == 2), Some(&2));
216
    /// assert_eq!(table.find(hasher(&4), |&val| val == 4), None);
217
    /// # }
218
    /// # fn main() {
219
    /// #     #[cfg(feature = "nightly")]
220
    /// #     test()
221
    /// # }
222
    /// ```
223
0
    pub fn find(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> {
224
0
        self.raw.get(hash, eq)
225
0
    }
226
227
    /// Returns a mutable reference to an entry in the table with the given hash
228
    /// and which satisfies the equality function passed.
229
    ///
230
    /// This method will call `eq` for all entries with the given hash, but may
231
    /// also call it for entries with a different hash. `eq` should only return
232
    /// true for the desired entry, at which point the search is stopped.
233
    ///
234
    /// When mutating an entry, you should ensure that it still retains the same
235
    /// hash value as when it was inserted, otherwise lookups of that entry may
236
    /// fail to find it.
237
    ///
238
    /// # Examples
239
    ///
240
    /// ```
241
    /// # #[cfg(feature = "nightly")]
242
    /// # fn test() {
243
    /// use hashbrown::{HashTable, DefaultHashBuilder};
244
    /// use std::hash::BuildHasher;
245
    ///
246
    /// let mut table = HashTable::new();
247
    /// let hasher = DefaultHashBuilder::default();
248
    /// let hasher = |val: &_| hasher.hash_one(val);
249
    /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
250
    /// if let Some(val) = table.find_mut(hasher(&1), |val| val.0 == 1) {
251
    ///     val.1 = "b";
252
    /// }
253
    /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), Some(&(1, "b")));
254
    /// assert_eq!(table.find(hasher(&2), |val| val.0 == 2), None);
255
    /// # }
256
    /// # fn main() {
257
    /// #     #[cfg(feature = "nightly")]
258
    /// #     test()
259
    /// # }
260
    /// ```
261
0
    pub fn find_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> {
262
0
        self.raw.get_mut(hash, eq)
263
0
    }
264
265
    /// Returns an `OccupiedEntry` for an entry in the table with the given hash
266
    /// and which satisfies the equality function passed.
267
    ///
268
    /// This can be used to remove the entry from the table. Call
269
    /// [`HashTable::entry`] instead if you wish to insert an entry if the
270
    /// lookup fails.
271
    ///
272
    /// This method will call `eq` for all entries with the given hash, but may
273
    /// also call it for entries with a different hash. `eq` should only return
274
    /// true for the desired entry, at which point the search is stopped.
275
    ///
276
    /// # Examples
277
    ///
278
    /// ```
279
    /// # #[cfg(feature = "nightly")]
280
    /// # fn test() {
281
    /// use hashbrown::{HashTable, DefaultHashBuilder};
282
    /// use std::hash::BuildHasher;
283
    ///
284
    /// let mut table = HashTable::new();
285
    /// let hasher = DefaultHashBuilder::default();
286
    /// let hasher = |val: &_| hasher.hash_one(val);
287
    /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
288
    /// if let Ok(entry) = table.find_entry(hasher(&1), |val| val.0 == 1) {
289
    ///     entry.remove();
290
    /// }
291
    /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), None);
292
    /// # }
293
    /// # fn main() {
294
    /// #     #[cfg(feature = "nightly")]
295
    /// #     test()
296
    /// # }
297
    /// ```
298
    #[cfg_attr(feature = "inline-more", inline)]
299
0
    pub fn find_entry(
300
0
        &mut self,
301
0
        hash: u64,
302
0
        eq: impl FnMut(&T) -> bool,
303
0
    ) -> Result<OccupiedEntry<'_, T, A>, AbsentEntry<'_, T, A>> {
304
0
        match self.raw.find(hash, eq) {
305
0
            Some(bucket) => Ok(OccupiedEntry {
306
0
                hash,
307
0
                bucket,
308
0
                table: self,
309
0
            }),
310
0
            None => Err(AbsentEntry { table: self }),
311
        }
312
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::find_entry::<indexmap::map::core::equivalent<(gimli::write::line::LineString, gimli::write::line::DirectoryId), gimli::write::line::FileInfo, (gimli::write::line::LineString, gimli::write::line::DirectoryId)>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<_, _>>::find_entry::<_>
313
314
    /// Returns an `Entry` for an entry in the table with the given hash
315
    /// and which satisfies the equality function passed.
316
    ///
317
    /// This can be used to remove the entry from the table, or insert a new
318
    /// entry with the given hash if one doesn't already exist.
319
    ///
320
    /// This method will call `eq` for all entries with the given hash, but may
321
    /// also call it for entries with a different hash. `eq` should only return
322
    /// true for the desired entry, at which point the search is stopped.
323
    ///
324
    /// This method may grow the table in preparation for an insertion. Call
325
    /// [`HashTable::find_entry`] if this is undesirable.
326
    ///
327
    /// `hasher` is called if entries need to be moved or copied to a new table.
328
    /// This must return the same hash value that each entry was inserted with.
329
    ///
330
    /// # Examples
331
    ///
332
    /// ```
333
    /// # #[cfg(feature = "nightly")]
334
    /// # fn test() {
335
    /// use hashbrown::hash_table::Entry;
336
    /// use hashbrown::{HashTable, DefaultHashBuilder};
337
    /// use std::hash::BuildHasher;
338
    ///
339
    /// let mut table = HashTable::new();
340
    /// let hasher = DefaultHashBuilder::default();
341
    /// let hasher = |val: &_| hasher.hash_one(val);
342
    /// table.insert_unique(hasher(&1), (1, "a"), |val| hasher(&val.0));
343
    /// if let Entry::Occupied(entry) = table.entry(hasher(&1), |val| val.0 == 1, |val| hasher(&val.0))
344
    /// {
345
    ///     entry.remove();
346
    /// }
347
    /// if let Entry::Vacant(entry) = table.entry(hasher(&2), |val| val.0 == 2, |val| hasher(&val.0)) {
348
    ///     entry.insert((2, "b"));
349
    /// }
350
    /// assert_eq!(table.find(hasher(&1), |val| val.0 == 1), None);
351
    /// assert_eq!(table.find(hasher(&2), |val| val.0 == 2), Some(&(2, "b")));
352
    /// # }
353
    /// # fn main() {
354
    /// #     #[cfg(feature = "nightly")]
355
    /// #     test()
356
    /// # }
357
    /// ```
358
    #[cfg_attr(feature = "inline-more", inline)]
359
0
    pub fn entry(
360
0
        &mut self,
361
0
        hash: u64,
362
0
        eq: impl FnMut(&T) -> bool,
363
0
        hasher: impl Fn(&T) -> u64,
364
0
    ) -> Entry<'_, T, A> {
365
0
        match self.raw.find_or_find_insert_slot(hash, eq, hasher) {
366
0
            Ok(bucket) => Entry::Occupied(OccupiedEntry {
367
0
                hash,
368
0
                bucket,
369
0
                table: self,
370
0
            }),
371
0
            Err(insert_slot) => Entry::Vacant(VacantEntry {
372
0
                hash,
373
0
                insert_slot,
374
0
                table: self,
375
0
            }),
376
        }
377
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<gimli::write::cfi::CommonInformationEntry, (), gimli::write::cfi::CommonInformationEntry>::{closure#0}, indexmap::map::core::get_hash<gimli::write::cfi::CommonInformationEntry, ()>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<gimli::write::loc::LocationList, (), gimli::write::loc::LocationList>::{closure#0}, indexmap::map::core::get_hash<gimli::write::loc::LocationList, ()>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<gimli::write::line::LineString, (), gimli::write::line::LineString>::{closure#0}, indexmap::map::core::get_hash<gimli::write::line::LineString, ()>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<gimli::write::range::RangeList, (), gimli::write::range::RangeList>::{closure#0}, indexmap::map::core::get_hash<gimli::write::range::RangeList, ()>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<gimli::write::abbrev::Abbreviation, (), gimli::write::abbrev::Abbreviation>::{closure#0}, indexmap::map::core::get_hash<gimli::write::abbrev::Abbreviation, ()>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::entry::<indexmap::map::core::equivalent<(gimli::write::line::LineString, gimli::write::line::DirectoryId), gimli::write::line::FileInfo, (gimli::write::line::LineString, gimli::write::line::DirectoryId)>::{closure#0}, indexmap::map::core::get_hash<(gimli::write::line::LineString, gimli::write::line::DirectoryId), gimli::write::line::FileInfo>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<_, _>>::entry::<_, _>
378
379
    /// Inserts an element into the `HashTable` with the given hash value, but
380
    /// without checking whether an equivalent element already exists within the
381
    /// table.
382
    ///
383
    /// `hasher` is called if entries need to be moved or copied to a new table.
384
    /// This must return the same hash value that each entry was inserted with.
385
    ///
386
    /// # Examples
387
    ///
388
    /// ```
389
    /// # #[cfg(feature = "nightly")]
390
    /// # fn test() {
391
    /// use hashbrown::{HashTable, DefaultHashBuilder};
392
    /// use std::hash::BuildHasher;
393
    ///
394
    /// let mut v = HashTable::new();
395
    /// let hasher = DefaultHashBuilder::default();
396
    /// let hasher = |val: &_| hasher.hash_one(val);
397
    /// v.insert_unique(hasher(&1), 1, hasher);
398
    /// # }
399
    /// # fn main() {
400
    /// #     #[cfg(feature = "nightly")]
401
    /// #     test()
402
    /// # }
403
    /// ```
404
0
    pub fn insert_unique(
405
0
        &mut self,
406
0
        hash: u64,
407
0
        value: T,
408
0
        hasher: impl Fn(&T) -> u64,
409
0
    ) -> OccupiedEntry<'_, T, A> {
410
0
        let bucket = self.raw.insert(hash, value, hasher);
411
0
        OccupiedEntry {
412
0
            hash,
413
0
            bucket,
414
0
            table: self,
415
0
        }
416
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::insert_unique::<indexmap::map::core::get_hash<(gimli::write::line::LineString, gimli::write::line::DirectoryId), gimli::write::line::FileInfo>::{closure#0}>
Unexecuted instantiation: <hashbrown::table::HashTable<_, _>>::insert_unique::<_>
417
418
    /// Clears the table, removing all values.
419
    ///
420
    /// # Examples
421
    ///
422
    /// ```
423
    /// # #[cfg(feature = "nightly")]
424
    /// # fn test() {
425
    /// use hashbrown::{HashTable, DefaultHashBuilder};
426
    /// use std::hash::BuildHasher;
427
    ///
428
    /// let mut v = HashTable::new();
429
    /// let hasher = DefaultHashBuilder::default();
430
    /// let hasher = |val: &_| hasher.hash_one(val);
431
    /// v.insert_unique(hasher(&1), 1, hasher);
432
    /// v.clear();
433
    /// assert!(v.is_empty());
434
    /// # }
435
    /// # fn main() {
436
    /// #     #[cfg(feature = "nightly")]
437
    /// #     test()
438
    /// # }
439
    /// ```
440
0
    pub fn clear(&mut self) {
441
0
        self.raw.clear();
442
0
    }
443
444
    /// Shrinks the capacity of the table as much as possible. It will drop
445
    /// down as much as possible while maintaining the internal rules
446
    /// and possibly leaving some space in accordance with the resize policy.
447
    ///
448
    /// `hasher` is called if entries need to be moved or copied to a new table.
449
    /// This must return the same hash value that each entry was inserted with.
450
    ///
451
    /// # Examples
452
    ///
453
    /// ```
454
    /// # #[cfg(feature = "nightly")]
455
    /// # fn test() {
456
    /// use hashbrown::{HashTable, DefaultHashBuilder};
457
    /// use std::hash::BuildHasher;
458
    ///
459
    /// let mut table = HashTable::with_capacity(100);
460
    /// let hasher = DefaultHashBuilder::default();
461
    /// let hasher = |val: &_| hasher.hash_one(val);
462
    /// table.insert_unique(hasher(&1), 1, hasher);
463
    /// table.insert_unique(hasher(&2), 2, hasher);
464
    /// assert!(table.capacity() >= 100);
465
    /// table.shrink_to_fit(hasher);
466
    /// assert!(table.capacity() >= 2);
467
    /// # }
468
    /// # fn main() {
469
    /// #     #[cfg(feature = "nightly")]
470
    /// #     test()
471
    /// # }
472
    /// ```
473
0
    pub fn shrink_to_fit(&mut self, hasher: impl Fn(&T) -> u64) {
474
0
        self.raw.shrink_to(self.len(), hasher)
475
0
    }
476
477
    /// Shrinks the capacity of the table with a lower limit. It will drop
478
    /// down no lower than the supplied limit while maintaining the internal rules
479
    /// and possibly leaving some space in accordance with the resize policy.
480
    ///
481
    /// `hasher` is called if entries need to be moved or copied to a new table.
482
    /// This must return the same hash value that each entry was inserted with.
483
    ///
484
    /// Panics if the current capacity is smaller than the supplied
485
    /// minimum capacity.
486
    ///
487
    /// # Examples
488
    ///
489
    /// ```
490
    /// # #[cfg(feature = "nightly")]
491
    /// # fn test() {
492
    /// use hashbrown::{HashTable, DefaultHashBuilder};
493
    /// use std::hash::BuildHasher;
494
    ///
495
    /// let mut table = HashTable::with_capacity(100);
496
    /// let hasher = DefaultHashBuilder::default();
497
    /// let hasher = |val: &_| hasher.hash_one(val);
498
    /// table.insert_unique(hasher(&1), 1, hasher);
499
    /// table.insert_unique(hasher(&2), 2, hasher);
500
    /// assert!(table.capacity() >= 100);
501
    /// table.shrink_to(10, hasher);
502
    /// assert!(table.capacity() >= 10);
503
    /// table.shrink_to(0, hasher);
504
    /// assert!(table.capacity() >= 2);
505
    /// # }
506
    /// # fn main() {
507
    /// #     #[cfg(feature = "nightly")]
508
    /// #     test()
509
    /// # }
510
    /// ```
511
0
    pub fn shrink_to(&mut self, min_capacity: usize, hasher: impl Fn(&T) -> u64) {
512
0
        self.raw.shrink_to(min_capacity, hasher);
513
0
    }
514
515
    /// Reserves capacity for at least `additional` more elements to be inserted
516
    /// in the `HashTable`. The collection may reserve more space to avoid
517
    /// frequent reallocations.
518
    ///
519
    /// `hasher` is called if entries need to be moved or copied to a new table.
520
    /// This must return the same hash value that each entry was inserted with.
521
    ///
522
    /// # Panics
523
    ///
524
    /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
525
    /// in case of allocation error. Use [`try_reserve`](HashTable::try_reserve) instead
526
    /// if you want to handle memory allocation failure.
527
    ///
528
    /// [`isize::MAX`]: https://doc.rust-lang.org/std/primitive.isize.html
529
    /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
530
    ///
531
    /// # Examples
532
    ///
533
    /// ```
534
    /// # #[cfg(feature = "nightly")]
535
    /// # fn test() {
536
    /// use hashbrown::{HashTable, DefaultHashBuilder};
537
    /// use std::hash::BuildHasher;
538
    ///
539
    /// let mut table: HashTable<i32> = HashTable::new();
540
    /// let hasher = DefaultHashBuilder::default();
541
    /// let hasher = |val: &_| hasher.hash_one(val);
542
    /// table.reserve(10, hasher);
543
    /// assert!(table.capacity() >= 10);
544
    /// # }
545
    /// # fn main() {
546
    /// #     #[cfg(feature = "nightly")]
547
    /// #     test()
548
    /// # }
549
    /// ```
550
0
    pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
551
0
        self.raw.reserve(additional, hasher)
552
0
    }
553
554
    /// Tries to reserve capacity for at least `additional` more elements to be inserted
555
    /// in the given `HashTable`. The collection may reserve more space to avoid
556
    /// frequent reallocations.
557
    ///
558
    /// `hasher` is called if entries need to be moved or copied to a new table.
559
    /// This must return the same hash value that each entry was inserted with.
560
    ///
561
    /// # Errors
562
    ///
563
    /// If the capacity overflows, or the allocator reports a failure, then an error
564
    /// is returned.
565
    ///
566
    /// # Examples
567
    ///
568
    /// ```
569
    /// # #[cfg(feature = "nightly")]
570
    /// # fn test() {
571
    /// use hashbrown::{HashTable, DefaultHashBuilder};
572
    /// use std::hash::BuildHasher;
573
    ///
574
    /// let mut table: HashTable<i32> = HashTable::new();
575
    /// let hasher = DefaultHashBuilder::default();
576
    /// let hasher = |val: &_| hasher.hash_one(val);
577
    /// table
578
    ///     .try_reserve(10, hasher)
579
    ///     .expect("why is the test harness OOMing on 10 bytes?");
580
    /// # }
581
    /// # fn main() {
582
    /// #     #[cfg(feature = "nightly")]
583
    /// #     test()
584
    /// # }
585
    /// ```
586
0
    pub fn try_reserve(
587
0
        &mut self,
588
0
        additional: usize,
589
0
        hasher: impl Fn(&T) -> u64,
590
0
    ) -> Result<(), TryReserveError> {
591
0
        self.raw.try_reserve(additional, hasher)
592
0
    }
593
594
    /// Returns the number of elements the table can hold without reallocating.
595
    ///
596
    /// # Examples
597
    ///
598
    /// ```
599
    /// use hashbrown::HashTable;
600
    /// let table: HashTable<i32> = HashTable::with_capacity(100);
601
    /// assert!(table.capacity() >= 100);
602
    /// ```
603
0
    pub fn capacity(&self) -> usize {
604
0
        self.raw.capacity()
605
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::capacity
Unexecuted instantiation: <hashbrown::table::HashTable<_, _>>::capacity
606
607
    /// Returns the number of elements in the table.
608
    ///
609
    /// # Examples
610
    ///
611
    /// ```
612
    /// # #[cfg(feature = "nightly")]
613
    /// # fn test() {
614
    /// use hashbrown::{HashTable, DefaultHashBuilder};
615
    /// use std::hash::BuildHasher;
616
    ///
617
    /// let hasher = DefaultHashBuilder::default();
618
    /// let hasher = |val: &_| hasher.hash_one(val);
619
    /// let mut v = HashTable::new();
620
    /// assert_eq!(v.len(), 0);
621
    /// v.insert_unique(hasher(&1), 1, hasher);
622
    /// assert_eq!(v.len(), 1);
623
    /// # }
624
    /// # fn main() {
625
    /// #     #[cfg(feature = "nightly")]
626
    /// #     test()
627
    /// # }
628
    /// ```
629
0
    pub fn len(&self) -> usize {
630
0
        self.raw.len()
631
0
    }
Unexecuted instantiation: <hashbrown::table::HashTable<usize>>::len
Unexecuted instantiation: <hashbrown::table::HashTable<_, _>>::len
632
633
    /// Returns `true` if the set contains no elements.
634
    ///
635
    /// # Examples
636
    ///
637
    /// ```
638
    /// # #[cfg(feature = "nightly")]
639
    /// # fn test() {
640
    /// use hashbrown::{HashTable, DefaultHashBuilder};
641
    /// use std::hash::BuildHasher;
642
    ///
643
    /// let hasher = DefaultHashBuilder::default();
644
    /// let hasher = |val: &_| hasher.hash_one(val);
645
    /// let mut v = HashTable::new();
646
    /// assert!(v.is_empty());
647
    /// v.insert_unique(hasher(&1), 1, hasher);
648
    /// assert!(!v.is_empty());
649
    /// # }
650
    /// # fn main() {
651
    /// #     #[cfg(feature = "nightly")]
652
    /// #     test()
653
    /// # }
654
    /// ```
655
0
    pub fn is_empty(&self) -> bool {
656
0
        self.raw.is_empty()
657
0
    }
658
659
    /// An iterator visiting all elements in arbitrary order.
660
    /// The iterator element type is `&'a T`.
661
    ///
662
    /// # Examples
663
    ///
664
    /// ```
665
    /// # #[cfg(feature = "nightly")]
666
    /// # fn test() {
667
    /// use hashbrown::{HashTable, DefaultHashBuilder};
668
    /// use std::hash::BuildHasher;
669
    ///
670
    /// let mut table = HashTable::new();
671
    /// let hasher = DefaultHashBuilder::default();
672
    /// let hasher = |val: &_| hasher.hash_one(val);
673
    /// table.insert_unique(hasher(&"a"), "b", hasher);
674
    /// table.insert_unique(hasher(&"b"), "b", hasher);
675
    ///
676
    /// // Will print in an arbitrary order.
677
    /// for x in table.iter() {
678
    ///     println!("{}", x);
679
    /// }
680
    /// # }
681
    /// # fn main() {
682
    /// #     #[cfg(feature = "nightly")]
683
    /// #     test()
684
    /// # }
685
    /// ```
686
0
    pub fn iter(&self) -> Iter<'_, T> {
687
0
        Iter {
688
0
            inner: unsafe { self.raw.iter() },
689
0
            marker: PhantomData,
690
0
        }
691
0
    }
692
693
    /// An iterator visiting all elements in arbitrary order,
694
    /// with mutable references to the elements.
695
    /// The iterator element type is `&'a mut T`.
696
    ///
697
    /// # Examples
698
    ///
699
    /// ```
700
    /// # #[cfg(feature = "nightly")]
701
    /// # fn test() {
702
    /// use hashbrown::{HashTable, DefaultHashBuilder};
703
    /// use std::hash::BuildHasher;
704
    ///
705
    /// let mut table = HashTable::new();
706
    /// let hasher = DefaultHashBuilder::default();
707
    /// let hasher = |val: &_| hasher.hash_one(val);
708
    /// table.insert_unique(hasher(&1), 1, hasher);
709
    /// table.insert_unique(hasher(&2), 2, hasher);
710
    /// table.insert_unique(hasher(&3), 3, hasher);
711
    ///
712
    /// // Update all values
713
    /// for val in table.iter_mut() {
714
    ///     *val *= 2;
715
    /// }
716
    ///
717
    /// assert_eq!(table.len(), 3);
718
    /// let mut vec: Vec<i32> = Vec::new();
719
    ///
720
    /// for val in &table {
721
    ///     println!("val: {}", val);
722
    ///     vec.push(*val);
723
    /// }
724
    ///
725
    /// // The `Iter` iterator produces items in arbitrary order, so the
726
    /// // items must be sorted to test them against a sorted array.
727
    /// vec.sort_unstable();
728
    /// assert_eq!(vec, [2, 4, 6]);
729
    ///
730
    /// assert_eq!(table.len(), 3);
731
    /// # }
732
    /// # fn main() {
733
    /// #     #[cfg(feature = "nightly")]
734
    /// #     test()
735
    /// # }
736
    /// ```
737
0
    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
738
0
        IterMut {
739
0
            inner: unsafe { self.raw.iter() },
740
0
            marker: PhantomData,
741
0
        }
742
0
    }
743
744
    /// An iterator visiting all elements which may match a hash.
745
    /// The iterator element type is `&'a T`.
746
    ///
747
    /// This iterator may return elements from the table that have a hash value
748
    /// different than the one provided. You should always validate the returned
749
    /// values before using them.
750
    ///
751
    /// # Examples
752
    ///
753
    /// ```
754
    /// # #[cfg(feature = "nightly")]
755
    /// # fn test() {
756
    /// use hashbrown::{HashTable, DefaultHashBuilder};
757
    /// use std::hash::BuildHasher;
758
    ///
759
    /// let mut table = HashTable::new();
760
    /// let hasher = DefaultHashBuilder::default();
761
    /// let hasher = |val: &_| hasher.hash_one(val);
762
    /// table.insert_unique(hasher(&"a"), "a", hasher);
763
    /// table.insert_unique(hasher(&"a"), "b", hasher);
764
    /// table.insert_unique(hasher(&"b"), "c", hasher);
765
    ///
766
    /// // Will print "a" and "b" (and possibly "c") in an arbitrary order.
767
    /// for x in table.iter_hash(hasher(&"a")) {
768
    ///     println!("{}", x);
769
    /// }
770
    /// # }
771
    /// # fn main() {
772
    /// #     #[cfg(feature = "nightly")]
773
    /// #     test()
774
    /// # }
775
    /// ```
776
0
    pub fn iter_hash(&self, hash: u64) -> IterHash<'_, T> {
777
0
        IterHash {
778
0
            inner: unsafe { self.raw.iter_hash(hash) },
779
0
            marker: PhantomData,
780
0
        }
781
0
    }
782
783
    /// A mutable iterator visiting all elements which may match a hash.
784
    /// The iterator element type is `&'a mut T`.
785
    ///
786
    /// This iterator may return elements from the table that have a hash value
787
    /// different than the one provided. You should always validate the returned
788
    /// values before using them.
789
    ///
790
    /// # Examples
791
    ///
792
    /// ```
793
    /// # #[cfg(feature = "nightly")]
794
    /// # fn test() {
795
    /// use hashbrown::{HashTable, DefaultHashBuilder};
796
    /// use std::hash::BuildHasher;
797
    ///
798
    /// let mut table = HashTable::new();
799
    /// let hasher = DefaultHashBuilder::default();
800
    /// let hasher = |val: &_| hasher.hash_one(val);
801
    /// table.insert_unique(hasher(&1), 2, hasher);
802
    /// table.insert_unique(hasher(&1), 3, hasher);
803
    /// table.insert_unique(hasher(&2), 5, hasher);
804
    ///
805
    /// // Update matching values
806
    /// for val in table.iter_hash_mut(hasher(&1)) {
807
    ///     *val *= 2;
808
    /// }
809
    ///
810
    /// assert_eq!(table.len(), 3);
811
    /// let mut vec: Vec<i32> = Vec::new();
812
    ///
813
    /// for val in &table {
814
    ///     println!("val: {}", val);
815
    ///     vec.push(*val);
816
    /// }
817
    ///
818
    /// // The values will contain 4 and 6 and may contain either 5 or 10.
819
    /// assert!(vec.contains(&4));
820
    /// assert!(vec.contains(&6));
821
    ///
822
    /// assert_eq!(table.len(), 3);
823
    /// # }
824
    /// # fn main() {
825
    /// #     #[cfg(feature = "nightly")]
826
    /// #     test()
827
    /// # }
828
    /// ```
829
0
    pub fn iter_hash_mut(&mut self, hash: u64) -> IterHashMut<'_, T> {
830
0
        IterHashMut {
831
0
            inner: unsafe { self.raw.iter_hash(hash) },
832
0
            marker: PhantomData,
833
0
        }
834
0
    }
835
836
    /// Retains only the elements specified by the predicate.
837
    ///
838
    /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
839
    ///
840
    /// # Examples
841
    ///
842
    /// ```
843
    /// # #[cfg(feature = "nightly")]
844
    /// # fn test() {
845
    /// use hashbrown::{HashTable, DefaultHashBuilder};
846
    /// use std::hash::BuildHasher;
847
    ///
848
    /// let mut table = HashTable::new();
849
    /// let hasher = DefaultHashBuilder::default();
850
    /// let hasher = |val: &_| hasher.hash_one(val);
851
    /// for x in 1..=6 {
852
    ///     table.insert_unique(hasher(&x), x, hasher);
853
    /// }
854
    /// table.retain(|&mut x| x % 2 == 0);
855
    /// assert_eq!(table.len(), 3);
856
    /// # }
857
    /// # fn main() {
858
    /// #     #[cfg(feature = "nightly")]
859
    /// #     test()
860
    /// # }
861
    /// ```
862
0
    pub fn retain(&mut self, mut f: impl FnMut(&mut T) -> bool) {
863
        // Here we only use `iter` as a temporary, preventing use-after-free
864
        unsafe {
865
0
            for item in self.raw.iter() {
866
0
                if !f(item.as_mut()) {
867
0
                    self.raw.erase(item);
868
0
                }
869
            }
870
        }
871
0
    }
872
873
    /// Clears the set, returning all elements in an iterator.
874
    ///
875
    /// # Examples
876
    ///
877
    /// ```
878
    /// # #[cfg(feature = "nightly")]
879
    /// # fn test() {
880
    /// use hashbrown::{HashTable, DefaultHashBuilder};
881
    /// use std::hash::BuildHasher;
882
    ///
883
    /// let mut table = HashTable::new();
884
    /// let hasher = DefaultHashBuilder::default();
885
    /// let hasher = |val: &_| hasher.hash_one(val);
886
    /// for x in 1..=3 {
887
    ///     table.insert_unique(hasher(&x), x, hasher);
888
    /// }
889
    /// assert!(!table.is_empty());
890
    ///
891
    /// // print 1, 2, 3 in an arbitrary order
892
    /// for i in table.drain() {
893
    ///     println!("{}", i);
894
    /// }
895
    ///
896
    /// assert!(table.is_empty());
897
    /// # }
898
    /// # fn main() {
899
    /// #     #[cfg(feature = "nightly")]
900
    /// #     test()
901
    /// # }
902
    /// ```
903
0
    pub fn drain(&mut self) -> Drain<'_, T, A> {
904
0
        Drain {
905
0
            inner: self.raw.drain(),
906
0
        }
907
0
    }
908
909
    /// Drains elements which are true under the given predicate,
910
    /// and returns an iterator over the removed items.
911
    ///
912
    /// In other words, move all elements `e` such that `f(&e)` returns `true` out
913
    /// into another iterator.
914
    ///
915
    /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped without iterating
916
    /// or the iteration short-circuits, then the remaining elements will be retained.
917
    /// Use [`retain()`] with a negated predicate if you do not need the returned iterator.
918
    ///
919
    /// [`retain()`]: HashTable::retain
920
    ///
921
    /// # Examples
922
    ///
923
    /// ```
924
    /// # #[cfg(feature = "nightly")]
925
    /// # fn test() {
926
    /// use hashbrown::{HashTable, DefaultHashBuilder};
927
    /// use std::hash::BuildHasher;
928
    ///
929
    /// let mut table = HashTable::new();
930
    /// let hasher = DefaultHashBuilder::default();
931
    /// let hasher = |val: &_| hasher.hash_one(val);
932
    /// for x in 0..8 {
933
    ///     table.insert_unique(hasher(&x), x, hasher);
934
    /// }
935
    /// let drained: Vec<i32> = table.extract_if(|&mut v| v % 2 == 0).collect();
936
    ///
937
    /// let mut evens = drained.into_iter().collect::<Vec<_>>();
938
    /// let mut odds = table.into_iter().collect::<Vec<_>>();
939
    /// evens.sort();
940
    /// odds.sort();
941
    ///
942
    /// assert_eq!(evens, vec![0, 2, 4, 6]);
943
    /// assert_eq!(odds, vec![1, 3, 5, 7]);
944
    /// # }
945
    /// # fn main() {
946
    /// #     #[cfg(feature = "nightly")]
947
    /// #     test()
948
    /// # }
949
    /// ```
950
0
    pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, T, F, A>
951
0
    where
952
0
        F: FnMut(&mut T) -> bool,
953
0
    {
954
0
        ExtractIf {
955
0
            f,
956
0
            inner: RawExtractIf {
957
0
                iter: unsafe { self.raw.iter() },
958
0
                table: &mut self.raw,
959
0
            },
960
0
        }
961
0
    }
962
963
    /// Attempts to get mutable references to `N` values in the map at once.
964
    ///
965
    /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
966
    /// the `i`th key to be looked up.
967
    ///
968
    /// Returns an array of length `N` with the results of each query. For soundness, at most one
969
    /// mutable reference will be returned to any value. `None` will be used if the key is missing.
970
    ///
971
    /// # Panics
972
    ///
973
    /// Panics if any keys are overlapping.
974
    ///
975
    /// # Examples
976
    ///
977
    /// ```
978
    /// # #[cfg(feature = "nightly")]
979
    /// # fn test() {
980
    /// use hashbrown::hash_table::Entry;
981
    /// use hashbrown::{HashTable, DefaultHashBuilder};
982
    /// use std::hash::BuildHasher;
983
    ///
984
    /// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
985
    /// let hasher = DefaultHashBuilder::default();
986
    /// let hasher = |val: &_| hasher.hash_one(val);
987
    /// for (k, v) in [
988
    ///     ("Bodleian Library", 1602),
989
    ///     ("Athenæum", 1807),
990
    ///     ("Herzogin-Anna-Amalia-Bibliothek", 1691),
991
    ///     ("Library of Congress", 1800),
992
    /// ] {
993
    ///     libraries.insert_unique(hasher(&k), (k, v), |(k, _)| hasher(&k));
994
    /// }
995
    ///
996
    /// let keys = ["Athenæum", "Library of Congress"];
997
    /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
998
    /// assert_eq!(
999
    ///     got,
1000
    ///     [Some(&mut ("Athenæum", 1807)), Some(&mut ("Library of Congress", 1800))],
1001
    /// );
1002
    ///
1003
    /// // Missing keys result in None
1004
    /// let keys = ["Athenæum", "New York Public Library"];
1005
    /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
1006
    /// assert_eq!(got, [Some(&mut ("Athenæum", 1807)), None]);
1007
    /// # }
1008
    /// # fn main() {
1009
    /// #     #[cfg(feature = "nightly")]
1010
    /// #     test()
1011
    /// # }
1012
    /// ```
1013
    ///
1014
    /// ```should_panic
1015
    /// # #[cfg(feature = "nightly")]
1016
    /// # fn test() {
1017
    /// # use hashbrown::{HashTable, DefaultHashBuilder};
1018
    /// # use std::hash::BuildHasher;
1019
    ///
1020
    /// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
1021
    /// let hasher = DefaultHashBuilder::default();
1022
    /// let hasher = |val: &_| hasher.hash_one(val);
1023
    /// for (k, v) in [
1024
    ///     ("Athenæum", 1807),
1025
    ///     ("Library of Congress", 1800),
1026
    /// ] {
1027
    ///     libraries.insert_unique(hasher(&k), (k, v), |(k, _)| hasher(&k));
1028
    /// }
1029
    ///
1030
    /// // Duplicate keys result in a panic!
1031
    /// let keys = ["Athenæum", "Athenæum"];
1032
    /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
1033
    /// # }
1034
    /// # fn main() {
1035
    /// #     #[cfg(feature = "nightly")]
1036
    /// #     test();
1037
    /// #     #[cfg(not(feature = "nightly"))]
1038
    /// #     panic!();
1039
    /// # }
1040
    /// ```
1041
0
    pub fn get_many_mut<const N: usize>(
1042
0
        &mut self,
1043
0
        hashes: [u64; N],
1044
0
        eq: impl FnMut(usize, &T) -> bool,
1045
0
    ) -> [Option<&'_ mut T>; N] {
1046
0
        self.raw.get_many_mut(hashes, eq)
1047
0
    }
1048
1049
    /// Attempts to get mutable references to `N` values in the map at once, without validating that
1050
    /// the values are unique.
1051
    ///
1052
    /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
1053
    /// the `i`th key to be looked up.
1054
    ///
1055
    /// Returns an array of length `N` with the results of each query. `None` will be returned if
1056
    /// any of the keys are missing.
1057
    ///
1058
    /// For a safe alternative see [`get_many_mut`](`HashTable::get_many_mut`).
1059
    ///
1060
    /// # Safety
1061
    ///
1062
    /// Calling this method with overlapping keys is *[undefined behavior]* even if the resulting
1063
    /// references are not used.
1064
    ///
1065
    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1066
    ///
1067
    /// # Examples
1068
    ///
1069
    /// ```
1070
    /// # #[cfg(feature = "nightly")]
1071
    /// # fn test() {
1072
    /// use hashbrown::hash_table::Entry;
1073
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1074
    /// use std::hash::BuildHasher;
1075
    ///
1076
    /// let mut libraries: HashTable<(&str, u32)> = HashTable::new();
1077
    /// let hasher = DefaultHashBuilder::default();
1078
    /// let hasher = |val: &_| hasher.hash_one(val);
1079
    /// for (k, v) in [
1080
    ///     ("Bodleian Library", 1602),
1081
    ///     ("Athenæum", 1807),
1082
    ///     ("Herzogin-Anna-Amalia-Bibliothek", 1691),
1083
    ///     ("Library of Congress", 1800),
1084
    /// ] {
1085
    ///     libraries.insert_unique(hasher(&k), (k, v), |(k, _)| hasher(&k));
1086
    /// }
1087
    ///
1088
    /// let keys = ["Athenæum", "Library of Congress"];
1089
    /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
1090
    /// assert_eq!(
1091
    ///     got,
1092
    ///     [Some(&mut ("Athenæum", 1807)), Some(&mut ("Library of Congress", 1800))],
1093
    /// );
1094
    ///
1095
    /// // Missing keys result in None
1096
    /// let keys = ["Athenæum", "New York Public Library"];
1097
    /// let got = libraries.get_many_mut(keys.map(|k| hasher(&k)), |i, val| keys[i] == val.0);
1098
    /// assert_eq!(got, [Some(&mut ("Athenæum", 1807)), None]);
1099
    /// # }
1100
    /// # fn main() {
1101
    /// #     #[cfg(feature = "nightly")]
1102
    /// #     test()
1103
    /// # }
1104
    /// ```
1105
0
    pub unsafe fn get_many_unchecked_mut<const N: usize>(
1106
0
        &mut self,
1107
0
        hashes: [u64; N],
1108
0
        eq: impl FnMut(usize, &T) -> bool,
1109
0
    ) -> [Option<&'_ mut T>; N] {
1110
0
        self.raw.get_many_unchecked_mut(hashes, eq)
1111
0
    }
1112
1113
    /// Returns the total amount of memory allocated internally by the hash
1114
    /// table, in bytes.
1115
    ///
1116
    /// The returned number is informational only. It is intended to be
1117
    /// primarily used for memory profiling.
1118
    #[inline]
1119
0
    pub fn allocation_size(&self) -> usize {
1120
0
        self.raw.allocation_size()
1121
0
    }
1122
}
1123
1124
impl<T, A> IntoIterator for HashTable<T, A>
1125
where
1126
    A: Allocator,
1127
{
1128
    type Item = T;
1129
    type IntoIter = IntoIter<T, A>;
1130
1131
0
    fn into_iter(self) -> IntoIter<T, A> {
1132
0
        IntoIter {
1133
0
            inner: self.raw.into_iter(),
1134
0
        }
1135
0
    }
1136
}
1137
1138
impl<'a, T, A> IntoIterator for &'a HashTable<T, A>
1139
where
1140
    A: Allocator,
1141
{
1142
    type Item = &'a T;
1143
    type IntoIter = Iter<'a, T>;
1144
1145
0
    fn into_iter(self) -> Iter<'a, T> {
1146
0
        self.iter()
1147
0
    }
1148
}
1149
1150
impl<'a, T, A> IntoIterator for &'a mut HashTable<T, A>
1151
where
1152
    A: Allocator,
1153
{
1154
    type Item = &'a mut T;
1155
    type IntoIter = IterMut<'a, T>;
1156
1157
0
    fn into_iter(self) -> IterMut<'a, T> {
1158
0
        self.iter_mut()
1159
0
    }
1160
}
1161
1162
impl<T, A> Default for HashTable<T, A>
1163
where
1164
    A: Allocator + Default,
1165
{
1166
0
    fn default() -> Self {
1167
0
        Self {
1168
0
            raw: Default::default(),
1169
0
        }
1170
0
    }
1171
}
1172
1173
impl<T, A> Clone for HashTable<T, A>
1174
where
1175
    T: Clone,
1176
    A: Allocator + Clone,
1177
{
1178
0
    fn clone(&self) -> Self {
1179
0
        Self {
1180
0
            raw: self.raw.clone(),
1181
0
        }
1182
0
    }
1183
}
1184
1185
impl<T, A> fmt::Debug for HashTable<T, A>
1186
where
1187
    T: fmt::Debug,
1188
    A: Allocator,
1189
{
1190
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191
0
        f.debug_set().entries(self.iter()).finish()
1192
0
    }
1193
}
1194
1195
/// A view into a single entry in a table, which may either be vacant or occupied.
1196
///
1197
/// This `enum` is constructed from the [`entry`] method on [`HashTable`].
1198
///
1199
/// [`HashTable`]: struct.HashTable.html
1200
/// [`entry`]: struct.HashTable.html#method.entry
1201
///
1202
/// # Examples
1203
///
1204
/// ```
1205
/// # #[cfg(feature = "nightly")]
1206
/// # fn test() {
1207
/// use hashbrown::hash_table::{Entry, OccupiedEntry};
1208
/// use hashbrown::{HashTable, DefaultHashBuilder};
1209
/// use std::hash::BuildHasher;
1210
///
1211
/// let mut table = HashTable::new();
1212
/// let hasher = DefaultHashBuilder::default();
1213
/// let hasher = |val: &_| hasher.hash_one(val);
1214
/// for x in ["a", "b", "c"] {
1215
///     table.insert_unique(hasher(&x), x, hasher);
1216
/// }
1217
/// assert_eq!(table.len(), 3);
1218
///
1219
/// // Existing value (insert)
1220
/// let entry: Entry<_> = table.entry(hasher(&"a"), |&x| x == "a", hasher);
1221
/// let _raw_o: OccupiedEntry<_, _> = entry.insert("a");
1222
/// assert_eq!(table.len(), 3);
1223
/// // Nonexistent value (insert)
1224
/// table.entry(hasher(&"d"), |&x| x == "d", hasher).insert("d");
1225
///
1226
/// // Existing value (or_insert)
1227
/// table
1228
///     .entry(hasher(&"b"), |&x| x == "b", hasher)
1229
///     .or_insert("b");
1230
/// // Nonexistent value (or_insert)
1231
/// table
1232
///     .entry(hasher(&"e"), |&x| x == "e", hasher)
1233
///     .or_insert("e");
1234
///
1235
/// println!("Our HashTable: {:?}", table);
1236
///
1237
/// let mut vec: Vec<_> = table.iter().copied().collect();
1238
/// // The `Iter` iterator produces items in arbitrary order, so the
1239
/// // items must be sorted to test them against a sorted array.
1240
/// vec.sort_unstable();
1241
/// assert_eq!(vec, ["a", "b", "c", "d", "e"]);
1242
/// # }
1243
/// # fn main() {
1244
/// #     #[cfg(feature = "nightly")]
1245
/// #     test()
1246
/// # }
1247
/// ```
1248
pub enum Entry<'a, T, A = Global>
1249
where
1250
    A: Allocator,
1251
{
1252
    /// An occupied entry.
1253
    ///
1254
    /// # Examples
1255
    ///
1256
    /// ```
1257
    /// # #[cfg(feature = "nightly")]
1258
    /// # fn test() {
1259
    /// use hashbrown::hash_table::{Entry, OccupiedEntry};
1260
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1261
    /// use std::hash::BuildHasher;
1262
    ///
1263
    /// let mut table = HashTable::new();
1264
    /// let hasher = DefaultHashBuilder::default();
1265
    /// let hasher = |val: &_| hasher.hash_one(val);
1266
    /// for x in ["a", "b"] {
1267
    ///     table.insert_unique(hasher(&x), x, hasher);
1268
    /// }
1269
    ///
1270
    /// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
1271
    ///     Entry::Vacant(_) => unreachable!(),
1272
    ///     Entry::Occupied(_) => {}
1273
    /// }
1274
    /// # }
1275
    /// # fn main() {
1276
    /// #     #[cfg(feature = "nightly")]
1277
    /// #     test()
1278
    /// # }
1279
    /// ```
1280
    Occupied(OccupiedEntry<'a, T, A>),
1281
1282
    /// A vacant entry.
1283
    ///
1284
    /// # Examples
1285
    ///
1286
    /// ```
1287
    /// # #[cfg(feature = "nightly")]
1288
    /// # fn test() {
1289
    /// use hashbrown::hash_table::{Entry, OccupiedEntry};
1290
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1291
    /// use std::hash::BuildHasher;
1292
    ///
1293
    /// let mut table = HashTable::<&str>::new();
1294
    /// let hasher = DefaultHashBuilder::default();
1295
    /// let hasher = |val: &_| hasher.hash_one(val);
1296
    ///
1297
    /// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
1298
    ///     Entry::Vacant(_) => {}
1299
    ///     Entry::Occupied(_) => unreachable!(),
1300
    /// }
1301
    /// # }
1302
    /// # fn main() {
1303
    /// #     #[cfg(feature = "nightly")]
1304
    /// #     test()
1305
    /// # }
1306
    /// ```
1307
    Vacant(VacantEntry<'a, T, A>),
1308
}
1309
1310
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Entry<'_, T, A> {
1311
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1312
0
        match *self {
1313
0
            Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
1314
0
            Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
1315
        }
1316
0
    }
1317
}
1318
1319
impl<'a, T, A> Entry<'a, T, A>
1320
where
1321
    A: Allocator,
1322
{
1323
    /// Sets the value of the entry, replacing any existing value if there is
1324
    /// one, and returns an [`OccupiedEntry`].
1325
    ///
1326
    /// # Examples
1327
    ///
1328
    /// ```
1329
    /// # #[cfg(feature = "nightly")]
1330
    /// # fn test() {
1331
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1332
    /// use std::hash::BuildHasher;
1333
    ///
1334
    /// let mut table: HashTable<&str> = HashTable::new();
1335
    /// let hasher = DefaultHashBuilder::default();
1336
    /// let hasher = |val: &_| hasher.hash_one(val);
1337
    ///
1338
    /// let entry = table
1339
    ///     .entry(hasher(&"horseyland"), |&x| x == "horseyland", hasher)
1340
    ///     .insert("horseyland");
1341
    ///
1342
    /// assert_eq!(entry.get(), &"horseyland");
1343
    /// # }
1344
    /// # fn main() {
1345
    /// #     #[cfg(feature = "nightly")]
1346
    /// #     test()
1347
    /// # }
1348
    /// ```
1349
0
    pub fn insert(self, value: T) -> OccupiedEntry<'a, T, A> {
1350
0
        match self {
1351
0
            Entry::Occupied(mut entry) => {
1352
0
                *entry.get_mut() = value;
1353
0
                entry
1354
            }
1355
0
            Entry::Vacant(entry) => entry.insert(value),
1356
        }
1357
0
    }
1358
1359
    /// Ensures a value is in the entry by inserting if it was vacant.
1360
    ///
1361
    /// Returns an [`OccupiedEntry`] pointing to the now-occupied entry.
1362
    ///
1363
    /// # Examples
1364
    ///
1365
    /// ```
1366
    /// # #[cfg(feature = "nightly")]
1367
    /// # fn test() {
1368
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1369
    /// use std::hash::BuildHasher;
1370
    ///
1371
    /// let mut table: HashTable<&str> = HashTable::new();
1372
    /// let hasher = DefaultHashBuilder::default();
1373
    /// let hasher = |val: &_| hasher.hash_one(val);
1374
    ///
1375
    /// // nonexistent key
1376
    /// table
1377
    ///     .entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher)
1378
    ///     .or_insert("poneyland");
1379
    /// assert!(table
1380
    ///     .find(hasher(&"poneyland"), |&x| x == "poneyland")
1381
    ///     .is_some());
1382
    ///
1383
    /// // existing key
1384
    /// table
1385
    ///     .entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher)
1386
    ///     .or_insert("poneyland");
1387
    /// assert!(table
1388
    ///     .find(hasher(&"poneyland"), |&x| x == "poneyland")
1389
    ///     .is_some());
1390
    /// assert_eq!(table.len(), 1);
1391
    /// # }
1392
    /// # fn main() {
1393
    /// #     #[cfg(feature = "nightly")]
1394
    /// #     test()
1395
    /// # }
1396
    /// ```
1397
0
    pub fn or_insert(self, default: T) -> OccupiedEntry<'a, T, A> {
1398
0
        match self {
1399
0
            Entry::Occupied(entry) => entry,
1400
0
            Entry::Vacant(entry) => entry.insert(default),
1401
        }
1402
0
    }
1403
1404
    /// Ensures a value is in the entry by inserting the result of the default function if empty..
1405
    ///
1406
    /// Returns an [`OccupiedEntry`] pointing to the now-occupied entry.
1407
    ///
1408
    /// # Examples
1409
    ///
1410
    /// ```
1411
    /// # #[cfg(feature = "nightly")]
1412
    /// # fn test() {
1413
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1414
    /// use std::hash::BuildHasher;
1415
    ///
1416
    /// let mut table: HashTable<String> = HashTable::new();
1417
    /// let hasher = DefaultHashBuilder::default();
1418
    /// let hasher = |val: &_| hasher.hash_one(val);
1419
    ///
1420
    /// table
1421
    ///     .entry(hasher("poneyland"), |x| x == "poneyland", |val| hasher(val))
1422
    ///     .or_insert_with(|| "poneyland".to_string());
1423
    ///
1424
    /// assert!(table
1425
    ///     .find(hasher(&"poneyland"), |x| x == "poneyland")
1426
    ///     .is_some());
1427
    /// # }
1428
    /// # fn main() {
1429
    /// #     #[cfg(feature = "nightly")]
1430
    /// #     test()
1431
    /// # }
1432
    /// ```
1433
0
    pub fn or_insert_with(self, default: impl FnOnce() -> T) -> OccupiedEntry<'a, T, A> {
1434
0
        match self {
1435
0
            Entry::Occupied(entry) => entry,
1436
0
            Entry::Vacant(entry) => entry.insert(default()),
1437
        }
1438
0
    }
1439
1440
    /// Provides in-place mutable access to an occupied entry before any
1441
    /// potential inserts into the table.
1442
    ///
1443
    /// # Examples
1444
    ///
1445
    /// ```
1446
    /// # #[cfg(feature = "nightly")]
1447
    /// # fn test() {
1448
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1449
    /// use std::hash::BuildHasher;
1450
    ///
1451
    /// let mut table: HashTable<(&str, u32)> = HashTable::new();
1452
    /// let hasher = DefaultHashBuilder::default();
1453
    /// let hasher = |val: &_| hasher.hash_one(val);
1454
    ///
1455
    /// table
1456
    ///     .entry(
1457
    ///         hasher(&"poneyland"),
1458
    ///         |&(x, _)| x == "poneyland",
1459
    ///         |(k, _)| hasher(&k),
1460
    ///     )
1461
    ///     .and_modify(|(_, v)| *v += 1)
1462
    ///     .or_insert(("poneyland", 42));
1463
    /// assert_eq!(
1464
    ///     table.find(hasher(&"poneyland"), |&(k, _)| k == "poneyland"),
1465
    ///     Some(&("poneyland", 42))
1466
    /// );
1467
    ///
1468
    /// table
1469
    ///     .entry(
1470
    ///         hasher(&"poneyland"),
1471
    ///         |&(x, _)| x == "poneyland",
1472
    ///         |(k, _)| hasher(&k),
1473
    ///     )
1474
    ///     .and_modify(|(_, v)| *v += 1)
1475
    ///     .or_insert(("poneyland", 42));
1476
    /// assert_eq!(
1477
    ///     table.find(hasher(&"poneyland"), |&(k, _)| k == "poneyland"),
1478
    ///     Some(&("poneyland", 43))
1479
    /// );
1480
    /// # }
1481
    /// # fn main() {
1482
    /// #     #[cfg(feature = "nightly")]
1483
    /// #     test()
1484
    /// # }
1485
    /// ```
1486
0
    pub fn and_modify(self, f: impl FnOnce(&mut T)) -> Self {
1487
0
        match self {
1488
0
            Entry::Occupied(mut entry) => {
1489
0
                f(entry.get_mut());
1490
0
                Entry::Occupied(entry)
1491
            }
1492
0
            Entry::Vacant(entry) => Entry::Vacant(entry),
1493
        }
1494
0
    }
1495
}
1496
1497
/// A view into an occupied entry in a `HashTable`.
1498
/// It is part of the [`Entry`] enum.
1499
///
1500
/// [`Entry`]: enum.Entry.html
1501
///
1502
/// # Examples
1503
///
1504
/// ```
1505
/// # #[cfg(feature = "nightly")]
1506
/// # fn test() {
1507
/// use hashbrown::hash_table::{Entry, OccupiedEntry};
1508
/// use hashbrown::{HashTable, DefaultHashBuilder};
1509
/// use std::hash::BuildHasher;
1510
///
1511
/// let mut table = HashTable::new();
1512
/// let hasher = DefaultHashBuilder::default();
1513
/// let hasher = |val: &_| hasher.hash_one(val);
1514
/// for x in ["a", "b", "c"] {
1515
///     table.insert_unique(hasher(&x), x, hasher);
1516
/// }
1517
/// assert_eq!(table.len(), 3);
1518
///
1519
/// let _entry_o: OccupiedEntry<_, _> = table.find_entry(hasher(&"a"), |&x| x == "a").unwrap();
1520
/// assert_eq!(table.len(), 3);
1521
///
1522
/// // Existing key
1523
/// match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
1524
///     Entry::Vacant(_) => unreachable!(),
1525
///     Entry::Occupied(view) => {
1526
///         assert_eq!(view.get(), &"a");
1527
///     }
1528
/// }
1529
///
1530
/// assert_eq!(table.len(), 3);
1531
///
1532
/// // Existing key (take)
1533
/// match table.entry(hasher(&"c"), |&x| x == "c", hasher) {
1534
///     Entry::Vacant(_) => unreachable!(),
1535
///     Entry::Occupied(view) => {
1536
///         assert_eq!(view.remove().0, "c");
1537
///     }
1538
/// }
1539
/// assert_eq!(table.find(hasher(&"c"), |&x| x == "c"), None);
1540
/// assert_eq!(table.len(), 2);
1541
/// # }
1542
/// # fn main() {
1543
/// #     #[cfg(feature = "nightly")]
1544
/// #     test()
1545
/// # }
1546
/// ```
1547
pub struct OccupiedEntry<'a, T, A = Global>
1548
where
1549
    A: Allocator,
1550
{
1551
    hash: u64,
1552
    bucket: Bucket<T>,
1553
    table: &'a mut HashTable<T, A>,
1554
}
1555
1556
unsafe impl<T, A> Send for OccupiedEntry<'_, T, A>
1557
where
1558
    T: Send,
1559
    A: Send + Allocator,
1560
{
1561
}
1562
unsafe impl<T, A> Sync for OccupiedEntry<'_, T, A>
1563
where
1564
    T: Sync,
1565
    A: Sync + Allocator,
1566
{
1567
}
1568
1569
impl<T: fmt::Debug, A: Allocator> fmt::Debug for OccupiedEntry<'_, T, A> {
1570
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1571
0
        f.debug_struct("OccupiedEntry")
1572
0
            .field("value", self.get())
1573
0
            .finish()
1574
0
    }
1575
}
1576
1577
impl<'a, T, A> OccupiedEntry<'a, T, A>
1578
where
1579
    A: Allocator,
1580
{
1581
    /// Takes the value out of the entry, and returns it along with a
1582
    /// `VacantEntry` that can be used to insert another value with the same
1583
    /// hash as the one that was just removed.
1584
    ///
1585
    /// # Examples
1586
    ///
1587
    /// ```
1588
    /// # #[cfg(feature = "nightly")]
1589
    /// # fn test() {
1590
    /// use hashbrown::hash_table::Entry;
1591
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1592
    /// use std::hash::BuildHasher;
1593
    ///
1594
    /// let mut table: HashTable<&str> = HashTable::new();
1595
    /// let hasher = DefaultHashBuilder::default();
1596
    /// let hasher = |val: &_| hasher.hash_one(val);
1597
    /// // The table is empty
1598
    /// assert!(table.is_empty() && table.capacity() == 0);
1599
    ///
1600
    /// table.insert_unique(hasher(&"poneyland"), "poneyland", hasher);
1601
    /// let capacity_before_remove = table.capacity();
1602
    ///
1603
    /// if let Entry::Occupied(o) = table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
1604
    ///     assert_eq!(o.remove().0, "poneyland");
1605
    /// }
1606
    ///
1607
    /// assert!(table
1608
    ///     .find(hasher(&"poneyland"), |&x| x == "poneyland")
1609
    ///     .is_none());
1610
    /// // Now table hold none elements but capacity is equal to the old one
1611
    /// assert!(table.len() == 0 && table.capacity() == capacity_before_remove);
1612
    /// # }
1613
    /// # fn main() {
1614
    /// #     #[cfg(feature = "nightly")]
1615
    /// #     test()
1616
    /// # }
1617
    /// ```
1618
    #[cfg_attr(feature = "inline-more", inline)]
1619
0
    pub fn remove(self) -> (T, VacantEntry<'a, T, A>) {
1620
0
        let (val, slot) = unsafe { self.table.raw.remove(self.bucket) };
1621
0
        (
1622
0
            val,
1623
0
            VacantEntry {
1624
0
                hash: self.hash,
1625
0
                insert_slot: slot,
1626
0
                table: self.table,
1627
0
            },
1628
0
        )
1629
0
    }
1630
1631
    /// Gets a reference to the value in the entry.
1632
    ///
1633
    /// # Examples
1634
    ///
1635
    /// ```
1636
    /// # #[cfg(feature = "nightly")]
1637
    /// # fn test() {
1638
    /// use hashbrown::hash_table::Entry;
1639
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1640
    /// use std::hash::BuildHasher;
1641
    ///
1642
    /// let mut table: HashTable<&str> = HashTable::new();
1643
    /// let hasher = DefaultHashBuilder::default();
1644
    /// let hasher = |val: &_| hasher.hash_one(val);
1645
    /// table.insert_unique(hasher(&"poneyland"), "poneyland", hasher);
1646
    ///
1647
    /// match table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
1648
    ///     Entry::Vacant(_) => panic!(),
1649
    ///     Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"),
1650
    /// }
1651
    /// # }
1652
    /// # fn main() {
1653
    /// #     #[cfg(feature = "nightly")]
1654
    /// #     test()
1655
    /// # }
1656
    /// ```
1657
    #[inline]
1658
0
    pub fn get(&self) -> &T {
1659
0
        unsafe { self.bucket.as_ref() }
1660
0
    }
Unexecuted instantiation: <hashbrown::table::OccupiedEntry<usize>>::get
Unexecuted instantiation: <hashbrown::table::OccupiedEntry<_, _>>::get
1661
1662
    /// Gets a mutable reference to the value in the entry.
1663
    ///
1664
    /// If you need a reference to the `OccupiedEntry` which may outlive the
1665
    /// destruction of the `Entry` value, see [`into_mut`].
1666
    ///
1667
    /// [`into_mut`]: #method.into_mut
1668
    ///
1669
    /// # Examples
1670
    ///
1671
    /// ```
1672
    /// # #[cfg(feature = "nightly")]
1673
    /// # fn test() {
1674
    /// use hashbrown::hash_table::Entry;
1675
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1676
    /// use std::hash::BuildHasher;
1677
    ///
1678
    /// let mut table: HashTable<(&str, u32)> = HashTable::new();
1679
    /// let hasher = DefaultHashBuilder::default();
1680
    /// let hasher = |val: &_| hasher.hash_one(val);
1681
    /// table.insert_unique(hasher(&"poneyland"), ("poneyland", 12), |(k, _)| hasher(&k));
1682
    ///
1683
    /// assert_eq!(
1684
    ///     table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
1685
    ///     Some(&("poneyland", 12))
1686
    /// );
1687
    ///
1688
    /// if let Entry::Occupied(mut o) = table.entry(
1689
    ///     hasher(&"poneyland"),
1690
    ///     |&(x, _)| x == "poneyland",
1691
    ///     |(k, _)| hasher(&k),
1692
    /// ) {
1693
    ///     o.get_mut().1 += 10;
1694
    ///     assert_eq!(o.get().1, 22);
1695
    ///
1696
    ///     // We can use the same Entry multiple times.
1697
    ///     o.get_mut().1 += 2;
1698
    /// }
1699
    ///
1700
    /// assert_eq!(
1701
    ///     table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
1702
    ///     Some(&("poneyland", 24))
1703
    /// );
1704
    /// # }
1705
    /// # fn main() {
1706
    /// #     #[cfg(feature = "nightly")]
1707
    /// #     test()
1708
    /// # }
1709
    /// ```
1710
    #[inline]
1711
0
    pub fn get_mut(&mut self) -> &mut T {
1712
0
        unsafe { self.bucket.as_mut() }
1713
0
    }
1714
1715
    /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
1716
    /// with a lifetime bound to the table itself.
1717
    ///
1718
    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
1719
    ///
1720
    /// [`get_mut`]: #method.get_mut
1721
    ///
1722
    /// # Examples
1723
    ///
1724
    /// ```
1725
    /// # #[cfg(feature = "nightly")]
1726
    /// # fn test() {
1727
    /// use hashbrown::hash_table::Entry;
1728
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1729
    /// use std::hash::BuildHasher;
1730
    ///
1731
    /// let mut table: HashTable<(&str, u32)> = HashTable::new();
1732
    /// let hasher = DefaultHashBuilder::default();
1733
    /// let hasher = |val: &_| hasher.hash_one(val);
1734
    /// table.insert_unique(hasher(&"poneyland"), ("poneyland", 12), |(k, _)| hasher(&k));
1735
    ///
1736
    /// assert_eq!(
1737
    ///     table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
1738
    ///     Some(&("poneyland", 12))
1739
    /// );
1740
    ///
1741
    /// let value: &mut (&str, u32);
1742
    /// match table.entry(
1743
    ///     hasher(&"poneyland"),
1744
    ///     |&(x, _)| x == "poneyland",
1745
    ///     |(k, _)| hasher(&k),
1746
    /// ) {
1747
    ///     Entry::Occupied(entry) => value = entry.into_mut(),
1748
    ///     Entry::Vacant(_) => panic!(),
1749
    /// }
1750
    /// value.1 += 10;
1751
    ///
1752
    /// assert_eq!(
1753
    ///     table.find(hasher(&"poneyland"), |&(x, _)| x == "poneyland",),
1754
    ///     Some(&("poneyland", 22))
1755
    /// );
1756
    /// # }
1757
    /// # fn main() {
1758
    /// #     #[cfg(feature = "nightly")]
1759
    /// #     test()
1760
    /// # }
1761
    /// ```
1762
0
    pub fn into_mut(self) -> &'a mut T {
1763
0
        unsafe { self.bucket.as_mut() }
1764
0
    }
1765
1766
    /// Converts the `OccupiedEntry` into a mutable reference to the underlying
1767
    /// table.
1768
0
    pub fn into_table(self) -> &'a mut HashTable<T, A> {
1769
0
        self.table
1770
0
    }
1771
}
1772
1773
/// A view into a vacant entry in a `HashTable`.
1774
/// It is part of the [`Entry`] enum.
1775
///
1776
/// [`Entry`]: enum.Entry.html
1777
///
1778
/// # Examples
1779
///
1780
/// ```
1781
/// # #[cfg(feature = "nightly")]
1782
/// # fn test() {
1783
/// use hashbrown::hash_table::{Entry, VacantEntry};
1784
/// use hashbrown::{HashTable, DefaultHashBuilder};
1785
/// use std::hash::BuildHasher;
1786
///
1787
/// let mut table: HashTable<&str> = HashTable::new();
1788
/// let hasher = DefaultHashBuilder::default();
1789
/// let hasher = |val: &_| hasher.hash_one(val);
1790
///
1791
/// let entry_v: VacantEntry<_, _> = match table.entry(hasher(&"a"), |&x| x == "a", hasher) {
1792
///     Entry::Vacant(view) => view,
1793
///     Entry::Occupied(_) => unreachable!(),
1794
/// };
1795
/// entry_v.insert("a");
1796
/// assert!(table.find(hasher(&"a"), |&x| x == "a").is_some() && table.len() == 1);
1797
///
1798
/// // Nonexistent key (insert)
1799
/// match table.entry(hasher(&"b"), |&x| x == "b", hasher) {
1800
///     Entry::Vacant(view) => {
1801
///         view.insert("b");
1802
///     }
1803
///     Entry::Occupied(_) => unreachable!(),
1804
/// }
1805
/// assert!(table.find(hasher(&"b"), |&x| x == "b").is_some() && table.len() == 2);
1806
/// # }
1807
/// # fn main() {
1808
/// #     #[cfg(feature = "nightly")]
1809
/// #     test()
1810
/// # }
1811
/// ```
1812
pub struct VacantEntry<'a, T, A = Global>
1813
where
1814
    A: Allocator,
1815
{
1816
    hash: u64,
1817
    insert_slot: InsertSlot,
1818
    table: &'a mut HashTable<T, A>,
1819
}
1820
1821
impl<T: fmt::Debug, A: Allocator> fmt::Debug for VacantEntry<'_, T, A> {
1822
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1823
0
        f.write_str("VacantEntry")
1824
0
    }
1825
}
1826
1827
impl<'a, T, A> VacantEntry<'a, T, A>
1828
where
1829
    A: Allocator,
1830
{
1831
    /// Inserts a new element into the table with the hash that was used to
1832
    /// obtain the `VacantEntry`.
1833
    ///
1834
    /// An `OccupiedEntry` is returned for the newly inserted element.
1835
    ///
1836
    /// # Examples
1837
    ///
1838
    /// ```
1839
    /// # #[cfg(feature = "nightly")]
1840
    /// # fn test() {
1841
    /// use hashbrown::hash_table::Entry;
1842
    /// use hashbrown::{HashTable, DefaultHashBuilder};
1843
    /// use std::hash::BuildHasher;
1844
    ///
1845
    /// let mut table: HashTable<&str> = HashTable::new();
1846
    /// let hasher = DefaultHashBuilder::default();
1847
    /// let hasher = |val: &_| hasher.hash_one(val);
1848
    ///
1849
    /// if let Entry::Vacant(o) = table.entry(hasher(&"poneyland"), |&x| x == "poneyland", hasher) {
1850
    ///     o.insert("poneyland");
1851
    /// }
1852
    /// assert_eq!(
1853
    ///     table.find(hasher(&"poneyland"), |&x| x == "poneyland"),
1854
    ///     Some(&"poneyland")
1855
    /// );
1856
    /// # }
1857
    /// # fn main() {
1858
    /// #     #[cfg(feature = "nightly")]
1859
    /// #     test()
1860
    /// # }
1861
    /// ```
1862
    #[inline]
1863
0
    pub fn insert(self, value: T) -> OccupiedEntry<'a, T, A> {
1864
0
        let bucket = unsafe {
1865
0
            self.table
1866
0
                .raw
1867
0
                .insert_in_slot(self.hash, self.insert_slot, value)
1868
0
        };
1869
0
        OccupiedEntry {
1870
0
            hash: self.hash,
1871
0
            bucket,
1872
0
            table: self.table,
1873
0
        }
1874
0
    }
Unexecuted instantiation: <hashbrown::table::VacantEntry<usize>>::insert
Unexecuted instantiation: <hashbrown::table::VacantEntry<_, _>>::insert
1875
1876
    /// Converts the `VacantEntry` into a mutable reference to the underlying
1877
    /// table.
1878
0
    pub fn into_table(self) -> &'a mut HashTable<T, A> {
1879
0
        self.table
1880
0
    }
1881
}
1882
1883
/// Type representing the absence of an entry, as returned by [`HashTable::find_entry`].
1884
///
1885
/// This type only exists due to [limitations] in Rust's NLL borrow checker. In
1886
/// the future, `find_entry` will return an `Option<OccupiedEntry>` and this
1887
/// type will be removed.
1888
///
1889
/// [limitations]: https://smallcultfollowing.com/babysteps/blog/2018/06/15/mir-based-borrow-check-nll-status-update/#polonius
1890
///
1891
/// # Examples
1892
///
1893
/// ```
1894
/// # #[cfg(feature = "nightly")]
1895
/// # fn test() {
1896
/// use hashbrown::hash_table::{AbsentEntry, Entry};
1897
/// use hashbrown::{HashTable, DefaultHashBuilder};
1898
/// use std::hash::BuildHasher;
1899
///
1900
/// let mut table: HashTable<&str> = HashTable::new();
1901
/// let hasher = DefaultHashBuilder::default();
1902
/// let hasher = |val: &_| hasher.hash_one(val);
1903
///
1904
/// let entry_v: AbsentEntry<_, _> = table.find_entry(hasher(&"a"), |&x| x == "a").unwrap_err();
1905
/// entry_v
1906
///     .into_table()
1907
///     .insert_unique(hasher(&"a"), "a", hasher);
1908
/// assert!(table.find(hasher(&"a"), |&x| x == "a").is_some() && table.len() == 1);
1909
///
1910
/// // Nonexistent key (insert)
1911
/// match table.entry(hasher(&"b"), |&x| x == "b", hasher) {
1912
///     Entry::Vacant(view) => {
1913
///         view.insert("b");
1914
///     }
1915
///     Entry::Occupied(_) => unreachable!(),
1916
/// }
1917
/// assert!(table.find(hasher(&"b"), |&x| x == "b").is_some() && table.len() == 2);
1918
/// # }
1919
/// # fn main() {
1920
/// #     #[cfg(feature = "nightly")]
1921
/// #     test()
1922
/// # }
1923
/// ```
1924
pub struct AbsentEntry<'a, T, A = Global>
1925
where
1926
    A: Allocator,
1927
{
1928
    table: &'a mut HashTable<T, A>,
1929
}
1930
1931
impl<T: fmt::Debug, A: Allocator> fmt::Debug for AbsentEntry<'_, T, A> {
1932
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1933
0
        f.write_str("AbsentEntry")
1934
0
    }
1935
}
1936
1937
impl<'a, T, A> AbsentEntry<'a, T, A>
1938
where
1939
    A: Allocator,
1940
{
1941
    /// Converts the `AbsentEntry` into a mutable reference to the underlying
1942
    /// table.
1943
0
    pub fn into_table(self) -> &'a mut HashTable<T, A> {
1944
0
        self.table
1945
0
    }
Unexecuted instantiation: <hashbrown::table::AbsentEntry<usize>>::into_table
Unexecuted instantiation: <hashbrown::table::AbsentEntry<_, _>>::into_table
1946
}
1947
1948
/// An iterator over the entries of a `HashTable` in arbitrary order.
1949
/// The iterator element type is `&'a T`.
1950
///
1951
/// This `struct` is created by the [`iter`] method on [`HashTable`]. See its
1952
/// documentation for more.
1953
///
1954
/// [`iter`]: struct.HashTable.html#method.iter
1955
/// [`HashTable`]: struct.HashTable.html
1956
pub struct Iter<'a, T> {
1957
    inner: RawIter<T>,
1958
    marker: PhantomData<&'a T>,
1959
}
1960
1961
impl<T> Default for Iter<'_, T> {
1962
    #[cfg_attr(feature = "inline-more", inline)]
1963
0
    fn default() -> Self {
1964
0
        Iter {
1965
0
            inner: Default::default(),
1966
0
            marker: PhantomData,
1967
0
        }
1968
0
    }
1969
}
1970
1971
impl<'a, T> Iterator for Iter<'a, T> {
1972
    type Item = &'a T;
1973
1974
0
    fn next(&mut self) -> Option<Self::Item> {
1975
0
        // Avoid `Option::map` because it bloats LLVM IR.
1976
0
        match self.inner.next() {
1977
0
            Some(bucket) => Some(unsafe { bucket.as_ref() }),
1978
0
            None => None,
1979
        }
1980
0
    }
1981
1982
0
    fn size_hint(&self) -> (usize, Option<usize>) {
1983
0
        self.inner.size_hint()
1984
0
    }
1985
1986
0
    fn fold<B, F>(self, init: B, mut f: F) -> B
1987
0
    where
1988
0
        Self: Sized,
1989
0
        F: FnMut(B, Self::Item) -> B,
1990
0
    {
1991
0
        self.inner
1992
0
            .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_ref()) })
1993
0
    }
1994
}
1995
1996
impl<T> ExactSizeIterator for Iter<'_, T> {
1997
0
    fn len(&self) -> usize {
1998
0
        self.inner.len()
1999
0
    }
2000
}
2001
2002
impl<T> FusedIterator for Iter<'_, T> {}
2003
2004
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
2005
impl<'a, T> Clone for Iter<'a, T> {
2006
    #[cfg_attr(feature = "inline-more", inline)]
2007
0
    fn clone(&self) -> Iter<'a, T> {
2008
0
        Iter {
2009
0
            inner: self.inner.clone(),
2010
0
            marker: PhantomData,
2011
0
        }
2012
0
    }
2013
}
2014
2015
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
2016
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2017
0
        f.debug_list().entries(self.clone()).finish()
2018
0
    }
2019
}
2020
2021
/// A mutable iterator over the entries of a `HashTable` in arbitrary order.
2022
/// The iterator element type is `&'a mut T`.
2023
///
2024
/// This `struct` is created by the [`iter_mut`] method on [`HashTable`]. See its
2025
/// documentation for more.
2026
///
2027
/// [`iter_mut`]: struct.HashTable.html#method.iter_mut
2028
/// [`HashTable`]: struct.HashTable.html
2029
pub struct IterMut<'a, T> {
2030
    inner: RawIter<T>,
2031
    marker: PhantomData<&'a mut T>,
2032
}
2033
2034
impl<T> Default for IterMut<'_, T> {
2035
    #[cfg_attr(feature = "inline-more", inline)]
2036
0
    fn default() -> Self {
2037
0
        IterMut {
2038
0
            inner: Default::default(),
2039
0
            marker: PhantomData,
2040
0
        }
2041
0
    }
2042
}
2043
impl<'a, T> Iterator for IterMut<'a, T> {
2044
    type Item = &'a mut T;
2045
2046
0
    fn next(&mut self) -> Option<Self::Item> {
2047
0
        // Avoid `Option::map` because it bloats LLVM IR.
2048
0
        match self.inner.next() {
2049
0
            Some(bucket) => Some(unsafe { bucket.as_mut() }),
2050
0
            None => None,
2051
        }
2052
0
    }
2053
2054
0
    fn size_hint(&self) -> (usize, Option<usize>) {
2055
0
        self.inner.size_hint()
2056
0
    }
2057
2058
0
    fn fold<B, F>(self, init: B, mut f: F) -> B
2059
0
    where
2060
0
        Self: Sized,
2061
0
        F: FnMut(B, Self::Item) -> B,
2062
0
    {
2063
0
        self.inner
2064
0
            .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_mut()) })
2065
0
    }
2066
}
2067
2068
impl<T> ExactSizeIterator for IterMut<'_, T> {
2069
0
    fn len(&self) -> usize {
2070
0
        self.inner.len()
2071
0
    }
2072
}
2073
2074
impl<T> FusedIterator for IterMut<'_, T> {}
2075
2076
impl<T> fmt::Debug for IterMut<'_, T>
2077
where
2078
    T: fmt::Debug,
2079
{
2080
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2081
0
        f.debug_list()
2082
0
            .entries(Iter {
2083
0
                inner: self.inner.clone(),
2084
0
                marker: PhantomData,
2085
0
            })
2086
0
            .finish()
2087
0
    }
2088
}
2089
2090
/// An iterator over the entries of a `HashTable` that could match a given hash.
2091
/// The iterator element type is `&'a T`.
2092
///
2093
/// This `struct` is created by the [`iter_hash`] method on [`HashTable`]. See its
2094
/// documentation for more.
2095
///
2096
/// [`iter_hash`]: struct.HashTable.html#method.iter_hash
2097
/// [`HashTable`]: struct.HashTable.html
2098
pub struct IterHash<'a, T> {
2099
    inner: RawIterHash<T>,
2100
    marker: PhantomData<&'a T>,
2101
}
2102
2103
impl<T> Default for IterHash<'_, T> {
2104
    #[cfg_attr(feature = "inline-more", inline)]
2105
0
    fn default() -> Self {
2106
0
        IterHash {
2107
0
            inner: Default::default(),
2108
0
            marker: PhantomData,
2109
0
        }
2110
0
    }
2111
}
2112
2113
impl<'a, T> Iterator for IterHash<'a, T> {
2114
    type Item = &'a T;
2115
2116
0
    fn next(&mut self) -> Option<Self::Item> {
2117
0
        // Avoid `Option::map` because it bloats LLVM IR.
2118
0
        match self.inner.next() {
2119
0
            Some(bucket) => Some(unsafe { bucket.as_ref() }),
2120
0
            None => None,
2121
        }
2122
0
    }
2123
2124
0
    fn fold<B, F>(self, init: B, mut f: F) -> B
2125
0
    where
2126
0
        Self: Sized,
2127
0
        F: FnMut(B, Self::Item) -> B,
2128
0
    {
2129
0
        self.inner
2130
0
            .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_ref()) })
2131
0
    }
2132
}
2133
2134
impl<T> FusedIterator for IterHash<'_, T> {}
2135
2136
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
2137
impl<'a, T> Clone for IterHash<'a, T> {
2138
    #[cfg_attr(feature = "inline-more", inline)]
2139
0
    fn clone(&self) -> IterHash<'a, T> {
2140
0
        IterHash {
2141
0
            inner: self.inner.clone(),
2142
0
            marker: PhantomData,
2143
0
        }
2144
0
    }
2145
}
2146
2147
impl<T> fmt::Debug for IterHash<'_, T>
2148
where
2149
    T: fmt::Debug,
2150
{
2151
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2152
0
        f.debug_list().entries(self.clone()).finish()
2153
0
    }
2154
}
2155
2156
/// A mutable iterator over the entries of a `HashTable` that could match a given hash.
2157
/// The iterator element type is `&'a mut T`.
2158
///
2159
/// This `struct` is created by the [`iter_hash_mut`] method on [`HashTable`]. See its
2160
/// documentation for more.
2161
///
2162
/// [`iter_hash_mut`]: struct.HashTable.html#method.iter_hash_mut
2163
/// [`HashTable`]: struct.HashTable.html
2164
pub struct IterHashMut<'a, T> {
2165
    inner: RawIterHash<T>,
2166
    marker: PhantomData<&'a mut T>,
2167
}
2168
2169
impl<T> Default for IterHashMut<'_, T> {
2170
    #[cfg_attr(feature = "inline-more", inline)]
2171
0
    fn default() -> Self {
2172
0
        IterHashMut {
2173
0
            inner: Default::default(),
2174
0
            marker: PhantomData,
2175
0
        }
2176
0
    }
2177
}
2178
2179
impl<'a, T> Iterator for IterHashMut<'a, T> {
2180
    type Item = &'a mut T;
2181
2182
0
    fn next(&mut self) -> Option<Self::Item> {
2183
0
        // Avoid `Option::map` because it bloats LLVM IR.
2184
0
        match self.inner.next() {
2185
0
            Some(bucket) => Some(unsafe { bucket.as_mut() }),
2186
0
            None => None,
2187
        }
2188
0
    }
2189
2190
0
    fn fold<B, F>(self, init: B, mut f: F) -> B
2191
0
    where
2192
0
        Self: Sized,
2193
0
        F: FnMut(B, Self::Item) -> B,
2194
0
    {
2195
0
        self.inner
2196
0
            .fold(init, |acc, bucket| unsafe { f(acc, bucket.as_mut()) })
2197
0
    }
2198
}
2199
2200
impl<T> FusedIterator for IterHashMut<'_, T> {}
2201
2202
impl<T> fmt::Debug for IterHashMut<'_, T>
2203
where
2204
    T: fmt::Debug,
2205
{
2206
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2207
0
        f.debug_list()
2208
0
            .entries(IterHash {
2209
0
                inner: self.inner.clone(),
2210
0
                marker: PhantomData,
2211
0
            })
2212
0
            .finish()
2213
0
    }
2214
}
2215
2216
/// An owning iterator over the entries of a `HashTable` in arbitrary order.
2217
/// The iterator element type is `T`.
2218
///
2219
/// This `struct` is created by the [`into_iter`] method on [`HashTable`]
2220
/// (provided by the [`IntoIterator`] trait). See its documentation for more.
2221
/// The table cannot be used after calling that method.
2222
///
2223
/// [`into_iter`]: struct.HashTable.html#method.into_iter
2224
/// [`HashTable`]: struct.HashTable.html
2225
/// [`IntoIterator`]: https://doc.rust-lang.org/core/iter/trait.IntoIterator.html
2226
pub struct IntoIter<T, A = Global>
2227
where
2228
    A: Allocator,
2229
{
2230
    inner: RawIntoIter<T, A>,
2231
}
2232
2233
impl<T, A: Allocator> Default for IntoIter<T, A> {
2234
    #[cfg_attr(feature = "inline-more", inline)]
2235
0
    fn default() -> Self {
2236
0
        IntoIter {
2237
0
            inner: Default::default(),
2238
0
        }
2239
0
    }
2240
}
2241
2242
impl<T, A> Iterator for IntoIter<T, A>
2243
where
2244
    A: Allocator,
2245
{
2246
    type Item = T;
2247
2248
0
    fn next(&mut self) -> Option<Self::Item> {
2249
0
        self.inner.next()
2250
0
    }
2251
2252
0
    fn size_hint(&self) -> (usize, Option<usize>) {
2253
0
        self.inner.size_hint()
2254
0
    }
2255
2256
0
    fn fold<B, F>(self, init: B, f: F) -> B
2257
0
    where
2258
0
        Self: Sized,
2259
0
        F: FnMut(B, Self::Item) -> B,
2260
0
    {
2261
0
        self.inner.fold(init, f)
2262
0
    }
2263
}
2264
2265
impl<T, A> ExactSizeIterator for IntoIter<T, A>
2266
where
2267
    A: Allocator,
2268
{
2269
0
    fn len(&self) -> usize {
2270
0
        self.inner.len()
2271
0
    }
2272
}
2273
2274
impl<T, A> FusedIterator for IntoIter<T, A> where A: Allocator {}
2275
2276
impl<T, A> fmt::Debug for IntoIter<T, A>
2277
where
2278
    T: fmt::Debug,
2279
    A: Allocator,
2280
{
2281
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2282
0
        f.debug_list()
2283
0
            .entries(Iter {
2284
0
                inner: self.inner.iter(),
2285
0
                marker: PhantomData,
2286
0
            })
2287
0
            .finish()
2288
0
    }
2289
}
2290
2291
/// A draining iterator over the items of a `HashTable`.
2292
///
2293
/// This `struct` is created by the [`drain`] method on [`HashTable`].
2294
/// See its documentation for more.
2295
///
2296
/// [`HashTable`]: struct.HashTable.html
2297
/// [`drain`]: struct.HashTable.html#method.drain
2298
pub struct Drain<'a, T, A: Allocator = Global> {
2299
    inner: RawDrain<'a, T, A>,
2300
}
2301
2302
impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
2303
    type Item = T;
2304
2305
0
    fn next(&mut self) -> Option<T> {
2306
0
        self.inner.next()
2307
0
    }
2308
2309
0
    fn size_hint(&self) -> (usize, Option<usize>) {
2310
0
        self.inner.size_hint()
2311
0
    }
2312
2313
0
    fn fold<B, F>(self, init: B, f: F) -> B
2314
0
    where
2315
0
        Self: Sized,
2316
0
        F: FnMut(B, Self::Item) -> B,
2317
0
    {
2318
0
        self.inner.fold(init, f)
2319
0
    }
2320
}
2321
2322
impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> {
2323
0
    fn len(&self) -> usize {
2324
0
        self.inner.len()
2325
0
    }
2326
}
2327
2328
impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {}
2329
2330
impl<T: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, T, A> {
2331
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2332
0
        f.debug_list()
2333
0
            .entries(Iter {
2334
0
                inner: self.inner.iter(),
2335
0
                marker: PhantomData,
2336
0
            })
2337
0
            .finish()
2338
0
    }
2339
}
2340
2341
/// A draining iterator over entries of a `HashTable` which don't satisfy the predicate `f`.
2342
///
2343
/// This `struct` is created by [`HashTable::extract_if`]. See its
2344
/// documentation for more.
2345
#[must_use = "Iterators are lazy unless consumed"]
2346
pub struct ExtractIf<'a, T, F, A: Allocator = Global> {
2347
    f: F,
2348
    inner: RawExtractIf<'a, T, A>,
2349
}
2350
2351
impl<T, F, A: Allocator> Iterator for ExtractIf<'_, T, F, A>
2352
where
2353
    F: FnMut(&mut T) -> bool,
2354
{
2355
    type Item = T;
2356
2357
    #[inline]
2358
0
    fn next(&mut self) -> Option<Self::Item> {
2359
0
        self.inner.next(|val| (self.f)(val))
2360
0
    }
2361
2362
    #[inline]
2363
0
    fn size_hint(&self) -> (usize, Option<usize>) {
2364
0
        (0, self.inner.iter.size_hint().1)
2365
0
    }
2366
}
2367
2368
impl<T, F, A: Allocator> FusedIterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool {}
2369
2370
#[cfg(test)]
2371
mod tests {
2372
    use super::HashTable;
2373
2374
    #[test]
2375
    fn test_allocation_info() {
2376
        assert_eq!(HashTable::<()>::new().allocation_size(), 0);
2377
        assert_eq!(HashTable::<u32>::new().allocation_size(), 0);
2378
        assert!(HashTable::<u32>::with_capacity(1).allocation_size() > core::mem::size_of::<u32>());
2379
    }
2380
}