hashbrown/raw/mod.rs
1use crate::alloc::alloc::{handle_alloc_error, Layout};
2use crate::control::{BitMaskIter, Group, Tag, TagSliceExt};
3use crate::scopeguard::{guard, ScopeGuard};
4use crate::util::{invalid_mut, likely, unlikely};
5use crate::TryReserveError;
6use core::array;
7use core::iter::FusedIterator;
8use core::marker::PhantomData;
9use core::mem;
10use core::ptr::NonNull;
11use core::slice;
12use core::{hint, ptr};
13
14mod alloc;
15pub(crate) use self::alloc::{do_alloc, Allocator, Global};
16
17#[inline]
18unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
19 to.offset_from(from) as usize
20}
21
22/// Whether memory allocation errors should return an error or abort.
23#[derive(Copy, Clone)]
24enum Fallibility {
25 Fallible,
26 Infallible,
27}
28
29impl Fallibility {
30 /// Error to return on capacity overflow.
31 #[cfg_attr(feature = "inline-more", inline)]
32 fn capacity_overflow(self) -> TryReserveError {
33 match self {
34 Fallibility::Fallible => TryReserveError::CapacityOverflow,
35 Fallibility::Infallible => panic!("Hash table capacity overflow"),
36 }
37 }
38
39 /// Error to return on allocation error.
40 #[cfg_attr(feature = "inline-more", inline)]
41 fn alloc_err(self, layout: Layout) -> TryReserveError {
42 match self {
43 Fallibility::Fallible => TryReserveError::AllocError { layout },
44 Fallibility::Infallible => handle_alloc_error(layout),
45 }
46 }
47}
48
49trait SizedTypeProperties: Sized {
50 const IS_ZERO_SIZED: bool = mem::size_of::<Self>() == 0;
51 const NEEDS_DROP: bool = mem::needs_drop::<Self>();
52}
53
54impl<T> SizedTypeProperties for T {}
55
56/// Primary hash function, used to select the initial bucket to probe from.
57#[inline]
58#[allow(clippy::cast_possible_truncation)]
59fn h1(hash: u64) -> usize {
60 // On 32-bit platforms we simply ignore the higher hash bits.
61 hash as usize
62}
63
64/// Probe sequence based on triangular numbers, which is guaranteed (since our
65/// table size is a power of two) to visit every group of elements exactly once.
66///
67/// A triangular probe has us jump by 1 more group every time. So first we
68/// jump by 1 group (meaning we just continue our linear scan), then 2 groups
69/// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on.
70///
71/// Proof that the probe will visit every group in the table:
72/// <https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/>
73#[derive(Clone)]
74struct ProbeSeq {
75 pos: usize,
76 stride: usize,
77}
78
79impl ProbeSeq {
80 #[inline]
81 fn move_next(&mut self, bucket_mask: usize) {
82 // We should have found an empty bucket by now and ended the probe.
83 debug_assert!(
84 self.stride <= bucket_mask,
85 "Went past end of probe sequence"
86 );
87
88 self.stride += Group::WIDTH;
89 self.pos += self.stride;
90 self.pos &= bucket_mask;
91 }
92}
93
94/// Returns the number of buckets needed to hold the given number of items,
95/// taking the maximum load factor into account.
96///
97/// Returns `None` if an overflow occurs.
98// Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258
99#[cfg_attr(target_os = "emscripten", inline(never))]
100#[cfg_attr(not(target_os = "emscripten"), inline)]
101fn capacity_to_buckets(cap: usize) -> Option<usize> {
102 debug_assert_ne!(cap, 0);
103
104 // For small tables we require at least 1 empty bucket so that lookups are
105 // guaranteed to terminate if an element doesn't exist in the table.
106 if cap < 8 {
107 // We don't bother with a table size of 2 buckets since that can only
108 // hold a single element. Instead we skip directly to a 4 bucket table
109 // which can hold 3 elements.
110 return Some(if cap < 4 { 4 } else { 8 });
111 }
112
113 // Otherwise require 1/8 buckets to be empty (87.5% load)
114 //
115 // Be careful when modifying this, calculate_layout relies on the
116 // overflow check here.
117 let adjusted_cap = cap.checked_mul(8)? / 7;
118
119 // Any overflows will have been caught by the checked_mul. Also, any
120 // rounding errors from the division above will be cleaned up by
121 // next_power_of_two (which can't overflow because of the previous division).
122 Some(adjusted_cap.next_power_of_two())
123}
124
125/// Returns the maximum effective capacity for the given bucket mask, taking
126/// the maximum load factor into account.
127#[inline]
128fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
129 if bucket_mask < 8 {
130 // For tables with 1/2/4/8 buckets, we always reserve one empty slot.
131 // Keep in mind that the bucket mask is one less than the bucket count.
132 bucket_mask
133 } else {
134 // For larger tables we reserve 12.5% of the slots as empty.
135 ((bucket_mask + 1) / 8) * 7
136 }
137}
138
139/// Helper which allows the max calculation for `ctrl_align` to be statically computed for each `T`
140/// while keeping the rest of `calculate_layout_for` independent of `T`
141#[derive(Copy, Clone)]
142struct TableLayout {
143 size: usize,
144 ctrl_align: usize,
145}
146
147impl TableLayout {
148 #[inline]
149 const fn new<T>() -> Self {
150 let layout = Layout::new::<T>();
151 Self {
152 size: layout.size(),
153 ctrl_align: if layout.align() > Group::WIDTH {
154 layout.align()
155 } else {
156 Group::WIDTH
157 },
158 }
159 }
160
161 #[inline]
162 fn calculate_layout_for(self, buckets: usize) -> Option<(Layout, usize)> {
163 debug_assert!(buckets.is_power_of_two());
164
165 let TableLayout { size, ctrl_align } = self;
166 // Manual layout calculation since Layout methods are not yet stable.
167 let ctrl_offset =
168 size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1);
169 let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?;
170
171 // We need an additional check to ensure that the allocation doesn't
172 // exceed `isize::MAX` (https://github.com/rust-lang/rust/pull/95295).
173 if len > isize::MAX as usize - (ctrl_align - 1) {
174 return None;
175 }
176
177 Some((
178 unsafe { Layout::from_size_align_unchecked(len, ctrl_align) },
179 ctrl_offset,
180 ))
181 }
182}
183
184/// A reference to an empty bucket into which an can be inserted.
185pub struct InsertSlot {
186 index: usize,
187}
188
189/// A reference to a hash table bucket containing a `T`.
190///
191/// This is usually just a pointer to the element itself. However if the element
192/// is a ZST, then we instead track the index of the element in the table so
193/// that `erase` works properly.
194pub struct Bucket<T> {
195 // Actually it is pointer to next element than element itself
196 // this is needed to maintain pointer arithmetic invariants
197 // keeping direct pointer to element introduces difficulty.
198 // Using `NonNull` for variance and niche layout
199 ptr: NonNull<T>,
200}
201
202// This Send impl is needed for rayon support. This is safe since Bucket is
203// never exposed in a public API.
204unsafe impl<T> Send for Bucket<T> {}
205
206impl<T> Clone for Bucket<T> {
207 #[inline]
208 fn clone(&self) -> Self {
209 Self { ptr: self.ptr }
210 }
211}
212
213impl<T> Bucket<T> {
214 /// Creates a [`Bucket`] that contain pointer to the data.
215 /// The pointer calculation is performed by calculating the
216 /// offset from given `base` pointer (convenience for
217 /// `base.as_ptr().sub(index)`).
218 ///
219 /// `index` is in units of `T`; e.g., an `index` of 3 represents a pointer
220 /// offset of `3 * size_of::<T>()` bytes.
221 ///
222 /// If the `T` is a ZST, then we instead track the index of the element
223 /// in the table so that `erase` works properly (return
224 /// `NonNull::new_unchecked((index + 1) as *mut T)`)
225 ///
226 /// # Safety
227 ///
228 /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
229 /// from the safety rules for [`<*mut T>::sub`] method of `*mut T` and the safety
230 /// rules of [`NonNull::new_unchecked`] function.
231 ///
232 /// Thus, in order to uphold the safety contracts for the [`<*mut T>::sub`] method
233 /// and [`NonNull::new_unchecked`] function, as well as for the correct
234 /// logic of the work of this crate, the following rules are necessary and
235 /// sufficient:
236 ///
237 /// * the `base` pointer must not be `dangling` and must points to the
238 /// end of the first `value element` from the `data part` of the table, i.e.
239 /// must be the pointer that returned by [`RawTable::data_end`] or by
240 /// [`RawTableInner::data_end<T>`];
241 ///
242 /// * `index` must not be greater than `RawTableInner.bucket_mask`, i.e.
243 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)`
244 /// must be no greater than the number returned by the function
245 /// [`RawTable::buckets`] or [`RawTableInner::buckets`].
246 ///
247 /// If `mem::size_of::<T>() == 0`, then the only requirement is that the
248 /// `index` must not be greater than `RawTableInner.bucket_mask`, i.e.
249 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)`
250 /// must be no greater than the number returned by the function
251 /// [`RawTable::buckets`] or [`RawTableInner::buckets`].
252 ///
253 /// [`Bucket`]: crate::raw::Bucket
254 /// [`<*mut T>::sub`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub-1
255 /// [`NonNull::new_unchecked`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.new_unchecked
256 /// [`RawTable::data_end`]: crate::raw::RawTable::data_end
257 /// [`RawTableInner::data_end<T>`]: RawTableInner::data_end<T>
258 /// [`RawTable::buckets`]: crate::raw::RawTable::buckets
259 /// [`RawTableInner::buckets`]: RawTableInner::buckets
260 #[inline]
261 unsafe fn from_base_index(base: NonNull<T>, index: usize) -> Self {
262 // If mem::size_of::<T>() != 0 then return a pointer to an `element` in
263 // the data part of the table (we start counting from "0", so that
264 // in the expression T[last], the "last" index actually one less than the
265 // "buckets" number in the table, i.e. "last = RawTableInner.bucket_mask"):
266 //
267 // `from_base_index(base, 1).as_ptr()` returns a pointer that
268 // points here in the data part of the table
269 // (to the start of T1)
270 // |
271 // | `base: NonNull<T>` must point here
272 // | (to the end of T0 or to the start of C0)
273 // v v
274 // [Padding], Tlast, ..., |T1|, T0, |C0, C1, ..., Clast
275 // ^
276 // `from_base_index(base, 1)` returns a pointer
277 // that points here in the data part of the table
278 // (to the end of T1)
279 //
280 // where: T0...Tlast - our stored data; C0...Clast - control bytes
281 // or metadata for data.
282 let ptr = if T::IS_ZERO_SIZED {
283 // won't overflow because index must be less than length (bucket_mask)
284 // and bucket_mask is guaranteed to be less than `isize::MAX`
285 // (see TableLayout::calculate_layout_for method)
286 invalid_mut(index + 1)
287 } else {
288 base.as_ptr().sub(index)
289 };
290 Self {
291 ptr: NonNull::new_unchecked(ptr),
292 }
293 }
294
295 /// Calculates the index of a [`Bucket`] as distance between two pointers
296 /// (convenience for `base.as_ptr().offset_from(self.ptr.as_ptr()) as usize`).
297 /// The returned value is in units of T: the distance in bytes divided by
298 /// [`core::mem::size_of::<T>()`].
299 ///
300 /// If the `T` is a ZST, then we return the index of the element in
301 /// the table so that `erase` works properly (return `self.ptr.as_ptr() as usize - 1`).
302 ///
303 /// This function is the inverse of [`from_base_index`].
304 ///
305 /// # Safety
306 ///
307 /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
308 /// from the safety rules for [`<*const T>::offset_from`] method of `*const T`.
309 ///
310 /// Thus, in order to uphold the safety contracts for [`<*const T>::offset_from`]
311 /// method, as well as for the correct logic of the work of this crate, the
312 /// following rules are necessary and sufficient:
313 ///
314 /// * `base` contained pointer must not be `dangling` and must point to the
315 /// end of the first `element` from the `data part` of the table, i.e.
316 /// must be a pointer that returns by [`RawTable::data_end`] or by
317 /// [`RawTableInner::data_end<T>`];
318 ///
319 /// * `self` also must not contain dangling pointer;
320 ///
321 /// * both `self` and `base` must be created from the same [`RawTable`]
322 /// (or [`RawTableInner`]).
323 ///
324 /// If `mem::size_of::<T>() == 0`, this function is always safe.
325 ///
326 /// [`Bucket`]: crate::raw::Bucket
327 /// [`from_base_index`]: crate::raw::Bucket::from_base_index
328 /// [`RawTable::data_end`]: crate::raw::RawTable::data_end
329 /// [`RawTableInner::data_end<T>`]: RawTableInner::data_end<T>
330 /// [`RawTable`]: crate::raw::RawTable
331 /// [`RawTableInner`]: RawTableInner
332 /// [`<*const T>::offset_from`]: https://doc.rust-lang.org/nightly/core/primitive.pointer.html#method.offset_from
333 #[inline]
334 unsafe fn to_base_index(&self, base: NonNull<T>) -> usize {
335 // If mem::size_of::<T>() != 0 then return an index under which we used to store the
336 // `element` in the data part of the table (we start counting from "0", so
337 // that in the expression T[last], the "last" index actually is one less than the
338 // "buckets" number in the table, i.e. "last = RawTableInner.bucket_mask").
339 // For example for 5th element in table calculation is performed like this:
340 //
341 // mem::size_of::<T>()
342 // |
343 // | `self = from_base_index(base, 5)` that returns pointer
344 // | that points here in the data part of the table
345 // | (to the end of T5)
346 // | | `base: NonNull<T>` must point here
347 // v | (to the end of T0 or to the start of C0)
348 // /???\ v v
349 // [Padding], Tlast, ..., |T10|, ..., T5|, T4, T3, T2, T1, T0, |C0, C1, C2, C3, C4, C5, ..., C10, ..., Clast
350 // \__________ __________/
351 // \/
352 // `bucket.to_base_index(base)` = 5
353 // (base.as_ptr() as usize - self.ptr.as_ptr() as usize) / mem::size_of::<T>()
354 //
355 // where: T0...Tlast - our stored data; C0...Clast - control bytes or metadata for data.
356 if T::IS_ZERO_SIZED {
357 // this can not be UB
358 self.ptr.as_ptr() as usize - 1
359 } else {
360 offset_from(base.as_ptr(), self.ptr.as_ptr())
361 }
362 }
363
364 /// Acquires the underlying raw pointer `*mut T` to `data`.
365 ///
366 /// # Note
367 ///
368 /// If `T` is not [`Copy`], do not use `*mut T` methods that can cause calling the
369 /// destructor of `T` (for example the [`<*mut T>::drop_in_place`] method), because
370 /// for properly dropping the data we also need to clear `data` control bytes. If we
371 /// drop data, but do not clear `data control byte` it leads to double drop when
372 /// [`RawTable`] goes out of scope.
373 ///
374 /// If you modify an already initialized `value`, so [`Hash`] and [`Eq`] on the new
375 /// `T` value and its borrowed form *must* match those for the old `T` value, as the map
376 /// will not re-evaluate where the new value should go, meaning the value may become
377 /// "lost" if their location does not reflect their state.
378 ///
379 /// [`RawTable`]: crate::raw::RawTable
380 /// [`<*mut T>::drop_in_place`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.drop_in_place
381 /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
382 /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
383 #[inline]
384 pub fn as_ptr(&self) -> *mut T {
385 if T::IS_ZERO_SIZED {
386 // Just return an arbitrary ZST pointer which is properly aligned
387 // invalid pointer is good enough for ZST
388 invalid_mut(mem::align_of::<T>())
389 } else {
390 unsafe { self.ptr.as_ptr().sub(1) }
391 }
392 }
393
394 /// Acquires the underlying non-null pointer `*mut T` to `data`.
395 #[inline]
396 fn as_non_null(&self) -> NonNull<T> {
397 // SAFETY: `self.ptr` is already a `NonNull`
398 unsafe { NonNull::new_unchecked(self.as_ptr()) }
399 }
400
401 /// Create a new [`Bucket`] that is offset from the `self` by the given
402 /// `offset`. The pointer calculation is performed by calculating the
403 /// offset from `self` pointer (convenience for `self.ptr.as_ptr().sub(offset)`).
404 /// This function is used for iterators.
405 ///
406 /// `offset` is in units of `T`; e.g., a `offset` of 3 represents a pointer
407 /// offset of `3 * size_of::<T>()` bytes.
408 ///
409 /// # Safety
410 ///
411 /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived
412 /// from the safety rules for [`<*mut T>::sub`] method of `*mut T` and safety
413 /// rules of [`NonNull::new_unchecked`] function.
414 ///
415 /// Thus, in order to uphold the safety contracts for [`<*mut T>::sub`] method
416 /// and [`NonNull::new_unchecked`] function, as well as for the correct
417 /// logic of the work of this crate, the following rules are necessary and
418 /// sufficient:
419 ///
420 /// * `self` contained pointer must not be `dangling`;
421 ///
422 /// * `self.to_base_index() + offset` must not be greater than `RawTableInner.bucket_mask`,
423 /// i.e. `(self.to_base_index() + offset) <= RawTableInner.bucket_mask` or, in other
424 /// words, `self.to_base_index() + offset + 1` must be no greater than the number returned
425 /// by the function [`RawTable::buckets`] or [`RawTableInner::buckets`].
426 ///
427 /// If `mem::size_of::<T>() == 0`, then the only requirement is that the
428 /// `self.to_base_index() + offset` must not be greater than `RawTableInner.bucket_mask`,
429 /// i.e. `(self.to_base_index() + offset) <= RawTableInner.bucket_mask` or, in other words,
430 /// `self.to_base_index() + offset + 1` must be no greater than the number returned by the
431 /// function [`RawTable::buckets`] or [`RawTableInner::buckets`].
432 ///
433 /// [`Bucket`]: crate::raw::Bucket
434 /// [`<*mut T>::sub`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.sub-1
435 /// [`NonNull::new_unchecked`]: https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.new_unchecked
436 /// [`RawTable::buckets`]: crate::raw::RawTable::buckets
437 /// [`RawTableInner::buckets`]: RawTableInner::buckets
438 #[inline]
439 unsafe fn next_n(&self, offset: usize) -> Self {
440 let ptr = if T::IS_ZERO_SIZED {
441 // invalid pointer is good enough for ZST
442 invalid_mut(self.ptr.as_ptr() as usize + offset)
443 } else {
444 self.ptr.as_ptr().sub(offset)
445 };
446 Self {
447 ptr: NonNull::new_unchecked(ptr),
448 }
449 }
450
451 /// Executes the destructor (if any) of the pointed-to `data`.
452 ///
453 /// # Safety
454 ///
455 /// See [`ptr::drop_in_place`] for safety concerns.
456 ///
457 /// You should use [`RawTable::erase`] instead of this function,
458 /// or be careful with calling this function directly, because for
459 /// properly dropping the data we need also clear `data` control bytes.
460 /// If we drop data, but do not erase `data control byte` it leads to
461 /// double drop when [`RawTable`] goes out of scope.
462 ///
463 /// [`ptr::drop_in_place`]: https://doc.rust-lang.org/core/ptr/fn.drop_in_place.html
464 /// [`RawTable`]: crate::raw::RawTable
465 /// [`RawTable::erase`]: crate::raw::RawTable::erase
466 #[cfg_attr(feature = "inline-more", inline)]
467 pub(crate) unsafe fn drop(&self) {
468 self.as_ptr().drop_in_place();
469 }
470
471 /// Reads the `value` from `self` without moving it. This leaves the
472 /// memory in `self` unchanged.
473 ///
474 /// # Safety
475 ///
476 /// See [`ptr::read`] for safety concerns.
477 ///
478 /// You should use [`RawTable::remove`] instead of this function,
479 /// or be careful with calling this function directly, because compiler
480 /// calls its destructor when the read `value` goes out of scope. It
481 /// can cause double dropping when [`RawTable`] goes out of scope,
482 /// because of not erased `data control byte`.
483 ///
484 /// [`ptr::read`]: https://doc.rust-lang.org/core/ptr/fn.read.html
485 /// [`RawTable`]: crate::raw::RawTable
486 /// [`RawTable::remove`]: crate::raw::RawTable::remove
487 #[inline]
488 pub(crate) unsafe fn read(&self) -> T {
489 self.as_ptr().read()
490 }
491
492 /// Overwrites a memory location with the given `value` without reading
493 /// or dropping the old value (like [`ptr::write`] function).
494 ///
495 /// # Safety
496 ///
497 /// See [`ptr::write`] for safety concerns.
498 ///
499 /// # Note
500 ///
501 /// [`Hash`] and [`Eq`] on the new `T` value and its borrowed form *must* match
502 /// those for the old `T` value, as the map will not re-evaluate where the new
503 /// value should go, meaning the value may become "lost" if their location
504 /// does not reflect their state.
505 ///
506 /// [`ptr::write`]: https://doc.rust-lang.org/core/ptr/fn.write.html
507 /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
508 /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
509 #[inline]
510 pub(crate) unsafe fn write(&self, val: T) {
511 self.as_ptr().write(val);
512 }
513
514 /// Returns a shared immutable reference to the `value`.
515 ///
516 /// # Safety
517 ///
518 /// See [`NonNull::as_ref`] for safety concerns.
519 ///
520 /// [`NonNull::as_ref`]: https://doc.rust-lang.org/core/ptr/struct.NonNull.html#method.as_ref
521 #[inline]
522 pub unsafe fn as_ref<'a>(&self) -> &'a T {
523 &*self.as_ptr()
524 }
525
526 /// Returns a unique mutable reference to the `value`.
527 ///
528 /// # Safety
529 ///
530 /// See [`NonNull::as_mut`] for safety concerns.
531 ///
532 /// # Note
533 ///
534 /// [`Hash`] and [`Eq`] on the new `T` value and its borrowed form *must* match
535 /// those for the old `T` value, as the map will not re-evaluate where the new
536 /// value should go, meaning the value may become "lost" if their location
537 /// does not reflect their state.
538 ///
539 /// [`NonNull::as_mut`]: https://doc.rust-lang.org/core/ptr/struct.NonNull.html#method.as_mut
540 /// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
541 /// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
542 #[inline]
543 pub unsafe fn as_mut<'a>(&self) -> &'a mut T {
544 &mut *self.as_ptr()
545 }
546}
547
548/// A raw hash table with an unsafe API.
549pub struct RawTable<T, A: Allocator = Global> {
550 table: RawTableInner,
551 alloc: A,
552 // Tell dropck that we own instances of T.
553 marker: PhantomData<T>,
554}
555
556/// Non-generic part of `RawTable` which allows functions to be instantiated only once regardless
557/// of how many different key-value types are used.
558struct RawTableInner {
559 // Mask to get an index from a hash value. The value is one less than the
560 // number of buckets in the table.
561 bucket_mask: usize,
562
563 // [Padding], T_n, ..., T1, T0, C0, C1, ...
564 // ^ points here
565 ctrl: NonNull<u8>,
566
567 // Number of elements that can be inserted before we need to grow the table
568 growth_left: usize,
569
570 // Number of elements in the table, only really used by len()
571 items: usize,
572}
573
574impl<T> RawTable<T, Global> {
575 /// Creates a new empty hash table without allocating any memory.
576 ///
577 /// In effect this returns a table with exactly 1 bucket. However we can
578 /// leave the data pointer dangling since that bucket is never written to
579 /// due to our load factor forcing us to always have at least 1 free bucket.
580 #[inline]
581 #[cfg_attr(feature = "rustc-dep-of-std", rustc_const_stable_indirect)]
582 pub const fn new() -> Self {
583 Self {
584 table: RawTableInner::NEW,
585 alloc: Global,
586 marker: PhantomData,
587 }
588 }
589
590 /// Allocates a new hash table with at least enough capacity for inserting
591 /// the given number of elements without reallocating.
592 pub fn with_capacity(capacity: usize) -> Self {
593 Self::with_capacity_in(capacity, Global)
594 }
595}
596
597impl<T, A: Allocator> RawTable<T, A> {
598 const TABLE_LAYOUT: TableLayout = TableLayout::new::<T>();
599
600 /// Creates a new empty hash table without allocating any memory, using the
601 /// given allocator.
602 ///
603 /// In effect this returns a table with exactly 1 bucket. However we can
604 /// leave the data pointer dangling since that bucket is never written to
605 /// due to our load factor forcing us to always have at least 1 free bucket.
606 #[inline]
607 #[cfg_attr(feature = "rustc-dep-of-std", rustc_const_stable_indirect)]
608 pub const fn new_in(alloc: A) -> Self {
609 Self {
610 table: RawTableInner::NEW,
611 alloc,
612 marker: PhantomData,
613 }
614 }
615
616 /// Allocates a new hash table with the given number of buckets.
617 ///
618 /// The control bytes are left uninitialized.
619 #[cfg_attr(feature = "inline-more", inline)]
620 unsafe fn new_uninitialized(
621 alloc: A,
622 buckets: usize,
623 fallibility: Fallibility,
624 ) -> Result<Self, TryReserveError> {
625 debug_assert!(buckets.is_power_of_two());
626
627 Ok(Self {
628 table: RawTableInner::new_uninitialized(
629 &alloc,
630 Self::TABLE_LAYOUT,
631 buckets,
632 fallibility,
633 )?,
634 alloc,
635 marker: PhantomData,
636 })
637 }
638
639 /// Allocates a new hash table using the given allocator, with at least enough capacity for
640 /// inserting the given number of elements without reallocating.
641 pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
642 Self {
643 table: RawTableInner::with_capacity(&alloc, Self::TABLE_LAYOUT, capacity),
644 alloc,
645 marker: PhantomData,
646 }
647 }
648
649 /// Returns a reference to the underlying allocator.
650 #[inline]
651 pub fn allocator(&self) -> &A {
652 &self.alloc
653 }
654
655 /// Returns pointer to one past last `data` element in the table as viewed from
656 /// the start point of the allocation.
657 ///
658 /// The caller must ensure that the `RawTable` outlives the returned [`NonNull<T>`],
659 /// otherwise using it may result in [`undefined behavior`].
660 ///
661 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
662 #[inline]
663 pub fn data_end(&self) -> NonNull<T> {
664 // `self.table.ctrl.cast()` returns pointer that
665 // points here (to the end of `T0`)
666 // ∨
667 // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
668 // \________ ________/
669 // \/
670 // `n = buckets - 1`, i.e. `RawTable::buckets() - 1`
671 //
672 // where: T0...T_n - our stored data;
673 // CT0...CT_n - control bytes or metadata for `data`.
674 // CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
675 // with loading `Group` bytes from the heap works properly, even if the result
676 // of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
677 // `RawTableInner::set_ctrl` function.
678 //
679 // P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
680 // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
681 self.table.ctrl.cast()
682 }
683
684 /// Returns pointer to start of data table.
685 #[inline]
686 #[cfg(feature = "nightly")]
687 pub unsafe fn data_start(&self) -> NonNull<T> {
688 NonNull::new_unchecked(self.data_end().as_ptr().wrapping_sub(self.buckets()))
689 }
690
691 /// Returns the total amount of memory allocated internally by the hash
692 /// table, in bytes.
693 ///
694 /// The returned number is informational only. It is intended to be
695 /// primarily used for memory profiling.
696 #[inline]
697 pub fn allocation_size(&self) -> usize {
698 // SAFETY: We use the same `table_layout` that was used to allocate
699 // this table.
700 unsafe { self.table.allocation_size_or_zero(Self::TABLE_LAYOUT) }
701 }
702
703 /// Returns the index of a bucket from a `Bucket`.
704 #[inline]
705 pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
706 bucket.to_base_index(self.data_end())
707 }
708
709 /// Returns a pointer to an element in the table.
710 ///
711 /// The caller must ensure that the `RawTable` outlives the returned [`Bucket<T>`],
712 /// otherwise using it may result in [`undefined behavior`].
713 ///
714 /// # Safety
715 ///
716 /// If `mem::size_of::<T>() != 0`, then the caller of this function must observe the
717 /// following safety rules:
718 ///
719 /// * The table must already be allocated;
720 ///
721 /// * The `index` must not be greater than the number returned by the [`RawTable::buckets`]
722 /// function, i.e. `(index + 1) <= self.buckets()`.
723 ///
724 /// It is safe to call this function with index of zero (`index == 0`) on a table that has
725 /// not been allocated, but using the returned [`Bucket`] results in [`undefined behavior`].
726 ///
727 /// If `mem::size_of::<T>() == 0`, then the only requirement is that the `index` must
728 /// not be greater than the number returned by the [`RawTable::buckets`] function, i.e.
729 /// `(index + 1) <= self.buckets()`.
730 ///
731 /// [`RawTable::buckets`]: RawTable::buckets
732 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
733 #[inline]
734 pub unsafe fn bucket(&self, index: usize) -> Bucket<T> {
735 // If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
736 // (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
737 // the "buckets" number of our `RawTable`, i.e. "n = RawTable::buckets() - 1"):
738 //
739 // `table.bucket(3).as_ptr()` returns a pointer that points here in the `data`
740 // part of the `RawTable`, i.e. to the start of T3 (see `Bucket::as_ptr`)
741 // |
742 // | `base = self.data_end()` points here
743 // | (to the start of CT0 or to the end of T0)
744 // v v
745 // [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
746 // ^ \__________ __________/
747 // `table.bucket(3)` returns a pointer that points \/
748 // here in the `data` part of the `RawTable` (to additional control bytes
749 // the end of T3) `m = Group::WIDTH - 1`
750 //
751 // where: T0...T_n - our stored data;
752 // CT0...CT_n - control bytes or metadata for `data`;
753 // CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
754 // the heap works properly, even if the result of `h1(hash) & self.table.bucket_mask`
755 // is equal to `self.table.bucket_mask`). See also `RawTableInner::set_ctrl` function.
756 //
757 // P.S. `h1(hash) & self.table.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
758 // of buckets is a power of two, and `self.table.bucket_mask = self.buckets() - 1`.
759 debug_assert_ne!(self.table.bucket_mask, 0);
760 debug_assert!(index < self.buckets());
761 Bucket::from_base_index(self.data_end(), index)
762 }
763
764 /// Erases an element from the table without dropping it.
765 #[cfg_attr(feature = "inline-more", inline)]
766 unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
767 let index = self.bucket_index(item);
768 self.table.erase(index);
769 }
770
771 /// Erases an element from the table, dropping it in place.
772 #[cfg_attr(feature = "inline-more", inline)]
773 #[allow(clippy::needless_pass_by_value)]
774 pub unsafe fn erase(&mut self, item: Bucket<T>) {
775 // Erase the element from the table first since drop might panic.
776 self.erase_no_drop(&item);
777 item.drop();
778 }
779
780 /// Removes an element from the table, returning it.
781 ///
782 /// This also returns an `InsertSlot` pointing to the newly free bucket.
783 #[cfg_attr(feature = "inline-more", inline)]
784 #[allow(clippy::needless_pass_by_value)]
785 pub unsafe fn remove(&mut self, item: Bucket<T>) -> (T, InsertSlot) {
786 self.erase_no_drop(&item);
787 (
788 item.read(),
789 InsertSlot {
790 index: self.bucket_index(&item),
791 },
792 )
793 }
794
795 /// Finds and removes an element from the table, returning it.
796 #[cfg_attr(feature = "inline-more", inline)]
797 pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<T> {
798 // Avoid `Option::map` because it bloats LLVM IR.
799 match self.find(hash, eq) {
800 Some(bucket) => Some(unsafe { self.remove(bucket).0 }),
801 None => None,
802 }
803 }
804
805 /// Marks all table buckets as empty without dropping their contents.
806 #[cfg_attr(feature = "inline-more", inline)]
807 pub fn clear_no_drop(&mut self) {
808 self.table.clear_no_drop();
809 }
810
811 /// Removes all elements from the table without freeing the backing memory.
812 #[cfg_attr(feature = "inline-more", inline)]
813 pub fn clear(&mut self) {
814 if self.is_empty() {
815 // Special case empty table to avoid surprising O(capacity) time.
816 return;
817 }
818 // Ensure that the table is reset even if one of the drops panic
819 let mut self_ = guard(self, |self_| self_.clear_no_drop());
820 unsafe {
821 // SAFETY: ScopeGuard sets to zero the `items` field of the table
822 // even in case of panic during the dropping of the elements so
823 // that there will be no double drop of the elements.
824 self_.table.drop_elements::<T>();
825 }
826 }
827
828 /// Shrinks the table to fit `max(self.len(), min_size)` elements.
829 #[cfg_attr(feature = "inline-more", inline)]
830 pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) {
831 // Calculate the minimal number of elements that we need to reserve
832 // space for.
833 let min_size = usize::max(self.table.items, min_size);
834 if min_size == 0 {
835 let mut old_inner = mem::replace(&mut self.table, RawTableInner::NEW);
836 unsafe {
837 // SAFETY:
838 // 1. We call the function only once;
839 // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
840 // and [`TableLayout`] that were used to allocate this table.
841 // 3. If any elements' drop function panics, then there will only be a memory leak,
842 // because we have replaced the inner table with a new one.
843 old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
844 }
845 return;
846 }
847
848 // Calculate the number of buckets that we need for this number of
849 // elements. If the calculation overflows then the requested bucket
850 // count must be larger than what we have right and nothing needs to be
851 // done.
852 let min_buckets = match capacity_to_buckets(min_size) {
853 Some(buckets) => buckets,
854 None => return,
855 };
856
857 // If we have more buckets than we need, shrink the table.
858 if min_buckets < self.buckets() {
859 // Fast path if the table is empty
860 if self.table.items == 0 {
861 let new_inner =
862 RawTableInner::with_capacity(&self.alloc, Self::TABLE_LAYOUT, min_size);
863 let mut old_inner = mem::replace(&mut self.table, new_inner);
864 unsafe {
865 // SAFETY:
866 // 1. We call the function only once;
867 // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
868 // and [`TableLayout`] that were used to allocate this table.
869 // 3. If any elements' drop function panics, then there will only be a memory leak,
870 // because we have replaced the inner table with a new one.
871 old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
872 }
873 } else {
874 // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
875 unsafe {
876 // SAFETY:
877 // 1. We know for sure that `min_size >= self.table.items`.
878 // 2. The [`RawTableInner`] must already have properly initialized control bytes since
879 // we will never expose RawTable::new_uninitialized in a public API.
880 if self
881 .resize(min_size, hasher, Fallibility::Infallible)
882 .is_err()
883 {
884 // SAFETY: The result of calling the `resize` function cannot be an error
885 // because `fallibility == Fallibility::Infallible.
886 hint::unreachable_unchecked()
887 }
888 }
889 }
890 }
891 }
892
893 /// Ensures that at least `additional` items can be inserted into the table
894 /// without reallocation.
895 #[cfg_attr(feature = "inline-more", inline)]
896 pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) {
897 if unlikely(additional > self.table.growth_left) {
898 // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
899 unsafe {
900 // SAFETY: The [`RawTableInner`] must already have properly initialized control
901 // bytes since we will never expose RawTable::new_uninitialized in a public API.
902 if self
903 .reserve_rehash(additional, hasher, Fallibility::Infallible)
904 .is_err()
905 {
906 // SAFETY: All allocation errors will be caught inside `RawTableInner::reserve_rehash`.
907 hint::unreachable_unchecked()
908 }
909 }
910 }
911 }
912
913 /// Tries to ensure that at least `additional` items can be inserted into
914 /// the table without reallocation.
915 #[cfg_attr(feature = "inline-more", inline)]
916 pub fn try_reserve(
917 &mut self,
918 additional: usize,
919 hasher: impl Fn(&T) -> u64,
920 ) -> Result<(), TryReserveError> {
921 if additional > self.table.growth_left {
922 // SAFETY: The [`RawTableInner`] must already have properly initialized control
923 // bytes since we will never expose RawTable::new_uninitialized in a public API.
924 unsafe { self.reserve_rehash(additional, hasher, Fallibility::Fallible) }
925 } else {
926 Ok(())
927 }
928 }
929
930 /// Out-of-line slow path for `reserve` and `try_reserve`.
931 ///
932 /// # Safety
933 ///
934 /// The [`RawTableInner`] must have properly initialized control bytes,
935 /// otherwise calling this function results in [`undefined behavior`]
936 ///
937 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
938 #[cold]
939 #[inline(never)]
940 unsafe fn reserve_rehash(
941 &mut self,
942 additional: usize,
943 hasher: impl Fn(&T) -> u64,
944 fallibility: Fallibility,
945 ) -> Result<(), TryReserveError> {
946 unsafe {
947 // SAFETY:
948 // 1. We know for sure that `alloc` and `layout` matches the [`Allocator`] and
949 // [`TableLayout`] that were used to allocate this table.
950 // 2. The `drop` function is the actual drop function of the elements stored in
951 // the table.
952 // 3. The caller ensures that the control bytes of the `RawTableInner`
953 // are already initialized.
954 self.table.reserve_rehash_inner(
955 &self.alloc,
956 additional,
957 &|table, index| hasher(table.bucket::<T>(index).as_ref()),
958 fallibility,
959 Self::TABLE_LAYOUT,
960 if T::NEEDS_DROP {
961 Some(|ptr| ptr::drop_in_place(ptr as *mut T))
962 } else {
963 None
964 },
965 )
966 }
967 }
968
969 /// Allocates a new table of a different size and moves the contents of the
970 /// current table into it.
971 ///
972 /// # Safety
973 ///
974 /// The [`RawTableInner`] must have properly initialized control bytes,
975 /// otherwise calling this function results in [`undefined behavior`]
976 ///
977 /// The caller of this function must ensure that `capacity >= self.table.items`
978 /// otherwise:
979 ///
980 /// * If `self.table.items != 0`, calling of this function with `capacity`
981 /// equal to 0 (`capacity == 0`) results in [`undefined behavior`].
982 ///
983 /// * If `capacity_to_buckets(capacity) < Group::WIDTH` and
984 /// `self.table.items > capacity_to_buckets(capacity)`
985 /// calling this function results in [`undefined behavior`].
986 ///
987 /// * If `capacity_to_buckets(capacity) >= Group::WIDTH` and
988 /// `self.table.items > capacity_to_buckets(capacity)`
989 /// calling this function are never return (will go into an
990 /// infinite loop).
991 ///
992 /// See [`RawTableInner::find_insert_slot`] for more information.
993 ///
994 /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
995 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
996 unsafe fn resize(
997 &mut self,
998 capacity: usize,
999 hasher: impl Fn(&T) -> u64,
1000 fallibility: Fallibility,
1001 ) -> Result<(), TryReserveError> {
1002 // SAFETY:
1003 // 1. The caller of this function guarantees that `capacity >= self.table.items`.
1004 // 2. We know for sure that `alloc` and `layout` matches the [`Allocator`] and
1005 // [`TableLayout`] that were used to allocate this table.
1006 // 3. The caller ensures that the control bytes of the `RawTableInner`
1007 // are already initialized.
1008 self.table.resize_inner(
1009 &self.alloc,
1010 capacity,
1011 &|table, index| hasher(table.bucket::<T>(index).as_ref()),
1012 fallibility,
1013 Self::TABLE_LAYOUT,
1014 )
1015 }
1016
1017 /// Inserts a new element into the table, and returns its raw bucket.
1018 ///
1019 /// This does not check if the given element already exists in the table.
1020 #[cfg_attr(feature = "inline-more", inline)]
1021 pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
1022 unsafe {
1023 // SAFETY:
1024 // 1. The [`RawTableInner`] must already have properly initialized control bytes since
1025 // we will never expose `RawTable::new_uninitialized` in a public API.
1026 //
1027 // 2. We reserve additional space (if necessary) right after calling this function.
1028 let mut slot = self.table.find_insert_slot(hash);
1029
1030 // We can avoid growing the table once we have reached our load factor if we are replacing
1031 // a tombstone. This works since the number of EMPTY slots does not change in this case.
1032 //
1033 // SAFETY: The function is guaranteed to return [`InsertSlot`] that contains an index
1034 // in the range `0..=self.buckets()`.
1035 let old_ctrl = *self.table.ctrl(slot.index);
1036 if unlikely(self.table.growth_left == 0 && old_ctrl.special_is_empty()) {
1037 self.reserve(1, hasher);
1038 // SAFETY: We know for sure that `RawTableInner` has control bytes
1039 // initialized and that there is extra space in the table.
1040 slot = self.table.find_insert_slot(hash);
1041 }
1042
1043 self.insert_in_slot(hash, slot, value)
1044 }
1045 }
1046
1047 /// Inserts a new element into the table, and returns a mutable reference to it.
1048 ///
1049 /// This does not check if the given element already exists in the table.
1050 #[cfg_attr(feature = "inline-more", inline)]
1051 pub fn insert_entry(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> &mut T {
1052 unsafe { self.insert(hash, value, hasher).as_mut() }
1053 }
1054
1055 /// Inserts a new element into the table, without growing the table.
1056 ///
1057 /// There must be enough space in the table to insert the new element.
1058 ///
1059 /// This does not check if the given element already exists in the table.
1060 #[cfg_attr(feature = "inline-more", inline)]
1061 #[cfg(feature = "rustc-internal-api")]
1062 pub unsafe fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> {
1063 let (index, old_ctrl) = self.table.prepare_insert_slot(hash);
1064 let bucket = self.table.bucket(index);
1065
1066 // If we are replacing a DELETED entry then we don't need to update
1067 // the load counter.
1068 self.table.growth_left -= old_ctrl.special_is_empty() as usize;
1069
1070 bucket.write(value);
1071 self.table.items += 1;
1072 bucket
1073 }
1074
1075 /// Temporary removes a bucket, applying the given function to the removed
1076 /// element and optionally put back the returned value in the same bucket.
1077 ///
1078 /// Returns `true` if the bucket still contains an element
1079 ///
1080 /// This does not check if the given bucket is actually occupied.
1081 #[cfg_attr(feature = "inline-more", inline)]
1082 pub unsafe fn replace_bucket_with<F>(&mut self, bucket: Bucket<T>, f: F) -> bool
1083 where
1084 F: FnOnce(T) -> Option<T>,
1085 {
1086 let index = self.bucket_index(&bucket);
1087 let old_ctrl = *self.table.ctrl(index);
1088 debug_assert!(self.is_bucket_full(index));
1089 let old_growth_left = self.table.growth_left;
1090 let item = self.remove(bucket).0;
1091 if let Some(new_item) = f(item) {
1092 self.table.growth_left = old_growth_left;
1093 self.table.set_ctrl(index, old_ctrl);
1094 self.table.items += 1;
1095 self.bucket(index).write(new_item);
1096 true
1097 } else {
1098 false
1099 }
1100 }
1101
1102 /// Searches for an element in the table. If the element is not found,
1103 /// returns `Err` with the position of a slot where an element with the
1104 /// same hash could be inserted.
1105 ///
1106 /// This function may resize the table if additional space is required for
1107 /// inserting an element.
1108 #[inline]
1109 pub fn find_or_find_insert_slot(
1110 &mut self,
1111 hash: u64,
1112 mut eq: impl FnMut(&T) -> bool,
1113 hasher: impl Fn(&T) -> u64,
1114 ) -> Result<Bucket<T>, InsertSlot> {
1115 self.reserve(1, hasher);
1116
1117 unsafe {
1118 // SAFETY:
1119 // 1. We know for sure that there is at least one empty `bucket` in the table.
1120 // 2. The [`RawTableInner`] must already have properly initialized control bytes since we will
1121 // never expose `RawTable::new_uninitialized` in a public API.
1122 // 3. The `find_or_find_insert_slot_inner` function returns the `index` of only the full bucket,
1123 // which is in the range `0..self.buckets()` (since there is at least one empty `bucket` in
1124 // the table), so calling `self.bucket(index)` and `Bucket::as_ref` is safe.
1125 match self
1126 .table
1127 .find_or_find_insert_slot_inner(hash, &mut |index| eq(self.bucket(index).as_ref()))
1128 {
1129 // SAFETY: See explanation above.
1130 Ok(index) => Ok(self.bucket(index)),
1131 Err(slot) => Err(slot),
1132 }
1133 }
1134 }
1135
1136 /// Inserts a new element into the table in the given slot, and returns its
1137 /// raw bucket.
1138 ///
1139 /// # Safety
1140 ///
1141 /// `slot` must point to a slot previously returned by
1142 /// `find_or_find_insert_slot`, and no mutation of the table must have
1143 /// occurred since that call.
1144 #[inline]
1145 pub unsafe fn insert_in_slot(&mut self, hash: u64, slot: InsertSlot, value: T) -> Bucket<T> {
1146 let old_ctrl = *self.table.ctrl(slot.index);
1147 self.table.record_item_insert_at(slot.index, old_ctrl, hash);
1148
1149 let bucket = self.bucket(slot.index);
1150 bucket.write(value);
1151 bucket
1152 }
1153
1154 /// Searches for an element in the table.
1155 #[inline]
1156 pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
1157 unsafe {
1158 // SAFETY:
1159 // 1. The [`RawTableInner`] must already have properly initialized control bytes since we
1160 // will never expose `RawTable::new_uninitialized` in a public API.
1161 // 1. The `find_inner` function returns the `index` of only the full bucket, which is in
1162 // the range `0..self.buckets()`, so calling `self.bucket(index)` and `Bucket::as_ref`
1163 // is safe.
1164 let result = self
1165 .table
1166 .find_inner(hash, &mut |index| eq(self.bucket(index).as_ref()));
1167
1168 // Avoid `Option::map` because it bloats LLVM IR.
1169 match result {
1170 // SAFETY: See explanation above.
1171 Some(index) => Some(self.bucket(index)),
1172 None => None,
1173 }
1174 }
1175 }
1176
1177 /// Gets a reference to an element in the table.
1178 #[inline]
1179 pub fn get(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> {
1180 // Avoid `Option::map` because it bloats LLVM IR.
1181 match self.find(hash, eq) {
1182 Some(bucket) => Some(unsafe { bucket.as_ref() }),
1183 None => None,
1184 }
1185 }
1186
1187 /// Gets a mutable reference to an element in the table.
1188 #[inline]
1189 pub fn get_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> {
1190 // Avoid `Option::map` because it bloats LLVM IR.
1191 match self.find(hash, eq) {
1192 Some(bucket) => Some(unsafe { bucket.as_mut() }),
1193 None => None,
1194 }
1195 }
1196
1197 /// Attempts to get mutable references to `N` entries in the table at once.
1198 ///
1199 /// Returns an array of length `N` with the results of each query.
1200 ///
1201 /// At most one mutable reference will be returned to any entry. `None` will be returned if any
1202 /// of the hashes are duplicates. `None` will be returned if the hash is not found.
1203 ///
1204 /// The `eq` argument should be a closure such that `eq(i, k)` returns true if `k` is equal to
1205 /// the `i`th key to be looked up.
1206 pub fn get_many_mut<const N: usize>(
1207 &mut self,
1208 hashes: [u64; N],
1209 eq: impl FnMut(usize, &T) -> bool,
1210 ) -> [Option<&'_ mut T>; N] {
1211 unsafe {
1212 let ptrs = self.get_many_mut_pointers(hashes, eq);
1213
1214 for (i, cur) in ptrs.iter().enumerate() {
1215 if cur.is_some() && ptrs[..i].contains(cur) {
1216 panic!("duplicate keys found");
1217 }
1218 }
1219 // All bucket are distinct from all previous buckets so we're clear to return the result
1220 // of the lookup.
1221
1222 ptrs.map(|ptr| ptr.map(|mut ptr| ptr.as_mut()))
1223 }
1224 }
1225
1226 pub unsafe fn get_many_unchecked_mut<const N: usize>(
1227 &mut self,
1228 hashes: [u64; N],
1229 eq: impl FnMut(usize, &T) -> bool,
1230 ) -> [Option<&'_ mut T>; N] {
1231 let ptrs = self.get_many_mut_pointers(hashes, eq);
1232 ptrs.map(|ptr| ptr.map(|mut ptr| ptr.as_mut()))
1233 }
1234
1235 unsafe fn get_many_mut_pointers<const N: usize>(
1236 &mut self,
1237 hashes: [u64; N],
1238 mut eq: impl FnMut(usize, &T) -> bool,
1239 ) -> [Option<NonNull<T>>; N] {
1240 array::from_fn(|i| {
1241 self.find(hashes[i], |k| eq(i, k))
1242 .map(|cur| cur.as_non_null())
1243 })
1244 }
1245
1246 /// Returns the number of elements the map can hold without reallocating.
1247 ///
1248 /// This number is a lower bound; the table might be able to hold
1249 /// more, but is guaranteed to be able to hold at least this many.
1250 #[inline]
1251 pub fn capacity(&self) -> usize {
1252 self.table.items + self.table.growth_left
1253 }
1254
1255 /// Returns the number of elements in the table.
1256 #[inline]
1257 pub fn len(&self) -> usize {
1258 self.table.items
1259 }
1260
1261 /// Returns `true` if the table contains no elements.
1262 #[inline]
1263 pub fn is_empty(&self) -> bool {
1264 self.len() == 0
1265 }
1266
1267 /// Returns the number of buckets in the table.
1268 #[inline]
1269 pub fn buckets(&self) -> usize {
1270 self.table.bucket_mask + 1
1271 }
1272
1273 /// Checks whether the bucket at `index` is full.
1274 ///
1275 /// # Safety
1276 ///
1277 /// The caller must ensure `index` is less than the number of buckets.
1278 #[inline]
1279 pub unsafe fn is_bucket_full(&self, index: usize) -> bool {
1280 self.table.is_bucket_full(index)
1281 }
1282
1283 /// Returns an iterator over every element in the table. It is up to
1284 /// the caller to ensure that the `RawTable` outlives the `RawIter`.
1285 /// Because we cannot make the `next` method unsafe on the `RawIter`
1286 /// struct, we have to make the `iter` method unsafe.
1287 #[inline]
1288 pub unsafe fn iter(&self) -> RawIter<T> {
1289 // SAFETY:
1290 // 1. The caller must uphold the safety contract for `iter` method.
1291 // 2. The [`RawTableInner`] must already have properly initialized control bytes since
1292 // we will never expose RawTable::new_uninitialized in a public API.
1293 self.table.iter()
1294 }
1295
1296 /// Returns an iterator over occupied buckets that could match a given hash.
1297 ///
1298 /// `RawTable` only stores 7 bits of the hash value, so this iterator may
1299 /// return items that have a hash value different than the one provided. You
1300 /// should always validate the returned values before using them.
1301 ///
1302 /// It is up to the caller to ensure that the `RawTable` outlives the
1303 /// `RawIterHash`. Because we cannot make the `next` method unsafe on the
1304 /// `RawIterHash` struct, we have to make the `iter_hash` method unsafe.
1305 #[cfg_attr(feature = "inline-more", inline)]
1306 pub unsafe fn iter_hash(&self, hash: u64) -> RawIterHash<T> {
1307 RawIterHash::new(self, hash)
1308 }
1309
1310 /// Returns an iterator which removes all elements from the table without
1311 /// freeing the memory.
1312 #[cfg_attr(feature = "inline-more", inline)]
1313 pub fn drain(&mut self) -> RawDrain<'_, T, A> {
1314 unsafe {
1315 let iter = self.iter();
1316 self.drain_iter_from(iter)
1317 }
1318 }
1319
1320 /// Returns an iterator which removes all elements from the table without
1321 /// freeing the memory.
1322 ///
1323 /// Iteration starts at the provided iterator's current location.
1324 ///
1325 /// It is up to the caller to ensure that the iterator is valid for this
1326 /// `RawTable` and covers all items that remain in the table.
1327 #[cfg_attr(feature = "inline-more", inline)]
1328 pub unsafe fn drain_iter_from(&mut self, iter: RawIter<T>) -> RawDrain<'_, T, A> {
1329 debug_assert_eq!(iter.len(), self.len());
1330 RawDrain {
1331 iter,
1332 table: mem::replace(&mut self.table, RawTableInner::NEW),
1333 orig_table: NonNull::from(&mut self.table),
1334 marker: PhantomData,
1335 }
1336 }
1337
1338 /// Returns an iterator which consumes all elements from the table.
1339 ///
1340 /// Iteration starts at the provided iterator's current location.
1341 ///
1342 /// It is up to the caller to ensure that the iterator is valid for this
1343 /// `RawTable` and covers all items that remain in the table.
1344 pub unsafe fn into_iter_from(self, iter: RawIter<T>) -> RawIntoIter<T, A> {
1345 debug_assert_eq!(iter.len(), self.len());
1346
1347 let allocation = self.into_allocation();
1348 RawIntoIter {
1349 iter,
1350 allocation,
1351 marker: PhantomData,
1352 }
1353 }
1354
1355 /// Converts the table into a raw allocation. The contents of the table
1356 /// should be dropped using a `RawIter` before freeing the allocation.
1357 #[cfg_attr(feature = "inline-more", inline)]
1358 pub(crate) fn into_allocation(self) -> Option<(NonNull<u8>, Layout, A)> {
1359 let alloc = if self.table.is_empty_singleton() {
1360 None
1361 } else {
1362 // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
1363 let (layout, ctrl_offset) =
1364 match Self::TABLE_LAYOUT.calculate_layout_for(self.table.buckets()) {
1365 Some(lco) => lco,
1366 None => unsafe { hint::unreachable_unchecked() },
1367 };
1368 Some((
1369 unsafe { NonNull::new_unchecked(self.table.ctrl.as_ptr().sub(ctrl_offset).cast()) },
1370 layout,
1371 unsafe { ptr::read(&self.alloc) },
1372 ))
1373 };
1374 mem::forget(self);
1375 alloc
1376 }
1377}
1378
1379unsafe impl<T, A: Allocator> Send for RawTable<T, A>
1380where
1381 T: Send,
1382 A: Send,
1383{
1384}
1385unsafe impl<T, A: Allocator> Sync for RawTable<T, A>
1386where
1387 T: Sync,
1388 A: Sync,
1389{
1390}
1391
1392impl RawTableInner {
1393 const NEW: Self = RawTableInner::new();
1394
1395 /// Creates a new empty hash table without allocating any memory.
1396 ///
1397 /// In effect this returns a table with exactly 1 bucket. However we can
1398 /// leave the data pointer dangling since that bucket is never accessed
1399 /// due to our load factor forcing us to always have at least 1 free bucket.
1400 #[inline]
1401 const fn new() -> Self {
1402 Self {
1403 // Be careful to cast the entire slice to a raw pointer.
1404 ctrl: unsafe {
1405 NonNull::new_unchecked(Group::static_empty().as_ptr().cast_mut().cast())
1406 },
1407 bucket_mask: 0,
1408 items: 0,
1409 growth_left: 0,
1410 }
1411 }
1412}
1413
1414impl RawTableInner {
1415 /// Allocates a new [`RawTableInner`] with the given number of buckets.
1416 /// The control bytes and buckets are left uninitialized.
1417 ///
1418 /// # Safety
1419 ///
1420 /// The caller of this function must ensure that the `buckets` is power of two
1421 /// and also initialize all control bytes of the length `self.bucket_mask + 1 +
1422 /// Group::WIDTH` with the [`Tag::EMPTY`] bytes.
1423 ///
1424 /// See also [`Allocator`] API for other safety concerns.
1425 ///
1426 /// [`Allocator`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html
1427 #[cfg_attr(feature = "inline-more", inline)]
1428 unsafe fn new_uninitialized<A>(
1429 alloc: &A,
1430 table_layout: TableLayout,
1431 buckets: usize,
1432 fallibility: Fallibility,
1433 ) -> Result<Self, TryReserveError>
1434 where
1435 A: Allocator,
1436 {
1437 debug_assert!(buckets.is_power_of_two());
1438
1439 // Avoid `Option::ok_or_else` because it bloats LLVM IR.
1440 let (layout, ctrl_offset) = match table_layout.calculate_layout_for(buckets) {
1441 Some(lco) => lco,
1442 None => return Err(fallibility.capacity_overflow()),
1443 };
1444
1445 let ptr: NonNull<u8> = match do_alloc(alloc, layout) {
1446 Ok(block) => block.cast(),
1447 Err(_) => return Err(fallibility.alloc_err(layout)),
1448 };
1449
1450 // SAFETY: null pointer will be caught in above check
1451 let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset));
1452 Ok(Self {
1453 ctrl,
1454 bucket_mask: buckets - 1,
1455 items: 0,
1456 growth_left: bucket_mask_to_capacity(buckets - 1),
1457 })
1458 }
1459
1460 /// Attempts to allocate a new [`RawTableInner`] with at least enough
1461 /// capacity for inserting the given number of elements without reallocating.
1462 ///
1463 /// All the control bytes are initialized with the [`Tag::EMPTY`] bytes.
1464 #[inline]
1465 fn fallible_with_capacity<A>(
1466 alloc: &A,
1467 table_layout: TableLayout,
1468 capacity: usize,
1469 fallibility: Fallibility,
1470 ) -> Result<Self, TryReserveError>
1471 where
1472 A: Allocator,
1473 {
1474 if capacity == 0 {
1475 Ok(Self::NEW)
1476 } else {
1477 // SAFETY: We checked that we could successfully allocate the new table, and then
1478 // initialized all control bytes with the constant `Tag::EMPTY` byte.
1479 unsafe {
1480 let buckets =
1481 capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?;
1482
1483 let mut result =
1484 Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?;
1485 // SAFETY: We checked that the table is allocated and therefore the table already has
1486 // `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
1487 // so writing `self.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
1488 result.ctrl_slice().fill_empty();
1489
1490 Ok(result)
1491 }
1492 }
1493 }
1494
1495 /// Allocates a new [`RawTableInner`] with at least enough capacity for inserting
1496 /// the given number of elements without reallocating.
1497 ///
1498 /// Panics if the new capacity exceeds [`isize::MAX`] bytes and [`abort`] the program
1499 /// in case of allocation error. Use [`fallible_with_capacity`] instead if you want to
1500 /// handle memory allocation failure.
1501 ///
1502 /// All the control bytes are initialized with the [`Tag::EMPTY`] bytes.
1503 ///
1504 /// [`fallible_with_capacity`]: RawTableInner::fallible_with_capacity
1505 /// [`abort`]: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html
1506 fn with_capacity<A>(alloc: &A, table_layout: TableLayout, capacity: usize) -> Self
1507 where
1508 A: Allocator,
1509 {
1510 // Avoid `Result::unwrap_or_else` because it bloats LLVM IR.
1511 match Self::fallible_with_capacity(alloc, table_layout, capacity, Fallibility::Infallible) {
1512 Ok(table_inner) => table_inner,
1513 // SAFETY: All allocation errors will be caught inside `RawTableInner::new_uninitialized`.
1514 Err(_) => unsafe { hint::unreachable_unchecked() },
1515 }
1516 }
1517
1518 /// Fixes up an insertion slot returned by the [`RawTableInner::find_insert_slot_in_group`] method.
1519 ///
1520 /// In tables smaller than the group width (`self.buckets() < Group::WIDTH`), trailing control
1521 /// bytes outside the range of the table are filled with [`Tag::EMPTY`] entries. These will unfortunately
1522 /// trigger a match of [`RawTableInner::find_insert_slot_in_group`] function. This is because
1523 /// the `Some(bit)` returned by `group.match_empty_or_deleted().lowest_set_bit()` after masking
1524 /// (`(probe_seq.pos + bit) & self.bucket_mask`) may point to a full bucket that is already occupied.
1525 /// We detect this situation here and perform a second scan starting at the beginning of the table.
1526 /// This second scan is guaranteed to find an empty slot (due to the load factor) before hitting the
1527 /// trailing control bytes (containing [`Tag::EMPTY`] bytes).
1528 ///
1529 /// If this function is called correctly, it is guaranteed to return [`InsertSlot`] with an
1530 /// index of an empty or deleted bucket in the range `0..self.buckets()` (see `Warning` and
1531 /// `Safety`).
1532 ///
1533 /// # Warning
1534 ///
1535 /// The table must have at least 1 empty or deleted `bucket`, otherwise if the table is less than
1536 /// the group width (`self.buckets() < Group::WIDTH`) this function returns an index outside of the
1537 /// table indices range `0..self.buckets()` (`0..=self.bucket_mask`). Attempt to write data at that
1538 /// index will cause immediate [`undefined behavior`].
1539 ///
1540 /// # Safety
1541 ///
1542 /// The safety rules are directly derived from the safety rules for [`RawTableInner::ctrl`] method.
1543 /// Thus, in order to uphold those safety contracts, as well as for the correct logic of the work
1544 /// of this crate, the following rules are necessary and sufficient:
1545 ///
1546 /// * The [`RawTableInner`] must have properly initialized control bytes otherwise calling this
1547 /// function results in [`undefined behavior`].
1548 ///
1549 /// * This function must only be used on insertion slots found by [`RawTableInner::find_insert_slot_in_group`]
1550 /// (after the `find_insert_slot_in_group` function, but before insertion into the table).
1551 ///
1552 /// * The `index` must not be greater than the `self.bucket_mask`, i.e. `(index + 1) <= self.buckets()`
1553 /// (this one is provided by the [`RawTableInner::find_insert_slot_in_group`] function).
1554 ///
1555 /// Calling this function with an index not provided by [`RawTableInner::find_insert_slot_in_group`]
1556 /// may result in [`undefined behavior`] even if the index satisfies the safety rules of the
1557 /// [`RawTableInner::ctrl`] function (`index < self.bucket_mask + 1 + Group::WIDTH`).
1558 ///
1559 /// [`RawTableInner::ctrl`]: RawTableInner::ctrl
1560 /// [`RawTableInner::find_insert_slot_in_group`]: RawTableInner::find_insert_slot_in_group
1561 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1562 #[inline]
1563 unsafe fn fix_insert_slot(&self, mut index: usize) -> InsertSlot {
1564 // SAFETY: The caller of this function ensures that `index` is in the range `0..=self.bucket_mask`.
1565 if unlikely(self.is_bucket_full(index)) {
1566 debug_assert!(self.bucket_mask < Group::WIDTH);
1567 // SAFETY:
1568 //
1569 // * Since the caller of this function ensures that the control bytes are properly
1570 // initialized and `ptr = self.ctrl(0)` points to the start of the array of control
1571 // bytes, therefore: `ctrl` is valid for reads, properly aligned to `Group::WIDTH`
1572 // and points to the properly initialized control bytes (see also
1573 // `TableLayout::calculate_layout_for` and `ptr::read`);
1574 //
1575 // * Because the caller of this function ensures that the index was provided by the
1576 // `self.find_insert_slot_in_group()` function, so for for tables larger than the
1577 // group width (self.buckets() >= Group::WIDTH), we will never end up in the given
1578 // branch, since `(probe_seq.pos + bit) & self.bucket_mask` in `find_insert_slot_in_group`
1579 // cannot return a full bucket index. For tables smaller than the group width, calling
1580 // the `unwrap_unchecked` function is also safe, as the trailing control bytes outside
1581 // the range of the table are filled with EMPTY bytes (and we know for sure that there
1582 // is at least one FULL bucket), so this second scan either finds an empty slot (due to
1583 // the load factor) or hits the trailing control bytes (containing EMPTY).
1584 index = Group::load_aligned(self.ctrl(0))
1585 .match_empty_or_deleted()
1586 .lowest_set_bit()
1587 .unwrap_unchecked();
1588 }
1589 InsertSlot { index }
1590 }
1591
1592 /// Finds the position to insert something in a group.
1593 ///
1594 /// **This may have false positives and must be fixed up with `fix_insert_slot`
1595 /// before it's used.**
1596 ///
1597 /// The function is guaranteed to return the index of an empty or deleted [`Bucket`]
1598 /// in the range `0..self.buckets()` (`0..=self.bucket_mask`).
1599 #[inline]
1600 fn find_insert_slot_in_group(&self, group: &Group, probe_seq: &ProbeSeq) -> Option<usize> {
1601 let bit = group.match_empty_or_deleted().lowest_set_bit();
1602
1603 if likely(bit.is_some()) {
1604 // This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
1605 // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
1606 Some((probe_seq.pos + bit.unwrap()) & self.bucket_mask)
1607 } else {
1608 None
1609 }
1610 }
1611
1612 /// Searches for an element in the table, or a potential slot where that element could
1613 /// be inserted (an empty or deleted [`Bucket`] index).
1614 ///
1615 /// This uses dynamic dispatch to reduce the amount of code generated, but that is
1616 /// eliminated by LLVM optimizations.
1617 ///
1618 /// This function does not make any changes to the `data` part of the table, or any
1619 /// changes to the `items` or `growth_left` field of the table.
1620 ///
1621 /// The table must have at least 1 empty or deleted `bucket`, otherwise, if the
1622 /// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`, this function
1623 /// will never return (will go into an infinite loop) for tables larger than the group
1624 /// width, or return an index outside of the table indices range if the table is less
1625 /// than the group width.
1626 ///
1627 /// This function is guaranteed to provide the `eq: &mut dyn FnMut(usize) -> bool`
1628 /// function with only `FULL` buckets' indices and return the `index` of the found
1629 /// element (as `Ok(index)`). If the element is not found and there is at least 1
1630 /// empty or deleted [`Bucket`] in the table, the function is guaranteed to return
1631 /// [`InsertSlot`] with an index in the range `0..self.buckets()`, but in any case,
1632 /// if this function returns [`InsertSlot`], it will contain an index in the range
1633 /// `0..=self.buckets()`.
1634 ///
1635 /// # Safety
1636 ///
1637 /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
1638 /// this function results in [`undefined behavior`].
1639 ///
1640 /// Attempt to write data at the [`InsertSlot`] returned by this function when the table is
1641 /// less than the group width and if there was not at least one empty or deleted bucket in
1642 /// the table will cause immediate [`undefined behavior`]. This is because in this case the
1643 /// function will return `self.bucket_mask + 1` as an index due to the trailing [`Tag::EMPTY`]
1644 /// control bytes outside the table range.
1645 ///
1646 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1647 #[inline]
1648 unsafe fn find_or_find_insert_slot_inner(
1649 &self,
1650 hash: u64,
1651 eq: &mut dyn FnMut(usize) -> bool,
1652 ) -> Result<usize, InsertSlot> {
1653 let mut insert_slot = None;
1654
1655 let tag_hash = Tag::full(hash);
1656 let mut probe_seq = self.probe_seq(hash);
1657
1658 loop {
1659 // SAFETY:
1660 // * Caller of this function ensures that the control bytes are properly initialized.
1661 //
1662 // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
1663 // of the table due to masking with `self.bucket_mask` and also because the number
1664 // of buckets is a power of two (see `self.probe_seq` function).
1665 //
1666 // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
1667 // call `Group::load` due to the extended control bytes range, which is
1668 // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
1669 // byte will never be read for the allocated table);
1670 //
1671 // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
1672 // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
1673 // bytes, which is safe (see RawTableInner::new).
1674 let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
1675
1676 for bit in group.match_tag(tag_hash) {
1677 let index = (probe_seq.pos + bit) & self.bucket_mask;
1678
1679 if likely(eq(index)) {
1680 return Ok(index);
1681 }
1682 }
1683
1684 // We didn't find the element we were looking for in the group, try to get an
1685 // insertion slot from the group if we don't have one yet.
1686 if likely(insert_slot.is_none()) {
1687 insert_slot = self.find_insert_slot_in_group(&group, &probe_seq);
1688 }
1689
1690 // Only stop the search if the group contains at least one empty element.
1691 // Otherwise, the element that we are looking for might be in a following group.
1692 if likely(group.match_empty().any_bit_set()) {
1693 // We must have found a insert slot by now, since the current group contains at
1694 // least one. For tables smaller than the group width, there will still be an
1695 // empty element in the current (and only) group due to the load factor.
1696 unsafe {
1697 // SAFETY:
1698 // * Caller of this function ensures that the control bytes are properly initialized.
1699 //
1700 // * We use this function with the slot / index found by `self.find_insert_slot_in_group`
1701 return Err(self.fix_insert_slot(insert_slot.unwrap_unchecked()));
1702 }
1703 }
1704
1705 probe_seq.move_next(self.bucket_mask);
1706 }
1707 }
1708
1709 /// Searches for an empty or deleted bucket which is suitable for inserting a new
1710 /// element and sets the hash for that slot. Returns an index of that slot and the
1711 /// old control byte stored in the found index.
1712 ///
1713 /// This function does not check if the given element exists in the table. Also,
1714 /// this function does not check if there is enough space in the table to insert
1715 /// a new element. The caller of the function must make sure that the table has at
1716 /// least 1 empty or deleted `bucket`, otherwise this function will never return
1717 /// (will go into an infinite loop) for tables larger than the group width, or
1718 /// return an index outside of the table indices range if the table is less than
1719 /// the group width.
1720 ///
1721 /// If there is at least 1 empty or deleted `bucket` in the table, the function is
1722 /// guaranteed to return an `index` in the range `0..self.buckets()`, but in any case,
1723 /// if this function returns an `index` it will be in the range `0..=self.buckets()`.
1724 ///
1725 /// This function does not make any changes to the `data` parts of the table,
1726 /// or any changes to the `items` or `growth_left` field of the table.
1727 ///
1728 /// # Safety
1729 ///
1730 /// The safety rules are directly derived from the safety rules for the
1731 /// [`RawTableInner::set_ctrl_hash`] and [`RawTableInner::find_insert_slot`] methods.
1732 /// Thus, in order to uphold the safety contracts for that methods, as well as for
1733 /// the correct logic of the work of this crate, you must observe the following rules
1734 /// when calling this function:
1735 ///
1736 /// * The [`RawTableInner`] has already been allocated and has properly initialized
1737 /// control bytes otherwise calling this function results in [`undefined behavior`].
1738 ///
1739 /// * The caller of this function must ensure that the "data" parts of the table
1740 /// will have an entry in the returned index (matching the given hash) right
1741 /// after calling this function.
1742 ///
1743 /// Attempt to write data at the `index` returned by this function when the table is
1744 /// less than the group width and if there was not at least one empty or deleted bucket in
1745 /// the table will cause immediate [`undefined behavior`]. This is because in this case the
1746 /// function will return `self.bucket_mask + 1` as an index due to the trailing [`Tag::EMPTY`]
1747 /// control bytes outside the table range.
1748 ///
1749 /// The caller must independently increase the `items` field of the table, and also,
1750 /// if the old control byte was [`Tag::EMPTY`], then decrease the table's `growth_left`
1751 /// field, and do not change it if the old control byte was [`Tag::DELETED`].
1752 ///
1753 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
1754 /// or saving `element` from / into the [`RawTable`] / [`RawTableInner`].
1755 ///
1756 /// [`Bucket::as_ptr`]: Bucket::as_ptr
1757 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1758 /// [`RawTableInner::ctrl`]: RawTableInner::ctrl
1759 /// [`RawTableInner::set_ctrl_hash`]: RawTableInner::set_ctrl_hash
1760 /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
1761 #[inline]
1762 unsafe fn prepare_insert_slot(&mut self, hash: u64) -> (usize, Tag) {
1763 // SAFETY: Caller of this function ensures that the control bytes are properly initialized.
1764 let index: usize = self.find_insert_slot(hash).index;
1765 // SAFETY:
1766 // 1. The `find_insert_slot` function either returns an `index` less than or
1767 // equal to `self.buckets() = self.bucket_mask + 1` of the table, or never
1768 // returns if it cannot find an empty or deleted slot.
1769 // 2. The caller of this function guarantees that the table has already been
1770 // allocated
1771 let old_ctrl = *self.ctrl(index);
1772 self.set_ctrl_hash(index, hash);
1773 (index, old_ctrl)
1774 }
1775
1776 /// Searches for an empty or deleted bucket which is suitable for inserting
1777 /// a new element, returning the `index` for the new [`Bucket`].
1778 ///
1779 /// This function does not make any changes to the `data` part of the table, or any
1780 /// changes to the `items` or `growth_left` field of the table.
1781 ///
1782 /// The table must have at least 1 empty or deleted `bucket`, otherwise this function
1783 /// will never return (will go into an infinite loop) for tables larger than the group
1784 /// width, or return an index outside of the table indices range if the table is less
1785 /// than the group width.
1786 ///
1787 /// If there is at least 1 empty or deleted `bucket` in the table, the function is
1788 /// guaranteed to return [`InsertSlot`] with an index in the range `0..self.buckets()`,
1789 /// but in any case, if this function returns [`InsertSlot`], it will contain an index
1790 /// in the range `0..=self.buckets()`.
1791 ///
1792 /// # Safety
1793 ///
1794 /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
1795 /// this function results in [`undefined behavior`].
1796 ///
1797 /// Attempt to write data at the [`InsertSlot`] returned by this function when the table is
1798 /// less than the group width and if there was not at least one empty or deleted bucket in
1799 /// the table will cause immediate [`undefined behavior`]. This is because in this case the
1800 /// function will return `self.bucket_mask + 1` as an index due to the trailing [`Tag::EMPTY`]
1801 /// control bytes outside the table range.
1802 ///
1803 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1804 #[inline]
1805 unsafe fn find_insert_slot(&self, hash: u64) -> InsertSlot {
1806 let mut probe_seq = self.probe_seq(hash);
1807 loop {
1808 // SAFETY:
1809 // * Caller of this function ensures that the control bytes are properly initialized.
1810 //
1811 // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
1812 // of the table due to masking with `self.bucket_mask` and also because the number
1813 // of buckets is a power of two (see `self.probe_seq` function).
1814 //
1815 // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
1816 // call `Group::load` due to the extended control bytes range, which is
1817 // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
1818 // byte will never be read for the allocated table);
1819 //
1820 // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
1821 // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
1822 // bytes, which is safe (see RawTableInner::new).
1823 let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
1824
1825 let index = self.find_insert_slot_in_group(&group, &probe_seq);
1826 if likely(index.is_some()) {
1827 // SAFETY:
1828 // * Caller of this function ensures that the control bytes are properly initialized.
1829 //
1830 // * We use this function with the slot / index found by `self.find_insert_slot_in_group`
1831 unsafe {
1832 return self.fix_insert_slot(index.unwrap_unchecked());
1833 }
1834 }
1835 probe_seq.move_next(self.bucket_mask);
1836 }
1837 }
1838
1839 /// Searches for an element in a table, returning the `index` of the found element.
1840 /// This uses dynamic dispatch to reduce the amount of code generated, but it is
1841 /// eliminated by LLVM optimizations.
1842 ///
1843 /// This function does not make any changes to the `data` part of the table, or any
1844 /// changes to the `items` or `growth_left` field of the table.
1845 ///
1846 /// The table must have at least 1 empty `bucket`, otherwise, if the
1847 /// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`,
1848 /// this function will also never return (will go into an infinite loop).
1849 ///
1850 /// This function is guaranteed to provide the `eq: &mut dyn FnMut(usize) -> bool`
1851 /// function with only `FULL` buckets' indices and return the `index` of the found
1852 /// element as `Some(index)`, so the index will always be in the range
1853 /// `0..self.buckets()`.
1854 ///
1855 /// # Safety
1856 ///
1857 /// The [`RawTableInner`] must have properly initialized control bytes otherwise calling
1858 /// this function results in [`undefined behavior`].
1859 ///
1860 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1861 #[inline(always)]
1862 unsafe fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> {
1863 let tag_hash = Tag::full(hash);
1864 let mut probe_seq = self.probe_seq(hash);
1865
1866 loop {
1867 // SAFETY:
1868 // * Caller of this function ensures that the control bytes are properly initialized.
1869 //
1870 // * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
1871 // of the table due to masking with `self.bucket_mask`.
1872 //
1873 // * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
1874 // call `Group::load` due to the extended control bytes range, which is
1875 // `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
1876 // byte will never be read for the allocated table);
1877 //
1878 // * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
1879 // always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
1880 // bytes, which is safe (see RawTableInner::new_in).
1881 let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
1882
1883 for bit in group.match_tag(tag_hash) {
1884 // This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
1885 // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
1886 let index = (probe_seq.pos + bit) & self.bucket_mask;
1887
1888 if likely(eq(index)) {
1889 return Some(index);
1890 }
1891 }
1892
1893 if likely(group.match_empty().any_bit_set()) {
1894 return None;
1895 }
1896
1897 probe_seq.move_next(self.bucket_mask);
1898 }
1899 }
1900
1901 /// Prepares for rehashing data in place (that is, without allocating new memory).
1902 /// Converts all full index `control bytes` to `Tag::DELETED` and all `Tag::DELETED` control
1903 /// bytes to `Tag::EMPTY`, i.e. performs the following conversion:
1904 ///
1905 /// - `Tag::EMPTY` control bytes -> `Tag::EMPTY`;
1906 /// - `Tag::DELETED` control bytes -> `Tag::EMPTY`;
1907 /// - `FULL` control bytes -> `Tag::DELETED`.
1908 ///
1909 /// This function does not make any changes to the `data` parts of the table,
1910 /// or any changes to the `items` or `growth_left` field of the table.
1911 ///
1912 /// # Safety
1913 ///
1914 /// You must observe the following safety rules when calling this function:
1915 ///
1916 /// * The [`RawTableInner`] has already been allocated;
1917 ///
1918 /// * The caller of this function must convert the `Tag::DELETED` bytes back to `FULL`
1919 /// bytes when re-inserting them into their ideal position (which was impossible
1920 /// to do during the first insert due to tombstones). If the caller does not do
1921 /// this, then calling this function may result in a memory leak.
1922 ///
1923 /// * The [`RawTableInner`] must have properly initialized control bytes otherwise
1924 /// calling this function results in [`undefined behavior`].
1925 ///
1926 /// Calling this function on a table that has not been allocated results in
1927 /// [`undefined behavior`].
1928 ///
1929 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
1930 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
1931 ///
1932 /// [`Bucket::as_ptr`]: Bucket::as_ptr
1933 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1934 #[allow(clippy::mut_mut)]
1935 #[inline]
1936 unsafe fn prepare_rehash_in_place(&mut self) {
1937 // Bulk convert all full control bytes to DELETED, and all DELETED control bytes to EMPTY.
1938 // This effectively frees up all buckets containing a DELETED entry.
1939 //
1940 // SAFETY:
1941 // 1. `i` is guaranteed to be within bounds since we are iterating from zero to `buckets - 1`;
1942 // 2. Even if `i` will be `i == self.bucket_mask`, it is safe to call `Group::load_aligned`
1943 // due to the extended control bytes range, which is `self.bucket_mask + 1 + Group::WIDTH`;
1944 // 3. The caller of this function guarantees that [`RawTableInner`] has already been allocated;
1945 // 4. We can use `Group::load_aligned` and `Group::store_aligned` here since we start from 0
1946 // and go to the end with a step equal to `Group::WIDTH` (see TableLayout::calculate_layout_for).
1947 for i in (0..self.buckets()).step_by(Group::WIDTH) {
1948 let group = Group::load_aligned(self.ctrl(i));
1949 let group = group.convert_special_to_empty_and_full_to_deleted();
1950 group.store_aligned(self.ctrl(i));
1951 }
1952
1953 // Fix up the trailing control bytes. See the comments in set_ctrl
1954 // for the handling of tables smaller than the group width.
1955 //
1956 // SAFETY: The caller of this function guarantees that [`RawTableInner`]
1957 // has already been allocated
1958 if unlikely(self.buckets() < Group::WIDTH) {
1959 // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of control bytes,
1960 // so copying `self.buckets() == self.bucket_mask + 1` bytes with offset equal to
1961 // `Group::WIDTH` is safe
1962 self.ctrl(0)
1963 .copy_to(self.ctrl(Group::WIDTH), self.buckets());
1964 } else {
1965 // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of
1966 // control bytes,so copying `Group::WIDTH` bytes with offset equal
1967 // to `self.buckets() == self.bucket_mask + 1` is safe
1968 self.ctrl(0)
1969 .copy_to(self.ctrl(self.buckets()), Group::WIDTH);
1970 }
1971 }
1972
1973 /// Returns an iterator over every element in the table.
1974 ///
1975 /// # Safety
1976 ///
1977 /// If any of the following conditions are violated, the result
1978 /// is [`undefined behavior`]:
1979 ///
1980 /// * The caller has to ensure that the `RawTableInner` outlives the
1981 /// `RawIter`. Because we cannot make the `next` method unsafe on
1982 /// the `RawIter` struct, we have to make the `iter` method unsafe.
1983 ///
1984 /// * The [`RawTableInner`] must have properly initialized control bytes.
1985 ///
1986 /// The type `T` must be the actual type of the elements stored in the table,
1987 /// otherwise using the returned [`RawIter`] results in [`undefined behavior`].
1988 ///
1989 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1990 #[inline]
1991 unsafe fn iter<T>(&self) -> RawIter<T> {
1992 // SAFETY:
1993 // 1. Since the caller of this function ensures that the control bytes
1994 // are properly initialized and `self.data_end()` points to the start
1995 // of the array of control bytes, therefore: `ctrl` is valid for reads,
1996 // properly aligned to `Group::WIDTH` and points to the properly initialized
1997 // control bytes.
1998 // 2. `data` bucket index in the table is equal to the `ctrl` index (i.e.
1999 // equal to zero).
2000 // 3. We pass the exact value of buckets of the table to the function.
2001 //
2002 // `ctrl` points here (to the start
2003 // of the first control byte `CT0`)
2004 // ∨
2005 // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
2006 // \________ ________/
2007 // \/
2008 // `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
2009 //
2010 // where: T0...T_n - our stored data;
2011 // CT0...CT_n - control bytes or metadata for `data`.
2012 // CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
2013 // with loading `Group` bytes from the heap works properly, even if the result
2014 // of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
2015 // `RawTableInner::set_ctrl` function.
2016 //
2017 // P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
2018 // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2019 let data = Bucket::from_base_index(self.data_end(), 0);
2020 RawIter {
2021 // SAFETY: See explanation above
2022 iter: RawIterRange::new(self.ctrl.as_ptr(), data, self.buckets()),
2023 items: self.items,
2024 }
2025 }
2026
2027 /// Executes the destructors (if any) of the values stored in the table.
2028 ///
2029 /// # Note
2030 ///
2031 /// This function does not erase the control bytes of the table and does
2032 /// not make any changes to the `items` or `growth_left` fields of the
2033 /// table. If necessary, the caller of this function must manually set
2034 /// up these table fields, for example using the [`clear_no_drop`] function.
2035 ///
2036 /// Be careful during calling this function, because drop function of
2037 /// the elements can panic, and this can leave table in an inconsistent
2038 /// state.
2039 ///
2040 /// # Safety
2041 ///
2042 /// The type `T` must be the actual type of the elements stored in the table,
2043 /// otherwise calling this function may result in [`undefined behavior`].
2044 ///
2045 /// If `T` is a type that should be dropped and **the table is not empty**,
2046 /// calling this function more than once results in [`undefined behavior`].
2047 ///
2048 /// If `T` is not [`Copy`], attempting to use values stored in the table after
2049 /// calling this function may result in [`undefined behavior`].
2050 ///
2051 /// It is safe to call this function on a table that has not been allocated,
2052 /// on a table with uninitialized control bytes, and on a table with no actual
2053 /// data but with `Full` control bytes if `self.items == 0`.
2054 ///
2055 /// See also [`Bucket::drop`] / [`Bucket::as_ptr`] methods, for more information
2056 /// about of properly removing or saving `element` from / into the [`RawTable`] /
2057 /// [`RawTableInner`].
2058 ///
2059 /// [`Bucket::drop`]: Bucket::drop
2060 /// [`Bucket::as_ptr`]: Bucket::as_ptr
2061 /// [`clear_no_drop`]: RawTableInner::clear_no_drop
2062 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2063 unsafe fn drop_elements<T>(&mut self) {
2064 // Check that `self.items != 0`. Protects against the possibility
2065 // of creating an iterator on an table with uninitialized control bytes.
2066 if T::NEEDS_DROP && self.items != 0 {
2067 // SAFETY: We know for sure that RawTableInner will outlive the
2068 // returned `RawIter` iterator, and the caller of this function
2069 // must uphold the safety contract for `drop_elements` method.
2070 for item in self.iter::<T>() {
2071 // SAFETY: The caller must uphold the safety contract for
2072 // `drop_elements` method.
2073 item.drop();
2074 }
2075 }
2076 }
2077
2078 /// Executes the destructors (if any) of the values stored in the table and than
2079 /// deallocates the table.
2080 ///
2081 /// # Note
2082 ///
2083 /// Calling this function automatically makes invalid (dangling) all instances of
2084 /// buckets ([`Bucket`]) and makes invalid (dangling) the `ctrl` field of the table.
2085 ///
2086 /// This function does not make any changes to the `bucket_mask`, `items` or `growth_left`
2087 /// fields of the table. If necessary, the caller of this function must manually set
2088 /// up these table fields.
2089 ///
2090 /// # Safety
2091 ///
2092 /// If any of the following conditions are violated, the result is [`undefined behavior`]:
2093 ///
2094 /// * Calling this function more than once;
2095 ///
2096 /// * The type `T` must be the actual type of the elements stored in the table.
2097 ///
2098 /// * The `alloc` must be the same [`Allocator`] as the `Allocator` that was used
2099 /// to allocate this table.
2100 ///
2101 /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout` that
2102 /// was used to allocate this table.
2103 ///
2104 /// The caller of this function should pay attention to the possibility of the
2105 /// elements' drop function panicking, because this:
2106 ///
2107 /// * May leave the table in an inconsistent state;
2108 ///
2109 /// * Memory is never deallocated, so a memory leak may occur.
2110 ///
2111 /// Attempt to use the `ctrl` field of the table (dereference) after calling this
2112 /// function results in [`undefined behavior`].
2113 ///
2114 /// It is safe to call this function on a table that has not been allocated,
2115 /// on a table with uninitialized control bytes, and on a table with no actual
2116 /// data but with `Full` control bytes if `self.items == 0`.
2117 ///
2118 /// See also [`RawTableInner::drop_elements`] or [`RawTableInner::free_buckets`]
2119 /// for more information.
2120 ///
2121 /// [`RawTableInner::drop_elements`]: RawTableInner::drop_elements
2122 /// [`RawTableInner::free_buckets`]: RawTableInner::free_buckets
2123 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2124 unsafe fn drop_inner_table<T, A: Allocator>(&mut self, alloc: &A, table_layout: TableLayout) {
2125 if !self.is_empty_singleton() {
2126 unsafe {
2127 // SAFETY: The caller must uphold the safety contract for `drop_inner_table` method.
2128 self.drop_elements::<T>();
2129 // SAFETY:
2130 // 1. We have checked that our table is allocated.
2131 // 2. The caller must uphold the safety contract for `drop_inner_table` method.
2132 self.free_buckets(alloc, table_layout);
2133 }
2134 }
2135 }
2136
2137 /// Returns a pointer to an element in the table (convenience for
2138 /// `Bucket::from_base_index(self.data_end::<T>(), index)`).
2139 ///
2140 /// The caller must ensure that the `RawTableInner` outlives the returned [`Bucket<T>`],
2141 /// otherwise using it may result in [`undefined behavior`].
2142 ///
2143 /// # Safety
2144 ///
2145 /// If `mem::size_of::<T>() != 0`, then the safety rules are directly derived from the
2146 /// safety rules of the [`Bucket::from_base_index`] function. Therefore, when calling
2147 /// this function, the following safety rules must be observed:
2148 ///
2149 /// * The table must already be allocated;
2150 ///
2151 /// * The `index` must not be greater than the number returned by the [`RawTableInner::buckets`]
2152 /// function, i.e. `(index + 1) <= self.buckets()`.
2153 ///
2154 /// * The type `T` must be the actual type of the elements stored in the table, otherwise
2155 /// using the returned [`Bucket`] may result in [`undefined behavior`].
2156 ///
2157 /// It is safe to call this function with index of zero (`index == 0`) on a table that has
2158 /// not been allocated, but using the returned [`Bucket`] results in [`undefined behavior`].
2159 ///
2160 /// If `mem::size_of::<T>() == 0`, then the only requirement is that the `index` must
2161 /// not be greater than the number returned by the [`RawTable::buckets`] function, i.e.
2162 /// `(index + 1) <= self.buckets()`.
2163 ///
2164 /// ```none
2165 /// If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
2166 /// (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
2167 /// the "buckets" number of our `RawTableInner`, i.e. "n = RawTableInner::buckets() - 1"):
2168 ///
2169 /// `table.bucket(3).as_ptr()` returns a pointer that points here in the `data`
2170 /// part of the `RawTableInner`, i.e. to the start of T3 (see [`Bucket::as_ptr`])
2171 /// |
2172 /// | `base = table.data_end::<T>()` points here
2173 /// | (to the start of CT0 or to the end of T0)
2174 /// v v
2175 /// [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
2176 /// ^ \__________ __________/
2177 /// `table.bucket(3)` returns a pointer that points \/
2178 /// here in the `data` part of the `RawTableInner` additional control bytes
2179 /// (to the end of T3) `m = Group::WIDTH - 1`
2180 ///
2181 /// where: T0...T_n - our stored data;
2182 /// CT0...CT_n - control bytes or metadata for `data`;
2183 /// CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
2184 /// the heap works properly, even if the result of `h1(hash) & self.bucket_mask`
2185 /// is equal to `self.bucket_mask`). See also `RawTableInner::set_ctrl` function.
2186 ///
2187 /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
2188 /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2189 /// ```
2190 ///
2191 /// [`Bucket::from_base_index`]: Bucket::from_base_index
2192 /// [`RawTableInner::buckets`]: RawTableInner::buckets
2193 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2194 #[inline]
2195 unsafe fn bucket<T>(&self, index: usize) -> Bucket<T> {
2196 debug_assert_ne!(self.bucket_mask, 0);
2197 debug_assert!(index < self.buckets());
2198 Bucket::from_base_index(self.data_end(), index)
2199 }
2200
2201 /// Returns a raw `*mut u8` pointer to the start of the `data` element in the table
2202 /// (convenience for `self.data_end::<u8>().as_ptr().sub((index + 1) * size_of)`).
2203 ///
2204 /// The caller must ensure that the `RawTableInner` outlives the returned `*mut u8`,
2205 /// otherwise using it may result in [`undefined behavior`].
2206 ///
2207 /// # Safety
2208 ///
2209 /// If any of the following conditions are violated, the result is [`undefined behavior`]:
2210 ///
2211 /// * The table must already be allocated;
2212 ///
2213 /// * The `index` must not be greater than the number returned by the [`RawTableInner::buckets`]
2214 /// function, i.e. `(index + 1) <= self.buckets()`;
2215 ///
2216 /// * The `size_of` must be equal to the size of the elements stored in the table;
2217 ///
2218 /// ```none
2219 /// If mem::size_of::<T>() != 0 then return a pointer to the `element` in the `data part` of the table
2220 /// (we start counting from "0", so that in the expression T[n], the "n" index actually one less than
2221 /// the "buckets" number of our `RawTableInner`, i.e. "n = RawTableInner::buckets() - 1"):
2222 ///
2223 /// `table.bucket_ptr(3, mem::size_of::<T>())` returns a pointer that points here in the
2224 /// `data` part of the `RawTableInner`, i.e. to the start of T3
2225 /// |
2226 /// | `base = table.data_end::<u8>()` points here
2227 /// | (to the start of CT0 or to the end of T0)
2228 /// v v
2229 /// [Pad], T_n, ..., |T3|, T2, T1, T0, |CT0, CT1, CT2, CT3, ..., CT_n, CTa_0, CTa_1, ..., CTa_m
2230 /// \__________ __________/
2231 /// \/
2232 /// additional control bytes
2233 /// `m = Group::WIDTH - 1`
2234 ///
2235 /// where: T0...T_n - our stored data;
2236 /// CT0...CT_n - control bytes or metadata for `data`;
2237 /// CTa_0...CTa_m - additional control bytes (so that the search with loading `Group` bytes from
2238 /// the heap works properly, even if the result of `h1(hash) & self.bucket_mask`
2239 /// is equal to `self.bucket_mask`). See also `RawTableInner::set_ctrl` function.
2240 ///
2241 /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
2242 /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2243 /// ```
2244 ///
2245 /// [`RawTableInner::buckets`]: RawTableInner::buckets
2246 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2247 #[inline]
2248 unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 {
2249 debug_assert_ne!(self.bucket_mask, 0);
2250 debug_assert!(index < self.buckets());
2251 let base: *mut u8 = self.data_end().as_ptr();
2252 base.sub((index + 1) * size_of)
2253 }
2254
2255 /// Returns pointer to one past last `data` element in the table as viewed from
2256 /// the start point of the allocation (convenience for `self.ctrl.cast()`).
2257 ///
2258 /// This function actually returns a pointer to the end of the `data element` at
2259 /// index "0" (zero).
2260 ///
2261 /// The caller must ensure that the `RawTableInner` outlives the returned [`NonNull<T>`],
2262 /// otherwise using it may result in [`undefined behavior`].
2263 ///
2264 /// # Note
2265 ///
2266 /// The type `T` must be the actual type of the elements stored in the table, otherwise
2267 /// using the returned [`NonNull<T>`] may result in [`undefined behavior`].
2268 ///
2269 /// ```none
2270 /// `table.data_end::<T>()` returns pointer that points here
2271 /// (to the end of `T0`)
2272 /// ∨
2273 /// [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, CTa_0, CTa_1, ..., CTa_m
2274 /// \________ ________/
2275 /// \/
2276 /// `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
2277 ///
2278 /// where: T0...T_n - our stored data;
2279 /// CT0...CT_n - control bytes or metadata for `data`.
2280 /// CTa_0...CTa_m - additional control bytes, where `m = Group::WIDTH - 1` (so that the search
2281 /// with loading `Group` bytes from the heap works properly, even if the result
2282 /// of `h1(hash) & self.bucket_mask` is equal to `self.bucket_mask`). See also
2283 /// `RawTableInner::set_ctrl` function.
2284 ///
2285 /// P.S. `h1(hash) & self.bucket_mask` is the same as `hash as usize % self.buckets()` because the number
2286 /// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2287 /// ```
2288 ///
2289 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2290 #[inline]
2291 fn data_end<T>(&self) -> NonNull<T> {
2292 self.ctrl.cast()
2293 }
2294
2295 /// Returns an iterator-like object for a probe sequence on the table.
2296 ///
2297 /// This iterator never terminates, but is guaranteed to visit each bucket
2298 /// group exactly once. The loop using `probe_seq` must terminate upon
2299 /// reaching a group containing an empty bucket.
2300 #[inline]
2301 fn probe_seq(&self, hash: u64) -> ProbeSeq {
2302 ProbeSeq {
2303 // This is the same as `hash as usize % self.buckets()` because the number
2304 // of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2305 pos: h1(hash) & self.bucket_mask,
2306 stride: 0,
2307 }
2308 }
2309
2310 #[inline]
2311 unsafe fn record_item_insert_at(&mut self, index: usize, old_ctrl: Tag, hash: u64) {
2312 self.growth_left -= usize::from(old_ctrl.special_is_empty());
2313 self.set_ctrl_hash(index, hash);
2314 self.items += 1;
2315 }
2316
2317 #[inline]
2318 fn is_in_same_group(&self, i: usize, new_i: usize, hash: u64) -> bool {
2319 let probe_seq_pos = self.probe_seq(hash).pos;
2320 let probe_index =
2321 |pos: usize| (pos.wrapping_sub(probe_seq_pos) & self.bucket_mask) / Group::WIDTH;
2322 probe_index(i) == probe_index(new_i)
2323 }
2324
2325 /// Sets a control byte to the hash, and possibly also the replicated control byte at
2326 /// the end of the array.
2327 ///
2328 /// This function does not make any changes to the `data` parts of the table,
2329 /// or any changes to the `items` or `growth_left` field of the table.
2330 ///
2331 /// # Safety
2332 ///
2333 /// The safety rules are directly derived from the safety rules for [`RawTableInner::set_ctrl`]
2334 /// method. Thus, in order to uphold the safety contracts for the method, you must observe the
2335 /// following rules when calling this function:
2336 ///
2337 /// * The [`RawTableInner`] has already been allocated;
2338 ///
2339 /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
2340 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
2341 /// be no greater than the number returned by the function [`RawTableInner::buckets`].
2342 ///
2343 /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
2344 ///
2345 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
2346 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
2347 ///
2348 /// [`RawTableInner::set_ctrl`]: RawTableInner::set_ctrl
2349 /// [`RawTableInner::buckets`]: RawTableInner::buckets
2350 /// [`Bucket::as_ptr`]: Bucket::as_ptr
2351 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2352 #[inline]
2353 unsafe fn set_ctrl_hash(&mut self, index: usize, hash: u64) {
2354 // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::set_ctrl_hash`]
2355 self.set_ctrl(index, Tag::full(hash));
2356 }
2357
2358 /// Replaces the hash in the control byte at the given index with the provided one,
2359 /// and possibly also replicates the new control byte at the end of the array of control
2360 /// bytes, returning the old control byte.
2361 ///
2362 /// This function does not make any changes to the `data` parts of the table,
2363 /// or any changes to the `items` or `growth_left` field of the table.
2364 ///
2365 /// # Safety
2366 ///
2367 /// The safety rules are directly derived from the safety rules for [`RawTableInner::set_ctrl_hash`]
2368 /// and [`RawTableInner::ctrl`] methods. Thus, in order to uphold the safety contracts for both
2369 /// methods, you must observe the following rules when calling this function:
2370 ///
2371 /// * The [`RawTableInner`] has already been allocated;
2372 ///
2373 /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
2374 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
2375 /// be no greater than the number returned by the function [`RawTableInner::buckets`].
2376 ///
2377 /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
2378 ///
2379 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
2380 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
2381 ///
2382 /// [`RawTableInner::set_ctrl_hash`]: RawTableInner::set_ctrl_hash
2383 /// [`RawTableInner::buckets`]: RawTableInner::buckets
2384 /// [`Bucket::as_ptr`]: Bucket::as_ptr
2385 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2386 #[inline]
2387 unsafe fn replace_ctrl_hash(&mut self, index: usize, hash: u64) -> Tag {
2388 // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::replace_ctrl_hash`]
2389 let prev_ctrl = *self.ctrl(index);
2390 self.set_ctrl_hash(index, hash);
2391 prev_ctrl
2392 }
2393
2394 /// Sets a control byte, and possibly also the replicated control byte at
2395 /// the end of the array.
2396 ///
2397 /// This function does not make any changes to the `data` parts of the table,
2398 /// or any changes to the `items` or `growth_left` field of the table.
2399 ///
2400 /// # Safety
2401 ///
2402 /// You must observe the following safety rules when calling this function:
2403 ///
2404 /// * The [`RawTableInner`] has already been allocated;
2405 ///
2406 /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
2407 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
2408 /// be no greater than the number returned by the function [`RawTableInner::buckets`].
2409 ///
2410 /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
2411 ///
2412 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
2413 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
2414 ///
2415 /// [`RawTableInner::buckets`]: RawTableInner::buckets
2416 /// [`Bucket::as_ptr`]: Bucket::as_ptr
2417 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2418 #[inline]
2419 unsafe fn set_ctrl(&mut self, index: usize, ctrl: Tag) {
2420 // Replicate the first Group::WIDTH control bytes at the end of
2421 // the array without using a branch. If the tables smaller than
2422 // the group width (self.buckets() < Group::WIDTH),
2423 // `index2 = Group::WIDTH + index`, otherwise `index2` is:
2424 //
2425 // - If index >= Group::WIDTH then index == index2.
2426 // - Otherwise index2 == self.bucket_mask + 1 + index.
2427 //
2428 // The very last replicated control byte is never actually read because
2429 // we mask the initial index for unaligned loads, but we write it
2430 // anyways because it makes the set_ctrl implementation simpler.
2431 //
2432 // If there are fewer buckets than Group::WIDTH then this code will
2433 // replicate the buckets at the end of the trailing group. For example
2434 // with 2 buckets and a group size of 4, the control bytes will look
2435 // like this:
2436 //
2437 // Real | Replicated
2438 // ---------------------------------------------
2439 // | [A] | [B] | [Tag::EMPTY] | [EMPTY] | [A] | [B] |
2440 // ---------------------------------------------
2441
2442 // This is the same as `(index.wrapping_sub(Group::WIDTH)) % self.buckets() + Group::WIDTH`
2443 // because the number of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
2444 let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH;
2445
2446 // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::set_ctrl`]
2447 *self.ctrl(index) = ctrl;
2448 *self.ctrl(index2) = ctrl;
2449 }
2450
2451 /// Returns a pointer to a control byte.
2452 ///
2453 /// # Safety
2454 ///
2455 /// For the allocated [`RawTableInner`], the result is [`Undefined Behavior`],
2456 /// if the `index` is greater than the `self.bucket_mask + 1 + Group::WIDTH`.
2457 /// In that case, calling this function with `index == self.bucket_mask + 1 + Group::WIDTH`
2458 /// will return a pointer to the end of the allocated table and it is useless on its own.
2459 ///
2460 /// Calling this function with `index >= self.bucket_mask + 1 + Group::WIDTH` on a
2461 /// table that has not been allocated results in [`Undefined Behavior`].
2462 ///
2463 /// So to satisfy both requirements you should always follow the rule that
2464 /// `index < self.bucket_mask + 1 + Group::WIDTH`
2465 ///
2466 /// Calling this function on [`RawTableInner`] that are not already allocated is safe
2467 /// for read-only purpose.
2468 ///
2469 /// See also [`Bucket::as_ptr()`] method, for more information about of properly removing
2470 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
2471 ///
2472 /// [`Bucket::as_ptr()`]: Bucket::as_ptr()
2473 /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2474 #[inline]
2475 unsafe fn ctrl(&self, index: usize) -> *mut Tag {
2476 debug_assert!(index < self.num_ctrl_bytes());
2477 // SAFETY: The caller must uphold the safety rules for the [`RawTableInner::ctrl`]
2478 self.ctrl.as_ptr().add(index).cast()
2479 }
2480
2481 /// Gets the slice of all control bytes.
2482 fn ctrl_slice(&mut self) -> &mut [Tag] {
2483 // SAFETY: We've intiailized all control bytes, and have the correct number.
2484 unsafe { slice::from_raw_parts_mut(self.ctrl.as_ptr().cast(), self.num_ctrl_bytes()) }
2485 }
2486
2487 #[inline]
2488 fn buckets(&self) -> usize {
2489 self.bucket_mask + 1
2490 }
2491
2492 /// Checks whether the bucket at `index` is full.
2493 ///
2494 /// # Safety
2495 ///
2496 /// The caller must ensure `index` is less than the number of buckets.
2497 #[inline]
2498 unsafe fn is_bucket_full(&self, index: usize) -> bool {
2499 debug_assert!(index < self.buckets());
2500 (*self.ctrl(index)).is_full()
2501 }
2502
2503 #[inline]
2504 fn num_ctrl_bytes(&self) -> usize {
2505 self.bucket_mask + 1 + Group::WIDTH
2506 }
2507
2508 #[inline]
2509 fn is_empty_singleton(&self) -> bool {
2510 self.bucket_mask == 0
2511 }
2512
2513 /// Attempts to allocate a new hash table with at least enough capacity
2514 /// for inserting the given number of elements without reallocating,
2515 /// and return it inside `ScopeGuard` to protect against panic in the hash
2516 /// function.
2517 ///
2518 /// # Note
2519 ///
2520 /// It is recommended (but not required):
2521 ///
2522 /// * That the new table's `capacity` be greater than or equal to `self.items`.
2523 ///
2524 /// * The `alloc` is the same [`Allocator`] as the `Allocator` used
2525 /// to allocate this table.
2526 ///
2527 /// * The `table_layout` is the same [`TableLayout`] as the `TableLayout` used
2528 /// to allocate this table.
2529 ///
2530 /// If `table_layout` does not match the `TableLayout` that was used to allocate
2531 /// this table, then using `mem::swap` with the `self` and the new table returned
2532 /// by this function results in [`undefined behavior`].
2533 ///
2534 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2535 #[allow(clippy::mut_mut)]
2536 #[inline]
2537 fn prepare_resize<'a, A>(
2538 &self,
2539 alloc: &'a A,
2540 table_layout: TableLayout,
2541 capacity: usize,
2542 fallibility: Fallibility,
2543 ) -> Result<crate::scopeguard::ScopeGuard<Self, impl FnMut(&mut Self) + 'a>, TryReserveError>
2544 where
2545 A: Allocator,
2546 {
2547 debug_assert!(self.items <= capacity);
2548
2549 // Allocate and initialize the new table.
2550 let new_table =
2551 RawTableInner::fallible_with_capacity(alloc, table_layout, capacity, fallibility)?;
2552
2553 // The hash function may panic, in which case we simply free the new
2554 // table without dropping any elements that may have been copied into
2555 // it.
2556 //
2557 // This guard is also used to free the old table on success, see
2558 // the comment at the bottom of this function.
2559 Ok(guard(new_table, move |self_| {
2560 if !self_.is_empty_singleton() {
2561 // SAFETY:
2562 // 1. We have checked that our table is allocated.
2563 // 2. We know for sure that the `alloc` and `table_layout` matches the
2564 // [`Allocator`] and [`TableLayout`] used to allocate this table.
2565 unsafe { self_.free_buckets(alloc, table_layout) };
2566 }
2567 }))
2568 }
2569
2570 /// Reserves or rehashes to make room for `additional` more elements.
2571 ///
2572 /// This uses dynamic dispatch to reduce the amount of
2573 /// code generated, but it is eliminated by LLVM optimizations when inlined.
2574 ///
2575 /// # Safety
2576 ///
2577 /// If any of the following conditions are violated, the result is
2578 /// [`undefined behavior`]:
2579 ///
2580 /// * The `alloc` must be the same [`Allocator`] as the `Allocator` used
2581 /// to allocate this table.
2582 ///
2583 /// * The `layout` must be the same [`TableLayout`] as the `TableLayout`
2584 /// used to allocate this table.
2585 ///
2586 /// * The `drop` function (`fn(*mut u8)`) must be the actual drop function of
2587 /// the elements stored in the table.
2588 ///
2589 /// * The [`RawTableInner`] must have properly initialized control bytes.
2590 ///
2591 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2592 #[allow(clippy::inline_always)]
2593 #[inline(always)]
2594 unsafe fn reserve_rehash_inner<A>(
2595 &mut self,
2596 alloc: &A,
2597 additional: usize,
2598 hasher: &dyn Fn(&mut Self, usize) -> u64,
2599 fallibility: Fallibility,
2600 layout: TableLayout,
2601 drop: Option<unsafe fn(*mut u8)>,
2602 ) -> Result<(), TryReserveError>
2603 where
2604 A: Allocator,
2605 {
2606 // Avoid `Option::ok_or_else` because it bloats LLVM IR.
2607 let new_items = match self.items.checked_add(additional) {
2608 Some(new_items) => new_items,
2609 None => return Err(fallibility.capacity_overflow()),
2610 };
2611 let full_capacity = bucket_mask_to_capacity(self.bucket_mask);
2612 if new_items <= full_capacity / 2 {
2613 // Rehash in-place without re-allocating if we have plenty of spare
2614 // capacity that is locked up due to DELETED entries.
2615
2616 // SAFETY:
2617 // 1. We know for sure that `[`RawTableInner`]` has already been allocated
2618 // (since new_items <= full_capacity / 2);
2619 // 2. The caller ensures that `drop` function is the actual drop function of
2620 // the elements stored in the table.
2621 // 3. The caller ensures that `layout` matches the [`TableLayout`] that was
2622 // used to allocate this table.
2623 // 4. The caller ensures that the control bytes of the `RawTableInner`
2624 // are already initialized.
2625 self.rehash_in_place(hasher, layout.size, drop);
2626 Ok(())
2627 } else {
2628 // Otherwise, conservatively resize to at least the next size up
2629 // to avoid churning deletes into frequent rehashes.
2630 //
2631 // SAFETY:
2632 // 1. We know for sure that `capacity >= self.items`.
2633 // 2. The caller ensures that `alloc` and `layout` matches the [`Allocator`] and
2634 // [`TableLayout`] that were used to allocate this table.
2635 // 3. The caller ensures that the control bytes of the `RawTableInner`
2636 // are already initialized.
2637 self.resize_inner(
2638 alloc,
2639 usize::max(new_items, full_capacity + 1),
2640 hasher,
2641 fallibility,
2642 layout,
2643 )
2644 }
2645 }
2646
2647 /// Returns an iterator over full buckets indices in the table.
2648 ///
2649 /// # Safety
2650 ///
2651 /// Behavior is undefined if any of the following conditions are violated:
2652 ///
2653 /// * The caller has to ensure that the `RawTableInner` outlives the
2654 /// `FullBucketsIndices`. Because we cannot make the `next` method
2655 /// unsafe on the `FullBucketsIndices` struct, we have to make the
2656 /// `full_buckets_indices` method unsafe.
2657 ///
2658 /// * The [`RawTableInner`] must have properly initialized control bytes.
2659 #[inline(always)]
2660 unsafe fn full_buckets_indices(&self) -> FullBucketsIndices {
2661 // SAFETY:
2662 // 1. Since the caller of this function ensures that the control bytes
2663 // are properly initialized and `self.ctrl(0)` points to the start
2664 // of the array of control bytes, therefore: `ctrl` is valid for reads,
2665 // properly aligned to `Group::WIDTH` and points to the properly initialized
2666 // control bytes.
2667 // 2. The value of `items` is equal to the amount of data (values) added
2668 // to the table.
2669 //
2670 // `ctrl` points here (to the start
2671 // of the first control byte `CT0`)
2672 // ∨
2673 // [Pad], T_n, ..., T1, T0, |CT0, CT1, ..., CT_n|, Group::WIDTH
2674 // \________ ________/
2675 // \/
2676 // `n = buckets - 1`, i.e. `RawTableInner::buckets() - 1`
2677 //
2678 // where: T0...T_n - our stored data;
2679 // CT0...CT_n - control bytes or metadata for `data`.
2680 let ctrl = NonNull::new_unchecked(self.ctrl(0).cast::<u8>());
2681
2682 FullBucketsIndices {
2683 // Load the first group
2684 // SAFETY: See explanation above.
2685 current_group: Group::load_aligned(ctrl.as_ptr().cast())
2686 .match_full()
2687 .into_iter(),
2688 group_first_index: 0,
2689 ctrl,
2690 items: self.items,
2691 }
2692 }
2693
2694 /// Allocates a new table of a different size and moves the contents of the
2695 /// current table into it.
2696 ///
2697 /// This uses dynamic dispatch to reduce the amount of
2698 /// code generated, but it is eliminated by LLVM optimizations when inlined.
2699 ///
2700 /// # Safety
2701 ///
2702 /// If any of the following conditions are violated, the result is
2703 /// [`undefined behavior`]:
2704 ///
2705 /// * The `alloc` must be the same [`Allocator`] as the `Allocator` used
2706 /// to allocate this table;
2707 ///
2708 /// * The `layout` must be the same [`TableLayout`] as the `TableLayout`
2709 /// used to allocate this table;
2710 ///
2711 /// * The [`RawTableInner`] must have properly initialized control bytes.
2712 ///
2713 /// The caller of this function must ensure that `capacity >= self.items`
2714 /// otherwise:
2715 ///
2716 /// * If `self.items != 0`, calling of this function with `capacity == 0`
2717 /// results in [`undefined behavior`].
2718 ///
2719 /// * If `capacity_to_buckets(capacity) < Group::WIDTH` and
2720 /// `self.items > capacity_to_buckets(capacity)` calling this function
2721 /// results in [`undefined behavior`].
2722 ///
2723 /// * If `capacity_to_buckets(capacity) >= Group::WIDTH` and
2724 /// `self.items > capacity_to_buckets(capacity)` calling this function
2725 /// are never return (will go into an infinite loop).
2726 ///
2727 /// Note: It is recommended (but not required) that the new table's `capacity`
2728 /// be greater than or equal to `self.items`. In case if `capacity <= self.items`
2729 /// this function can never return. See [`RawTableInner::find_insert_slot`] for
2730 /// more information.
2731 ///
2732 /// [`RawTableInner::find_insert_slot`]: RawTableInner::find_insert_slot
2733 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2734 #[allow(clippy::inline_always)]
2735 #[inline(always)]
2736 unsafe fn resize_inner<A>(
2737 &mut self,
2738 alloc: &A,
2739 capacity: usize,
2740 hasher: &dyn Fn(&mut Self, usize) -> u64,
2741 fallibility: Fallibility,
2742 layout: TableLayout,
2743 ) -> Result<(), TryReserveError>
2744 where
2745 A: Allocator,
2746 {
2747 // SAFETY: We know for sure that `alloc` and `layout` matches the [`Allocator`] and [`TableLayout`]
2748 // that were used to allocate this table.
2749 let mut new_table = self.prepare_resize(alloc, layout, capacity, fallibility)?;
2750
2751 // SAFETY: We know for sure that RawTableInner will outlive the
2752 // returned `FullBucketsIndices` iterator, and the caller of this
2753 // function ensures that the control bytes are properly initialized.
2754 for full_byte_index in self.full_buckets_indices() {
2755 // This may panic.
2756 let hash = hasher(self, full_byte_index);
2757
2758 // SAFETY:
2759 // We can use a simpler version of insert() here since:
2760 // 1. There are no DELETED entries.
2761 // 2. We know there is enough space in the table.
2762 // 3. All elements are unique.
2763 // 4. The caller of this function guarantees that `capacity > 0`
2764 // so `new_table` must already have some allocated memory.
2765 // 5. We set `growth_left` and `items` fields of the new table
2766 // after the loop.
2767 // 6. We insert into the table, at the returned index, the data
2768 // matching the given hash immediately after calling this function.
2769 let (new_index, _) = new_table.prepare_insert_slot(hash);
2770
2771 // SAFETY:
2772 //
2773 // * `src` is valid for reads of `layout.size` bytes, since the
2774 // table is alive and the `full_byte_index` is guaranteed to be
2775 // within bounds (see `FullBucketsIndices::next_impl`);
2776 //
2777 // * `dst` is valid for writes of `layout.size` bytes, since the
2778 // caller ensures that `table_layout` matches the [`TableLayout`]
2779 // that was used to allocate old table and we have the `new_index`
2780 // returned by `prepare_insert_slot`.
2781 //
2782 // * Both `src` and `dst` are properly aligned.
2783 //
2784 // * Both `src` and `dst` point to different region of memory.
2785 ptr::copy_nonoverlapping(
2786 self.bucket_ptr(full_byte_index, layout.size),
2787 new_table.bucket_ptr(new_index, layout.size),
2788 layout.size,
2789 );
2790 }
2791
2792 // The hash function didn't panic, so we can safely set the
2793 // `growth_left` and `items` fields of the new table.
2794 new_table.growth_left -= self.items;
2795 new_table.items = self.items;
2796
2797 // We successfully copied all elements without panicking. Now replace
2798 // self with the new table. The old table will have its memory freed but
2799 // the items will not be dropped (since they have been moved into the
2800 // new table).
2801 // SAFETY: The caller ensures that `table_layout` matches the [`TableLayout`]
2802 // that was used to allocate this table.
2803 mem::swap(self, &mut new_table);
2804
2805 Ok(())
2806 }
2807
2808 /// Rehashes the contents of the table in place (i.e. without changing the
2809 /// allocation).
2810 ///
2811 /// If `hasher` panics then some the table's contents may be lost.
2812 ///
2813 /// This uses dynamic dispatch to reduce the amount of
2814 /// code generated, but it is eliminated by LLVM optimizations when inlined.
2815 ///
2816 /// # Safety
2817 ///
2818 /// If any of the following conditions are violated, the result is [`undefined behavior`]:
2819 ///
2820 /// * The `size_of` must be equal to the size of the elements stored in the table;
2821 ///
2822 /// * The `drop` function (`fn(*mut u8)`) must be the actual drop function of
2823 /// the elements stored in the table.
2824 ///
2825 /// * The [`RawTableInner`] has already been allocated;
2826 ///
2827 /// * The [`RawTableInner`] must have properly initialized control bytes.
2828 ///
2829 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2830 #[allow(clippy::inline_always)]
2831 #[cfg_attr(feature = "inline-more", inline(always))]
2832 #[cfg_attr(not(feature = "inline-more"), inline)]
2833 unsafe fn rehash_in_place(
2834 &mut self,
2835 hasher: &dyn Fn(&mut Self, usize) -> u64,
2836 size_of: usize,
2837 drop: Option<unsafe fn(*mut u8)>,
2838 ) {
2839 // If the hash function panics then properly clean up any elements
2840 // that we haven't rehashed yet. We unfortunately can't preserve the
2841 // element since we lost their hash and have no way of recovering it
2842 // without risking another panic.
2843 self.prepare_rehash_in_place();
2844
2845 let mut guard = guard(self, move |self_| {
2846 if let Some(drop) = drop {
2847 for i in 0..self_.buckets() {
2848 if *self_.ctrl(i) == Tag::DELETED {
2849 self_.set_ctrl(i, Tag::EMPTY);
2850 drop(self_.bucket_ptr(i, size_of));
2851 self_.items -= 1;
2852 }
2853 }
2854 }
2855 self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items;
2856 });
2857
2858 // At this point, DELETED elements are elements that we haven't
2859 // rehashed yet. Find them and re-insert them at their ideal
2860 // position.
2861 'outer: for i in 0..guard.buckets() {
2862 if *guard.ctrl(i) != Tag::DELETED {
2863 continue;
2864 }
2865
2866 let i_p = guard.bucket_ptr(i, size_of);
2867
2868 'inner: loop {
2869 // Hash the current item
2870 let hash = hasher(*guard, i);
2871
2872 // Search for a suitable place to put it
2873 //
2874 // SAFETY: Caller of this function ensures that the control bytes
2875 // are properly initialized.
2876 let new_i = guard.find_insert_slot(hash).index;
2877
2878 // Probing works by scanning through all of the control
2879 // bytes in groups, which may not be aligned to the group
2880 // size. If both the new and old position fall within the
2881 // same unaligned group, then there is no benefit in moving
2882 // it and we can just continue to the next item.
2883 if likely(guard.is_in_same_group(i, new_i, hash)) {
2884 guard.set_ctrl_hash(i, hash);
2885 continue 'outer;
2886 }
2887
2888 let new_i_p = guard.bucket_ptr(new_i, size_of);
2889
2890 // We are moving the current item to a new position. Write
2891 // our H2 to the control byte of the new position.
2892 let prev_ctrl = guard.replace_ctrl_hash(new_i, hash);
2893 if prev_ctrl == Tag::EMPTY {
2894 guard.set_ctrl(i, Tag::EMPTY);
2895 // If the target slot is empty, simply move the current
2896 // element into the new slot and clear the old control
2897 // byte.
2898 ptr::copy_nonoverlapping(i_p, new_i_p, size_of);
2899 continue 'outer;
2900 } else {
2901 // If the target slot is occupied, swap the two elements
2902 // and then continue processing the element that we just
2903 // swapped into the old slot.
2904 debug_assert_eq!(prev_ctrl, Tag::DELETED);
2905 ptr::swap_nonoverlapping(i_p, new_i_p, size_of);
2906 continue 'inner;
2907 }
2908 }
2909 }
2910
2911 guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items;
2912
2913 mem::forget(guard);
2914 }
2915
2916 /// Deallocates the table without dropping any entries.
2917 ///
2918 /// # Note
2919 ///
2920 /// This function must be called only after [`drop_elements`](RawTableInner::drop_elements),
2921 /// else it can lead to leaking of memory. Also calling this function automatically
2922 /// makes invalid (dangling) all instances of buckets ([`Bucket`]) and makes invalid
2923 /// (dangling) the `ctrl` field of the table.
2924 ///
2925 /// # Safety
2926 ///
2927 /// If any of the following conditions are violated, the result is [`Undefined Behavior`]:
2928 ///
2929 /// * The [`RawTableInner`] has already been allocated;
2930 ///
2931 /// * The `alloc` must be the same [`Allocator`] as the `Allocator` that was used
2932 /// to allocate this table.
2933 ///
2934 /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout` that was used
2935 /// to allocate this table.
2936 ///
2937 /// See also [`GlobalAlloc::dealloc`] or [`Allocator::deallocate`] for more information.
2938 ///
2939 /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2940 /// [`GlobalAlloc::dealloc`]: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
2941 /// [`Allocator::deallocate`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html#tymethod.deallocate
2942 #[inline]
2943 unsafe fn free_buckets<A>(&mut self, alloc: &A, table_layout: TableLayout)
2944 where
2945 A: Allocator,
2946 {
2947 // SAFETY: The caller must uphold the safety contract for `free_buckets`
2948 // method.
2949 let (ptr, layout) = self.allocation_info(table_layout);
2950 alloc.deallocate(ptr, layout);
2951 }
2952
2953 /// Returns a pointer to the allocated memory and the layout that was used to
2954 /// allocate the table.
2955 ///
2956 /// # Safety
2957 ///
2958 /// Caller of this function must observe the following safety rules:
2959 ///
2960 /// * The [`RawTableInner`] has already been allocated, otherwise
2961 /// calling this function results in [`undefined behavior`]
2962 ///
2963 /// * The `table_layout` must be the same [`TableLayout`] as the `TableLayout`
2964 /// that was used to allocate this table. Failure to comply with this condition
2965 /// may result in [`undefined behavior`].
2966 ///
2967 /// See also [`GlobalAlloc::dealloc`] or [`Allocator::deallocate`] for more information.
2968 ///
2969 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2970 /// [`GlobalAlloc::dealloc`]: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
2971 /// [`Allocator::deallocate`]: https://doc.rust-lang.org/alloc/alloc/trait.Allocator.html#tymethod.deallocate
2972 #[inline]
2973 unsafe fn allocation_info(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) {
2974 debug_assert!(
2975 !self.is_empty_singleton(),
2976 "this function can only be called on non-empty tables"
2977 );
2978
2979 // Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
2980 let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
2981 Some(lco) => lco,
2982 None => unsafe { hint::unreachable_unchecked() },
2983 };
2984 (
2985 // SAFETY: The caller must uphold the safety contract for `allocation_info` method.
2986 unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) },
2987 layout,
2988 )
2989 }
2990
2991 /// Returns the total amount of memory allocated internally by the hash
2992 /// table, in bytes.
2993 ///
2994 /// The returned number is informational only. It is intended to be
2995 /// primarily used for memory profiling.
2996 ///
2997 /// # Safety
2998 ///
2999 /// The `table_layout` must be the same [`TableLayout`] as the `TableLayout`
3000 /// that was used to allocate this table. Failure to comply with this condition
3001 /// may result in [`undefined behavior`].
3002 ///
3003 ///
3004 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3005 #[inline]
3006 unsafe fn allocation_size_or_zero(&self, table_layout: TableLayout) -> usize {
3007 if self.is_empty_singleton() {
3008 0
3009 } else {
3010 // SAFETY:
3011 // 1. We have checked that our table is allocated.
3012 // 2. The caller ensures that `table_layout` matches the [`TableLayout`]
3013 // that was used to allocate this table.
3014 unsafe { self.allocation_info(table_layout).1.size() }
3015 }
3016 }
3017
3018 /// Marks all table buckets as empty without dropping their contents.
3019 #[inline]
3020 fn clear_no_drop(&mut self) {
3021 if !self.is_empty_singleton() {
3022 self.ctrl_slice().fill_empty();
3023 }
3024 self.items = 0;
3025 self.growth_left = bucket_mask_to_capacity(self.bucket_mask);
3026 }
3027
3028 /// Erases the [`Bucket`]'s control byte at the given index so that it does not
3029 /// triggered as full, decreases the `items` of the table and, if it can be done,
3030 /// increases `self.growth_left`.
3031 ///
3032 /// This function does not actually erase / drop the [`Bucket`] itself, i.e. it
3033 /// does not make any changes to the `data` parts of the table. The caller of this
3034 /// function must take care to properly drop the `data`, otherwise calling this
3035 /// function may result in a memory leak.
3036 ///
3037 /// # Safety
3038 ///
3039 /// You must observe the following safety rules when calling this function:
3040 ///
3041 /// * The [`RawTableInner`] has already been allocated;
3042 ///
3043 /// * It must be the full control byte at the given position;
3044 ///
3045 /// * The `index` must not be greater than the `RawTableInner.bucket_mask`, i.e.
3046 /// `index <= RawTableInner.bucket_mask` or, in other words, `(index + 1)` must
3047 /// be no greater than the number returned by the function [`RawTableInner::buckets`].
3048 ///
3049 /// Calling this function on a table that has not been allocated results in [`undefined behavior`].
3050 ///
3051 /// Calling this function on a table with no elements is unspecified, but calling subsequent
3052 /// functions is likely to result in [`undefined behavior`] due to overflow subtraction
3053 /// (`self.items -= 1 cause overflow when self.items == 0`).
3054 ///
3055 /// See also [`Bucket::as_ptr`] method, for more information about of properly removing
3056 /// or saving `data element` from / into the [`RawTable`] / [`RawTableInner`].
3057 ///
3058 /// [`RawTableInner::buckets`]: RawTableInner::buckets
3059 /// [`Bucket::as_ptr`]: Bucket::as_ptr
3060 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3061 #[inline]
3062 unsafe fn erase(&mut self, index: usize) {
3063 debug_assert!(self.is_bucket_full(index));
3064
3065 // This is the same as `index.wrapping_sub(Group::WIDTH) % self.buckets()` because
3066 // the number of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
3067 let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
3068 // SAFETY:
3069 // - The caller must uphold the safety contract for `erase` method;
3070 // - `index_before` is guaranteed to be in range due to masking with `self.bucket_mask`
3071 let empty_before = Group::load(self.ctrl(index_before)).match_empty();
3072 let empty_after = Group::load(self.ctrl(index)).match_empty();
3073
3074 // Inserting and searching in the map is performed by two key functions:
3075 //
3076 // - The `find_insert_slot` function that looks up the index of any `Tag::EMPTY` or `Tag::DELETED`
3077 // slot in a group to be able to insert. If it doesn't find an `Tag::EMPTY` or `Tag::DELETED`
3078 // slot immediately in the first group, it jumps to the next `Group` looking for it,
3079 // and so on until it has gone through all the groups in the control bytes.
3080 //
3081 // - The `find_inner` function that looks for the index of the desired element by looking
3082 // at all the `FULL` bytes in the group. If it did not find the element right away, and
3083 // there is no `Tag::EMPTY` byte in the group, then this means that the `find_insert_slot`
3084 // function may have found a suitable slot in the next group. Therefore, `find_inner`
3085 // jumps further, and if it does not find the desired element and again there is no `Tag::EMPTY`
3086 // byte, then it jumps further, and so on. The search stops only if `find_inner` function
3087 // finds the desired element or hits an `Tag::EMPTY` slot/byte.
3088 //
3089 // Accordingly, this leads to two consequences:
3090 //
3091 // - The map must have `Tag::EMPTY` slots (bytes);
3092 //
3093 // - You can't just mark the byte to be erased as `Tag::EMPTY`, because otherwise the `find_inner`
3094 // function may stumble upon an `Tag::EMPTY` byte before finding the desired element and stop
3095 // searching.
3096 //
3097 // Thus it is necessary to check all bytes after and before the erased element. If we are in
3098 // a contiguous `Group` of `FULL` or `Tag::DELETED` bytes (the number of `FULL` or `Tag::DELETED` bytes
3099 // before and after is greater than or equal to `Group::WIDTH`), then we must mark our byte as
3100 // `Tag::DELETED` in order for the `find_inner` function to go further. On the other hand, if there
3101 // is at least one `Tag::EMPTY` slot in the `Group`, then the `find_inner` function will still stumble
3102 // upon an `Tag::EMPTY` byte, so we can safely mark our erased byte as `Tag::EMPTY` as well.
3103 //
3104 // Finally, since `index_before == (index.wrapping_sub(Group::WIDTH) & self.bucket_mask) == index`
3105 // and given all of the above, tables smaller than the group width (self.buckets() < Group::WIDTH)
3106 // cannot have `Tag::DELETED` bytes.
3107 //
3108 // Note that in this context `leading_zeros` refers to the bytes at the end of a group, while
3109 // `trailing_zeros` refers to the bytes at the beginning of a group.
3110 let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH {
3111 Tag::DELETED
3112 } else {
3113 self.growth_left += 1;
3114 Tag::EMPTY
3115 };
3116 // SAFETY: the caller must uphold the safety contract for `erase` method.
3117 self.set_ctrl(index, ctrl);
3118 self.items -= 1;
3119 }
3120}
3121
3122impl<T: Clone, A: Allocator + Clone> Clone for RawTable<T, A> {
3123 fn clone(&self) -> Self {
3124 if self.table.is_empty_singleton() {
3125 Self::new_in(self.alloc.clone())
3126 } else {
3127 unsafe {
3128 // Avoid `Result::ok_or_else` because it bloats LLVM IR.
3129 //
3130 // SAFETY: This is safe as we are taking the size of an already allocated table
3131 // and therefore capacity overflow cannot occur, `self.table.buckets()` is power
3132 // of two and all allocator errors will be caught inside `RawTableInner::new_uninitialized`.
3133 let mut new_table = match Self::new_uninitialized(
3134 self.alloc.clone(),
3135 self.table.buckets(),
3136 Fallibility::Infallible,
3137 ) {
3138 Ok(table) => table,
3139 Err(_) => hint::unreachable_unchecked(),
3140 };
3141
3142 // Cloning elements may fail (the clone function may panic). But we don't
3143 // need to worry about uninitialized control bits, since:
3144 // 1. The number of items (elements) in the table is zero, which means that
3145 // the control bits will not be read by Drop function.
3146 // 2. The `clone_from_spec` method will first copy all control bits from
3147 // `self` (thus initializing them). But this will not affect the `Drop`
3148 // function, since the `clone_from_spec` function sets `items` only after
3149 // successfully cloning all elements.
3150 new_table.clone_from_spec(self);
3151 new_table
3152 }
3153 }
3154 }
3155
3156 fn clone_from(&mut self, source: &Self) {
3157 if source.table.is_empty_singleton() {
3158 let mut old_inner = mem::replace(&mut self.table, RawTableInner::NEW);
3159 unsafe {
3160 // SAFETY:
3161 // 1. We call the function only once;
3162 // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
3163 // and [`TableLayout`] that were used to allocate this table.
3164 // 3. If any elements' drop function panics, then there will only be a memory leak,
3165 // because we have replaced the inner table with a new one.
3166 old_inner.drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
3167 }
3168 } else {
3169 unsafe {
3170 // Make sure that if any panics occurs, we clear the table and
3171 // leave it in an empty state.
3172 let mut self_ = guard(self, |self_| {
3173 self_.clear_no_drop();
3174 });
3175
3176 // First, drop all our elements without clearing the control
3177 // bytes. If this panics then the scope guard will clear the
3178 // table, leaking any elements that were not dropped yet.
3179 //
3180 // This leak is unavoidable: we can't try dropping more elements
3181 // since this could lead to another panic and abort the process.
3182 //
3183 // SAFETY: If something gets wrong we clear our table right after
3184 // dropping the elements, so there is no double drop, since `items`
3185 // will be equal to zero.
3186 self_.table.drop_elements::<T>();
3187
3188 // If necessary, resize our table to match the source.
3189 if self_.buckets() != source.buckets() {
3190 let new_inner = match RawTableInner::new_uninitialized(
3191 &self_.alloc,
3192 Self::TABLE_LAYOUT,
3193 source.buckets(),
3194 Fallibility::Infallible,
3195 ) {
3196 Ok(table) => table,
3197 Err(_) => hint::unreachable_unchecked(),
3198 };
3199 // Replace the old inner with new uninitialized one. It's ok, since if something gets
3200 // wrong `ScopeGuard` will initialize all control bytes and leave empty table.
3201 let mut old_inner = mem::replace(&mut self_.table, new_inner);
3202 if !old_inner.is_empty_singleton() {
3203 // SAFETY:
3204 // 1. We have checked that our table is allocated.
3205 // 2. We know for sure that `alloc` and `table_layout` matches
3206 // the [`Allocator`] and [`TableLayout`] that were used to allocate this table.
3207 old_inner.free_buckets(&self_.alloc, Self::TABLE_LAYOUT);
3208 }
3209 }
3210
3211 // Cloning elements may fail (the clone function may panic), but the `ScopeGuard`
3212 // inside the `clone_from_impl` function will take care of that, dropping all
3213 // cloned elements if necessary. Our `ScopeGuard` will clear the table.
3214 self_.clone_from_spec(source);
3215
3216 // Disarm the scope guard if cloning was successful.
3217 ScopeGuard::into_inner(self_);
3218 }
3219 }
3220 }
3221}
3222
3223/// Specialization of `clone_from` for `Copy` types
3224trait RawTableClone {
3225 unsafe fn clone_from_spec(&mut self, source: &Self);
3226}
3227impl<T: Clone, A: Allocator + Clone> RawTableClone for RawTable<T, A> {
3228 default_fn! {
3229 #[cfg_attr(feature = "inline-more", inline)]
3230 unsafe fn clone_from_spec(&mut self, source: &Self) {
3231 self.clone_from_impl(source);
3232 }
3233 }
3234}
3235#[cfg(feature = "nightly")]
3236impl<T: Copy, A: Allocator + Clone> RawTableClone for RawTable<T, A> {
3237 #[cfg_attr(feature = "inline-more", inline)]
3238 unsafe fn clone_from_spec(&mut self, source: &Self) {
3239 source
3240 .table
3241 .ctrl(0)
3242 .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes());
3243 source
3244 .data_start()
3245 .as_ptr()
3246 .copy_to_nonoverlapping(self.data_start().as_ptr(), self.table.buckets());
3247
3248 self.table.items = source.table.items;
3249 self.table.growth_left = source.table.growth_left;
3250 }
3251}
3252
3253impl<T: Clone, A: Allocator + Clone> RawTable<T, A> {
3254 /// Common code for `clone` and `clone_from`. Assumes:
3255 /// - `self.buckets() == source.buckets()`.
3256 /// - Any existing elements have been dropped.
3257 /// - The control bytes are not initialized yet.
3258 #[cfg_attr(feature = "inline-more", inline)]
3259 unsafe fn clone_from_impl(&mut self, source: &Self) {
3260 // Copy the control bytes unchanged. We do this in a single pass
3261 source
3262 .table
3263 .ctrl(0)
3264 .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes());
3265
3266 // The cloning of elements may panic, in which case we need
3267 // to make sure we drop only the elements that have been
3268 // cloned so far.
3269 let mut guard = guard((0, &mut *self), |(index, self_)| {
3270 if T::NEEDS_DROP {
3271 for i in 0..*index {
3272 if self_.is_bucket_full(i) {
3273 self_.bucket(i).drop();
3274 }
3275 }
3276 }
3277 });
3278
3279 for from in source.iter() {
3280 let index = source.bucket_index(&from);
3281 let to = guard.1.bucket(index);
3282 to.write(from.as_ref().clone());
3283
3284 // Update the index in case we need to unwind.
3285 guard.0 = index + 1;
3286 }
3287
3288 // Successfully cloned all items, no need to clean up.
3289 mem::forget(guard);
3290
3291 self.table.items = source.table.items;
3292 self.table.growth_left = source.table.growth_left;
3293 }
3294}
3295
3296impl<T, A: Allocator + Default> Default for RawTable<T, A> {
3297 #[inline]
3298 fn default() -> Self {
3299 Self::new_in(Default::default())
3300 }
3301}
3302
3303#[cfg(feature = "nightly")]
3304unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawTable<T, A> {
3305 #[cfg_attr(feature = "inline-more", inline)]
3306 fn drop(&mut self) {
3307 unsafe {
3308 // SAFETY:
3309 // 1. We call the function only once;
3310 // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
3311 // and [`TableLayout`] that were used to allocate this table.
3312 // 3. If the drop function of any elements fails, then only a memory leak will occur,
3313 // and we don't care because we are inside the `Drop` function of the `RawTable`,
3314 // so there won't be any table left in an inconsistent state.
3315 self.table
3316 .drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
3317 }
3318 }
3319}
3320#[cfg(not(feature = "nightly"))]
3321impl<T, A: Allocator> Drop for RawTable<T, A> {
3322 #[cfg_attr(feature = "inline-more", inline)]
3323 fn drop(&mut self) {
3324 unsafe {
3325 // SAFETY:
3326 // 1. We call the function only once;
3327 // 2. We know for sure that `alloc` and `table_layout` matches the [`Allocator`]
3328 // and [`TableLayout`] that were used to allocate this table.
3329 // 3. If the drop function of any elements fails, then only a memory leak will occur,
3330 // and we don't care because we are inside the `Drop` function of the `RawTable`,
3331 // so there won't be any table left in an inconsistent state.
3332 self.table
3333 .drop_inner_table::<T, _>(&self.alloc, Self::TABLE_LAYOUT);
3334 }
3335 }
3336}
3337
3338impl<T, A: Allocator> IntoIterator for RawTable<T, A> {
3339 type Item = T;
3340 type IntoIter = RawIntoIter<T, A>;
3341
3342 #[cfg_attr(feature = "inline-more", inline)]
3343 fn into_iter(self) -> RawIntoIter<T, A> {
3344 unsafe {
3345 let iter = self.iter();
3346 self.into_iter_from(iter)
3347 }
3348 }
3349}
3350
3351/// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does
3352/// not track an item count.
3353pub(crate) struct RawIterRange<T> {
3354 // Mask of full buckets in the current group. Bits are cleared from this
3355 // mask as each element is processed.
3356 current_group: BitMaskIter,
3357
3358 // Pointer to the buckets for the current group.
3359 data: Bucket<T>,
3360
3361 // Pointer to the next group of control bytes,
3362 // Must be aligned to the group size.
3363 next_ctrl: *const u8,
3364
3365 // Pointer one past the last control byte of this range.
3366 end: *const u8,
3367}
3368
3369impl<T> RawIterRange<T> {
3370 /// Returns a `RawIterRange` covering a subset of a table.
3371 ///
3372 /// # Safety
3373 ///
3374 /// If any of the following conditions are violated, the result is
3375 /// [`undefined behavior`]:
3376 ///
3377 /// * `ctrl` must be [valid] for reads, i.e. table outlives the `RawIterRange`;
3378 ///
3379 /// * `ctrl` must be properly aligned to the group size (`Group::WIDTH`);
3380 ///
3381 /// * `ctrl` must point to the array of properly initialized control bytes;
3382 ///
3383 /// * `data` must be the [`Bucket`] at the `ctrl` index in the table;
3384 ///
3385 /// * the value of `len` must be less than or equal to the number of table buckets,
3386 /// and the returned value of `ctrl.as_ptr().add(len).offset_from(ctrl.as_ptr())`
3387 /// must be positive.
3388 ///
3389 /// * The `ctrl.add(len)` pointer must be either in bounds or one
3390 /// byte past the end of the same [allocated table].
3391 ///
3392 /// * The `len` must be a power of two.
3393 ///
3394 /// [valid]: https://doc.rust-lang.org/std/ptr/index.html#safety
3395 /// [`undefined behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3396 #[cfg_attr(feature = "inline-more", inline)]
3397 unsafe fn new(ctrl: *const u8, data: Bucket<T>, len: usize) -> Self {
3398 debug_assert_ne!(len, 0);
3399 debug_assert_eq!(ctrl as usize % Group::WIDTH, 0);
3400 // SAFETY: The caller must uphold the safety rules for the [`RawIterRange::new`]
3401 let end = ctrl.add(len);
3402
3403 // Load the first group and advance ctrl to point to the next group
3404 // SAFETY: The caller must uphold the safety rules for the [`RawIterRange::new`]
3405 let current_group = Group::load_aligned(ctrl.cast()).match_full();
3406 let next_ctrl = ctrl.add(Group::WIDTH);
3407
3408 Self {
3409 current_group: current_group.into_iter(),
3410 data,
3411 next_ctrl,
3412 end,
3413 }
3414 }
3415
3416 /// Splits a `RawIterRange` into two halves.
3417 ///
3418 /// Returns `None` if the remaining range is smaller than or equal to the
3419 /// group width.
3420 #[cfg_attr(feature = "inline-more", inline)]
3421 #[cfg(feature = "rayon")]
3422 pub(crate) fn split(mut self) -> (Self, Option<RawIterRange<T>>) {
3423 unsafe {
3424 if self.end <= self.next_ctrl {
3425 // Nothing to split if the group that we are current processing
3426 // is the last one.
3427 (self, None)
3428 } else {
3429 // len is the remaining number of elements after the group that
3430 // we are currently processing. It must be a multiple of the
3431 // group size (small tables are caught by the check above).
3432 let len = offset_from(self.end, self.next_ctrl);
3433 debug_assert_eq!(len % Group::WIDTH, 0);
3434
3435 // Split the remaining elements into two halves, but round the
3436 // midpoint down in case there is an odd number of groups
3437 // remaining. This ensures that:
3438 // - The tail is at least 1 group long.
3439 // - The split is roughly even considering we still have the
3440 // current group to process.
3441 let mid = (len / 2) & !(Group::WIDTH - 1);
3442
3443 let tail = Self::new(
3444 self.next_ctrl.add(mid),
3445 self.data.next_n(Group::WIDTH).next_n(mid),
3446 len - mid,
3447 );
3448 debug_assert_eq!(
3449 self.data.next_n(Group::WIDTH).next_n(mid).ptr,
3450 tail.data.ptr
3451 );
3452 debug_assert_eq!(self.end, tail.end);
3453 self.end = self.next_ctrl.add(mid);
3454 debug_assert_eq!(self.end.add(Group::WIDTH), tail.next_ctrl);
3455 (self, Some(tail))
3456 }
3457 }
3458 }
3459
3460 /// # Safety
3461 /// If `DO_CHECK_PTR_RANGE` is false, caller must ensure that we never try to iterate
3462 /// after yielding all elements.
3463 #[cfg_attr(feature = "inline-more", inline)]
3464 unsafe fn next_impl<const DO_CHECK_PTR_RANGE: bool>(&mut self) -> Option<Bucket<T>> {
3465 loop {
3466 if let Some(index) = self.current_group.next() {
3467 return Some(self.data.next_n(index));
3468 }
3469
3470 if DO_CHECK_PTR_RANGE && self.next_ctrl >= self.end {
3471 return None;
3472 }
3473
3474 // We might read past self.end up to the next group boundary,
3475 // but this is fine because it only occurs on tables smaller
3476 // than the group size where the trailing control bytes are all
3477 // EMPTY. On larger tables self.end is guaranteed to be aligned
3478 // to the group size (since tables are power-of-two sized).
3479 self.current_group = Group::load_aligned(self.next_ctrl.cast())
3480 .match_full()
3481 .into_iter();
3482 self.data = self.data.next_n(Group::WIDTH);
3483 self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
3484 }
3485 }
3486
3487 /// Folds every element into an accumulator by applying an operation,
3488 /// returning the final result.
3489 ///
3490 /// `fold_impl()` takes three arguments: the number of items remaining in
3491 /// the iterator, an initial value, and a closure with two arguments: an
3492 /// 'accumulator', and an element. The closure returns the value that the
3493 /// accumulator should have for the next iteration.
3494 ///
3495 /// The initial value is the value the accumulator will have on the first call.
3496 ///
3497 /// After applying this closure to every element of the iterator, `fold_impl()`
3498 /// returns the accumulator.
3499 ///
3500 /// # Safety
3501 ///
3502 /// If any of the following conditions are violated, the result is
3503 /// [`Undefined Behavior`]:
3504 ///
3505 /// * The [`RawTableInner`] / [`RawTable`] must be alive and not moved,
3506 /// i.e. table outlives the `RawIterRange`;
3507 ///
3508 /// * The provided `n` value must match the actual number of items
3509 /// in the table.
3510 ///
3511 /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3512 #[allow(clippy::while_let_on_iterator)]
3513 #[cfg_attr(feature = "inline-more", inline)]
3514 unsafe fn fold_impl<F, B>(mut self, mut n: usize, mut acc: B, mut f: F) -> B
3515 where
3516 F: FnMut(B, Bucket<T>) -> B,
3517 {
3518 loop {
3519 while let Some(index) = self.current_group.next() {
3520 // The returned `index` will always be in the range `0..Group::WIDTH`,
3521 // so that calling `self.data.next_n(index)` is safe (see detailed explanation below).
3522 debug_assert!(n != 0);
3523 let bucket = self.data.next_n(index);
3524 acc = f(acc, bucket);
3525 n -= 1;
3526 }
3527
3528 if n == 0 {
3529 return acc;
3530 }
3531
3532 // SAFETY: The caller of this function ensures that:
3533 //
3534 // 1. The provided `n` value matches the actual number of items in the table;
3535 // 2. The table is alive and did not moved.
3536 //
3537 // Taking the above into account, we always stay within the bounds, because:
3538 //
3539 // 1. For tables smaller than the group width (self.buckets() <= Group::WIDTH),
3540 // we will never end up in the given branch, since we should have already
3541 // yielded all the elements of the table.
3542 //
3543 // 2. For tables larger than the group width. The number of buckets is a
3544 // power of two (2 ^ n), Group::WIDTH is also power of two (2 ^ k). Since
3545 // `(2 ^ n) > (2 ^ k)`, than `(2 ^ n) % (2 ^ k) = 0`. As we start from the
3546 // start of the array of control bytes, and never try to iterate after
3547 // getting all the elements, the last `self.current_group` will read bytes
3548 // from the `self.buckets() - Group::WIDTH` index. We know also that
3549 // `self.current_group.next()` will always return indices within the range
3550 // `0..Group::WIDTH`.
3551 //
3552 // Knowing all of the above and taking into account that we are synchronizing
3553 // the `self.data` index with the index we used to read the `self.current_group`,
3554 // the subsequent `self.data.next_n(index)` will always return a bucket with
3555 // an index number less than `self.buckets()`.
3556 //
3557 // The last `self.next_ctrl`, whose index would be `self.buckets()`, will never
3558 // actually be read, since we should have already yielded all the elements of
3559 // the table.
3560 self.current_group = Group::load_aligned(self.next_ctrl.cast())
3561 .match_full()
3562 .into_iter();
3563 self.data = self.data.next_n(Group::WIDTH);
3564 self.next_ctrl = self.next_ctrl.add(Group::WIDTH);
3565 }
3566 }
3567}
3568
3569// We make raw iterators unconditionally Send and Sync, and let the PhantomData
3570// in the actual iterator implementations determine the real Send/Sync bounds.
3571unsafe impl<T> Send for RawIterRange<T> {}
3572unsafe impl<T> Sync for RawIterRange<T> {}
3573
3574impl<T> Clone for RawIterRange<T> {
3575 #[cfg_attr(feature = "inline-more", inline)]
3576 fn clone(&self) -> Self {
3577 Self {
3578 data: self.data.clone(),
3579 next_ctrl: self.next_ctrl,
3580 current_group: self.current_group.clone(),
3581 end: self.end,
3582 }
3583 }
3584}
3585
3586impl<T> Iterator for RawIterRange<T> {
3587 type Item = Bucket<T>;
3588
3589 #[cfg_attr(feature = "inline-more", inline)]
3590 fn next(&mut self) -> Option<Bucket<T>> {
3591 unsafe {
3592 // SAFETY: We set checker flag to true.
3593 self.next_impl::<true>()
3594 }
3595 }
3596
3597 #[inline]
3598 fn size_hint(&self) -> (usize, Option<usize>) {
3599 // We don't have an item count, so just guess based on the range size.
3600 let remaining_buckets = if self.end > self.next_ctrl {
3601 unsafe { offset_from(self.end, self.next_ctrl) }
3602 } else {
3603 0
3604 };
3605
3606 // Add a group width to include the group we are currently processing.
3607 (0, Some(Group::WIDTH + remaining_buckets))
3608 }
3609}
3610
3611impl<T> FusedIterator for RawIterRange<T> {}
3612
3613/// Iterator which returns a raw pointer to every full bucket in the table.
3614///
3615/// For maximum flexibility this iterator is not bound by a lifetime, but you
3616/// must observe several rules when using it:
3617/// - You must not free the hash table while iterating (including via growing/shrinking).
3618/// - It is fine to erase a bucket that has been yielded by the iterator.
3619/// - Erasing a bucket that has not yet been yielded by the iterator may still
3620/// result in the iterator yielding that bucket (unless `reflect_remove` is called).
3621/// - It is unspecified whether an element inserted after the iterator was
3622/// created will be yielded by that iterator (unless `reflect_insert` is called).
3623/// - The order in which the iterator yields bucket is unspecified and may
3624/// change in the future.
3625pub struct RawIter<T> {
3626 pub(crate) iter: RawIterRange<T>,
3627 items: usize,
3628}
3629
3630impl<T> RawIter<T> {
3631 unsafe fn drop_elements(&mut self) {
3632 if T::NEEDS_DROP && self.items != 0 {
3633 for item in self {
3634 item.drop();
3635 }
3636 }
3637 }
3638}
3639
3640impl<T> Clone for RawIter<T> {
3641 #[cfg_attr(feature = "inline-more", inline)]
3642 fn clone(&self) -> Self {
3643 Self {
3644 iter: self.iter.clone(),
3645 items: self.items,
3646 }
3647 }
3648}
3649impl<T> Default for RawIter<T> {
3650 #[cfg_attr(feature = "inline-more", inline)]
3651 fn default() -> Self {
3652 // SAFETY: Because the table is static, it always outlives the iter.
3653 unsafe { RawTableInner::NEW.iter() }
3654 }
3655}
3656
3657impl<T> Iterator for RawIter<T> {
3658 type Item = Bucket<T>;
3659
3660 #[cfg_attr(feature = "inline-more", inline)]
3661 fn next(&mut self) -> Option<Bucket<T>> {
3662 // Inner iterator iterates over buckets
3663 // so it can do unnecessary work if we already yielded all items.
3664 if self.items == 0 {
3665 return None;
3666 }
3667
3668 let nxt = unsafe {
3669 // SAFETY: We check number of items to yield using `items` field.
3670 self.iter.next_impl::<false>()
3671 };
3672
3673 debug_assert!(nxt.is_some());
3674 self.items -= 1;
3675
3676 nxt
3677 }
3678
3679 #[inline]
3680 fn size_hint(&self) -> (usize, Option<usize>) {
3681 (self.items, Some(self.items))
3682 }
3683
3684 #[inline]
3685 fn fold<B, F>(self, init: B, f: F) -> B
3686 where
3687 Self: Sized,
3688 F: FnMut(B, Self::Item) -> B,
3689 {
3690 unsafe { self.iter.fold_impl(self.items, init, f) }
3691 }
3692}
3693
3694impl<T> ExactSizeIterator for RawIter<T> {}
3695impl<T> FusedIterator for RawIter<T> {}
3696
3697/// Iterator which returns an index of every full bucket in the table.
3698///
3699/// For maximum flexibility this iterator is not bound by a lifetime, but you
3700/// must observe several rules when using it:
3701/// - You must not free the hash table while iterating (including via growing/shrinking).
3702/// - It is fine to erase a bucket that has been yielded by the iterator.
3703/// - Erasing a bucket that has not yet been yielded by the iterator may still
3704/// result in the iterator yielding index of that bucket.
3705/// - It is unspecified whether an element inserted after the iterator was
3706/// created will be yielded by that iterator.
3707/// - The order in which the iterator yields indices of the buckets is unspecified
3708/// and may change in the future.
3709pub(crate) struct FullBucketsIndices {
3710 // Mask of full buckets in the current group. Bits are cleared from this
3711 // mask as each element is processed.
3712 current_group: BitMaskIter,
3713
3714 // Initial value of the bytes' indices of the current group (relative
3715 // to the start of the control bytes).
3716 group_first_index: usize,
3717
3718 // Pointer to the current group of control bytes,
3719 // Must be aligned to the group size (Group::WIDTH).
3720 ctrl: NonNull<u8>,
3721
3722 // Number of elements in the table.
3723 items: usize,
3724}
3725
3726impl FullBucketsIndices {
3727 /// Advances the iterator and returns the next value.
3728 ///
3729 /// # Safety
3730 ///
3731 /// If any of the following conditions are violated, the result is
3732 /// [`Undefined Behavior`]:
3733 ///
3734 /// * The [`RawTableInner`] / [`RawTable`] must be alive and not moved,
3735 /// i.e. table outlives the `FullBucketsIndices`;
3736 ///
3737 /// * It never tries to iterate after getting all elements.
3738 ///
3739 /// [`Undefined Behavior`]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3740 #[inline(always)]
3741 unsafe fn next_impl(&mut self) -> Option<usize> {
3742 loop {
3743 if let Some(index) = self.current_group.next() {
3744 // The returned `self.group_first_index + index` will always
3745 // be in the range `0..self.buckets()`. See explanation below.
3746 return Some(self.group_first_index + index);
3747 }
3748
3749 // SAFETY: The caller of this function ensures that:
3750 //
3751 // 1. It never tries to iterate after getting all the elements;
3752 // 2. The table is alive and did not moved;
3753 // 3. The first `self.ctrl` pointed to the start of the array of control bytes.
3754 //
3755 // Taking the above into account, we always stay within the bounds, because:
3756 //
3757 // 1. For tables smaller than the group width (self.buckets() <= Group::WIDTH),
3758 // we will never end up in the given branch, since we should have already
3759 // yielded all the elements of the table.
3760 //
3761 // 2. For tables larger than the group width. The number of buckets is a
3762 // power of two (2 ^ n), Group::WIDTH is also power of two (2 ^ k). Since
3763 // `(2 ^ n) > (2 ^ k)`, than `(2 ^ n) % (2 ^ k) = 0`. As we start from the
3764 // the start of the array of control bytes, and never try to iterate after
3765 // getting all the elements, the last `self.ctrl` will be equal to
3766 // the `self.buckets() - Group::WIDTH`, so `self.current_group.next()`
3767 // will always contains indices within the range `0..Group::WIDTH`,
3768 // and subsequent `self.group_first_index + index` will always return a
3769 // number less than `self.buckets()`.
3770 self.ctrl = NonNull::new_unchecked(self.ctrl.as_ptr().add(Group::WIDTH));
3771
3772 // SAFETY: See explanation above.
3773 self.current_group = Group::load_aligned(self.ctrl.as_ptr().cast())
3774 .match_full()
3775 .into_iter();
3776 self.group_first_index += Group::WIDTH;
3777 }
3778 }
3779}
3780
3781impl Iterator for FullBucketsIndices {
3782 type Item = usize;
3783
3784 /// Advances the iterator and returns the next value. It is up to
3785 /// the caller to ensure that the `RawTable` outlives the `FullBucketsIndices`,
3786 /// because we cannot make the `next` method unsafe.
3787 #[inline(always)]
3788 fn next(&mut self) -> Option<usize> {
3789 // Return if we already yielded all items.
3790 if self.items == 0 {
3791 return None;
3792 }
3793
3794 let nxt = unsafe {
3795 // SAFETY:
3796 // 1. We check number of items to yield using `items` field.
3797 // 2. The caller ensures that the table is alive and has not moved.
3798 self.next_impl()
3799 };
3800
3801 debug_assert!(nxt.is_some());
3802 self.items -= 1;
3803
3804 nxt
3805 }
3806
3807 #[inline(always)]
3808 fn size_hint(&self) -> (usize, Option<usize>) {
3809 (self.items, Some(self.items))
3810 }
3811}
3812
3813impl ExactSizeIterator for FullBucketsIndices {}
3814impl FusedIterator for FullBucketsIndices {}
3815
3816/// Iterator which consumes a table and returns elements.
3817pub struct RawIntoIter<T, A: Allocator = Global> {
3818 iter: RawIter<T>,
3819 allocation: Option<(NonNull<u8>, Layout, A)>,
3820 marker: PhantomData<T>,
3821}
3822
3823impl<T, A: Allocator> RawIntoIter<T, A> {
3824 #[cfg_attr(feature = "inline-more", inline)]
3825 pub fn iter(&self) -> RawIter<T> {
3826 self.iter.clone()
3827 }
3828}
3829
3830unsafe impl<T, A: Allocator> Send for RawIntoIter<T, A>
3831where
3832 T: Send,
3833 A: Send,
3834{
3835}
3836unsafe impl<T, A: Allocator> Sync for RawIntoIter<T, A>
3837where
3838 T: Sync,
3839 A: Sync,
3840{
3841}
3842
3843#[cfg(feature = "nightly")]
3844unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawIntoIter<T, A> {
3845 #[cfg_attr(feature = "inline-more", inline)]
3846 fn drop(&mut self) {
3847 unsafe {
3848 // Drop all remaining elements
3849 self.iter.drop_elements();
3850
3851 // Free the table
3852 if let Some((ptr, layout, ref alloc)) = self.allocation {
3853 alloc.deallocate(ptr, layout);
3854 }
3855 }
3856 }
3857}
3858#[cfg(not(feature = "nightly"))]
3859impl<T, A: Allocator> Drop for RawIntoIter<T, A> {
3860 #[cfg_attr(feature = "inline-more", inline)]
3861 fn drop(&mut self) {
3862 unsafe {
3863 // Drop all remaining elements
3864 self.iter.drop_elements();
3865
3866 // Free the table
3867 if let Some((ptr, layout, ref alloc)) = self.allocation {
3868 alloc.deallocate(ptr, layout);
3869 }
3870 }
3871 }
3872}
3873
3874impl<T, A: Allocator> Default for RawIntoIter<T, A> {
3875 fn default() -> Self {
3876 Self {
3877 iter: Default::default(),
3878 allocation: None,
3879 marker: PhantomData,
3880 }
3881 }
3882}
3883impl<T, A: Allocator> Iterator for RawIntoIter<T, A> {
3884 type Item = T;
3885
3886 #[cfg_attr(feature = "inline-more", inline)]
3887 fn next(&mut self) -> Option<T> {
3888 unsafe { Some(self.iter.next()?.read()) }
3889 }
3890
3891 #[inline]
3892 fn size_hint(&self) -> (usize, Option<usize>) {
3893 self.iter.size_hint()
3894 }
3895}
3896
3897impl<T, A: Allocator> ExactSizeIterator for RawIntoIter<T, A> {}
3898impl<T, A: Allocator> FusedIterator for RawIntoIter<T, A> {}
3899
3900/// Iterator which consumes elements without freeing the table storage.
3901pub struct RawDrain<'a, T, A: Allocator = Global> {
3902 iter: RawIter<T>,
3903
3904 // The table is moved into the iterator for the duration of the drain. This
3905 // ensures that an empty table is left if the drain iterator is leaked
3906 // without dropping.
3907 table: RawTableInner,
3908 orig_table: NonNull<RawTableInner>,
3909
3910 // We don't use a &'a mut RawTable<T> because we want RawDrain to be
3911 // covariant over T.
3912 marker: PhantomData<&'a RawTable<T, A>>,
3913}
3914
3915impl<T, A: Allocator> RawDrain<'_, T, A> {
3916 #[cfg_attr(feature = "inline-more", inline)]
3917 pub fn iter(&self) -> RawIter<T> {
3918 self.iter.clone()
3919 }
3920}
3921
3922unsafe impl<T, A: Allocator> Send for RawDrain<'_, T, A>
3923where
3924 T: Send,
3925 A: Send,
3926{
3927}
3928unsafe impl<T, A: Allocator> Sync for RawDrain<'_, T, A>
3929where
3930 T: Sync,
3931 A: Sync,
3932{
3933}
3934
3935impl<T, A: Allocator> Drop for RawDrain<'_, T, A> {
3936 #[cfg_attr(feature = "inline-more", inline)]
3937 fn drop(&mut self) {
3938 unsafe {
3939 // Drop all remaining elements. Note that this may panic.
3940 self.iter.drop_elements();
3941
3942 // Reset the contents of the table now that all elements have been
3943 // dropped.
3944 self.table.clear_no_drop();
3945
3946 // Move the now empty table back to its original location.
3947 self.orig_table
3948 .as_ptr()
3949 .copy_from_nonoverlapping(&self.table, 1);
3950 }
3951 }
3952}
3953
3954impl<T, A: Allocator> Iterator for RawDrain<'_, T, A> {
3955 type Item = T;
3956
3957 #[cfg_attr(feature = "inline-more", inline)]
3958 fn next(&mut self) -> Option<T> {
3959 unsafe {
3960 let item = self.iter.next()?;
3961 Some(item.read())
3962 }
3963 }
3964
3965 #[inline]
3966 fn size_hint(&self) -> (usize, Option<usize>) {
3967 self.iter.size_hint()
3968 }
3969}
3970
3971impl<T, A: Allocator> ExactSizeIterator for RawDrain<'_, T, A> {}
3972impl<T, A: Allocator> FusedIterator for RawDrain<'_, T, A> {}
3973
3974/// Iterator over occupied buckets that could match a given hash.
3975///
3976/// `RawTable` only stores 7 bits of the hash value, so this iterator may return
3977/// items that have a hash value different than the one provided. You should
3978/// always validate the returned values before using them.
3979///
3980/// For maximum flexibility this iterator is not bound by a lifetime, but you
3981/// must observe several rules when using it:
3982/// - You must not free the hash table while iterating (including via growing/shrinking).
3983/// - It is fine to erase a bucket that has been yielded by the iterator.
3984/// - Erasing a bucket that has not yet been yielded by the iterator may still
3985/// result in the iterator yielding that bucket.
3986/// - It is unspecified whether an element inserted after the iterator was
3987/// created will be yielded by that iterator.
3988/// - The order in which the iterator yields buckets is unspecified and may
3989/// change in the future.
3990pub struct RawIterHash<T> {
3991 inner: RawIterHashInner,
3992 _marker: PhantomData<T>,
3993}
3994
3995#[derive(Clone)]
3996struct RawIterHashInner {
3997 // See `RawTableInner`'s corresponding fields for details.
3998 // We can't store a `*const RawTableInner` as it would get
3999 // invalidated by the user calling `&mut` methods on `RawTable`.
4000 bucket_mask: usize,
4001 ctrl: NonNull<u8>,
4002
4003 // The top 7 bits of the hash.
4004 tag_hash: Tag,
4005
4006 // The sequence of groups to probe in the search.
4007 probe_seq: ProbeSeq,
4008
4009 group: Group,
4010
4011 // The elements within the group with a matching tag-hash.
4012 bitmask: BitMaskIter,
4013}
4014
4015impl<T> RawIterHash<T> {
4016 #[cfg_attr(feature = "inline-more", inline)]
4017 unsafe fn new<A: Allocator>(table: &RawTable<T, A>, hash: u64) -> Self {
4018 RawIterHash {
4019 inner: RawIterHashInner::new(&table.table, hash),
4020 _marker: PhantomData,
4021 }
4022 }
4023}
4024
4025impl<T> Clone for RawIterHash<T> {
4026 #[cfg_attr(feature = "inline-more", inline)]
4027 fn clone(&self) -> Self {
4028 Self {
4029 inner: self.inner.clone(),
4030 _marker: PhantomData,
4031 }
4032 }
4033}
4034
4035impl<T> Default for RawIterHash<T> {
4036 #[cfg_attr(feature = "inline-more", inline)]
4037 fn default() -> Self {
4038 Self {
4039 // SAFETY: Because the table is static, it always outlives the iter.
4040 inner: unsafe { RawIterHashInner::new(&RawTableInner::NEW, 0) },
4041 _marker: PhantomData,
4042 }
4043 }
4044}
4045
4046impl RawIterHashInner {
4047 #[cfg_attr(feature = "inline-more", inline)]
4048 unsafe fn new(table: &RawTableInner, hash: u64) -> Self {
4049 let tag_hash = Tag::full(hash);
4050 let probe_seq = table.probe_seq(hash);
4051 let group = Group::load(table.ctrl(probe_seq.pos));
4052 let bitmask = group.match_tag(tag_hash).into_iter();
4053
4054 RawIterHashInner {
4055 bucket_mask: table.bucket_mask,
4056 ctrl: table.ctrl,
4057 tag_hash,
4058 probe_seq,
4059 group,
4060 bitmask,
4061 }
4062 }
4063}
4064
4065impl<T> Iterator for RawIterHash<T> {
4066 type Item = Bucket<T>;
4067
4068 fn next(&mut self) -> Option<Bucket<T>> {
4069 unsafe {
4070 match self.inner.next() {
4071 Some(index) => {
4072 // Can't use `RawTable::bucket` here as we don't have
4073 // an actual `RawTable` reference to use.
4074 debug_assert!(index <= self.inner.bucket_mask);
4075 let bucket = Bucket::from_base_index(self.inner.ctrl.cast(), index);
4076 Some(bucket)
4077 }
4078 None => None,
4079 }
4080 }
4081 }
4082}
4083
4084impl Iterator for RawIterHashInner {
4085 type Item = usize;
4086
4087 fn next(&mut self) -> Option<Self::Item> {
4088 unsafe {
4089 loop {
4090 if let Some(bit) = self.bitmask.next() {
4091 let index = (self.probe_seq.pos + bit) & self.bucket_mask;
4092 return Some(index);
4093 }
4094 if likely(self.group.match_empty().any_bit_set()) {
4095 return None;
4096 }
4097 self.probe_seq.move_next(self.bucket_mask);
4098
4099 // Can't use `RawTableInner::ctrl` here as we don't have
4100 // an actual `RawTableInner` reference to use.
4101 let index = self.probe_seq.pos;
4102 debug_assert!(index < self.bucket_mask + 1 + Group::WIDTH);
4103 let group_ctrl = self.ctrl.as_ptr().add(index).cast();
4104
4105 self.group = Group::load(group_ctrl);
4106 self.bitmask = self.group.match_tag(self.tag_hash).into_iter();
4107 }
4108 }
4109 }
4110}
4111
4112pub(crate) struct RawExtractIf<'a, T, A: Allocator> {
4113 pub iter: RawIter<T>,
4114 pub table: &'a mut RawTable<T, A>,
4115}
4116
4117impl<T, A: Allocator> RawExtractIf<'_, T, A> {
4118 #[cfg_attr(feature = "inline-more", inline)]
4119 pub(crate) fn next<F>(&mut self, mut f: F) -> Option<T>
4120 where
4121 F: FnMut(&mut T) -> bool,
4122 {
4123 unsafe {
4124 for item in &mut self.iter {
4125 if f(item.as_mut()) {
4126 return Some(self.table.remove(item).0);
4127 }
4128 }
4129 }
4130 None
4131 }
4132}
4133
4134#[cfg(test)]
4135mod test_map {
4136 use super::*;
4137
4138 fn rehash_in_place<T>(table: &mut RawTable<T>, hasher: impl Fn(&T) -> u64) {
4139 unsafe {
4140 table.table.rehash_in_place(
4141 &|table, index| hasher(table.bucket::<T>(index).as_ref()),
4142 mem::size_of::<T>(),
4143 if mem::needs_drop::<T>() {
4144 Some(|ptr| ptr::drop_in_place(ptr as *mut T))
4145 } else {
4146 None
4147 },
4148 );
4149 }
4150 }
4151
4152 #[test]
4153 fn rehash() {
4154 let mut table = RawTable::new();
4155 let hasher = |i: &u64| *i;
4156 for i in 0..100 {
4157 table.insert(i, i, hasher);
4158 }
4159
4160 for i in 0..100 {
4161 unsafe {
4162 assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i));
4163 }
4164 assert!(table.find(i + 100, |x| *x == i + 100).is_none());
4165 }
4166
4167 rehash_in_place(&mut table, hasher);
4168
4169 for i in 0..100 {
4170 unsafe {
4171 assert_eq!(table.find(i, |x| *x == i).map(|b| b.read()), Some(i));
4172 }
4173 assert!(table.find(i + 100, |x| *x == i + 100).is_none());
4174 }
4175 }
4176
4177 /// CHECKING THAT WE ARE NOT TRYING TO READ THE MEMORY OF
4178 /// AN UNINITIALIZED TABLE DURING THE DROP
4179 #[test]
4180 fn test_drop_uninitialized() {
4181 use ::alloc::vec::Vec;
4182
4183 let table = unsafe {
4184 // SAFETY: The `buckets` is power of two and we're not
4185 // trying to actually use the returned RawTable.
4186 RawTable::<(u64, Vec<i32>)>::new_uninitialized(Global, 8, Fallibility::Infallible)
4187 .unwrap()
4188 };
4189 drop(table);
4190 }
4191
4192 /// CHECKING THAT WE DON'T TRY TO DROP DATA IF THE `ITEMS`
4193 /// ARE ZERO, EVEN IF WE HAVE `FULL` CONTROL BYTES.
4194 #[test]
4195 fn test_drop_zero_items() {
4196 use ::alloc::vec::Vec;
4197 unsafe {
4198 // SAFETY: The `buckets` is power of two and we're not
4199 // trying to actually use the returned RawTable.
4200 let mut table =
4201 RawTable::<(u64, Vec<i32>)>::new_uninitialized(Global, 8, Fallibility::Infallible)
4202 .unwrap();
4203
4204 // WE SIMULATE, AS IT WERE, A FULL TABLE.
4205
4206 // SAFETY: We checked that the table is allocated and therefore the table already has
4207 // `self.bucket_mask + 1 + Group::WIDTH` number of control bytes (see TableLayout::calculate_layout_for)
4208 // so writing `table.table.num_ctrl_bytes() == bucket_mask + 1 + Group::WIDTH` bytes is safe.
4209 table.table.ctrl_slice().fill_empty();
4210
4211 // SAFETY: table.capacity() is guaranteed to be smaller than table.buckets()
4212 table.table.ctrl(0).write_bytes(0, table.capacity());
4213
4214 // Fix up the trailing control bytes. See the comments in set_ctrl
4215 // for the handling of tables smaller than the group width.
4216 if table.buckets() < Group::WIDTH {
4217 // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of control bytes,
4218 // so copying `self.buckets() == self.bucket_mask + 1` bytes with offset equal to
4219 // `Group::WIDTH` is safe
4220 table
4221 .table
4222 .ctrl(0)
4223 .copy_to(table.table.ctrl(Group::WIDTH), table.table.buckets());
4224 } else {
4225 // SAFETY: We have `self.bucket_mask + 1 + Group::WIDTH` number of
4226 // control bytes,so copying `Group::WIDTH` bytes with offset equal
4227 // to `self.buckets() == self.bucket_mask + 1` is safe
4228 table
4229 .table
4230 .ctrl(0)
4231 .copy_to(table.table.ctrl(table.table.buckets()), Group::WIDTH);
4232 }
4233 drop(table);
4234 }
4235 }
4236
4237 /// CHECKING THAT WE DON'T TRY TO DROP DATA IF THE `ITEMS`
4238 /// ARE ZERO, EVEN IF WE HAVE `FULL` CONTROL BYTES.
4239 #[test]
4240 fn test_catch_panic_clone_from() {
4241 use ::alloc::sync::Arc;
4242 use ::alloc::vec::Vec;
4243 use allocator_api2::alloc::{AllocError, Allocator, Global};
4244 use core::sync::atomic::{AtomicI8, Ordering};
4245 use std::thread;
4246
4247 struct MyAllocInner {
4248 drop_count: Arc<AtomicI8>,
4249 }
4250
4251 #[derive(Clone)]
4252 struct MyAlloc {
4253 _inner: Arc<MyAllocInner>,
4254 }
4255
4256 impl Drop for MyAllocInner {
4257 fn drop(&mut self) {
4258 println!("MyAlloc freed.");
4259 self.drop_count.fetch_sub(1, Ordering::SeqCst);
4260 }
4261 }
4262
4263 unsafe impl Allocator for MyAlloc {
4264 fn allocate(&self, layout: Layout) -> std::result::Result<NonNull<[u8]>, AllocError> {
4265 let g = Global;
4266 g.allocate(layout)
4267 }
4268
4269 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
4270 let g = Global;
4271 g.deallocate(ptr, layout)
4272 }
4273 }
4274
4275 const DISARMED: bool = false;
4276 const ARMED: bool = true;
4277
4278 struct CheckedCloneDrop {
4279 panic_in_clone: bool,
4280 dropped: bool,
4281 need_drop: Vec<u64>,
4282 }
4283
4284 impl Clone for CheckedCloneDrop {
4285 fn clone(&self) -> Self {
4286 if self.panic_in_clone {
4287 panic!("panic in clone")
4288 }
4289 Self {
4290 panic_in_clone: self.panic_in_clone,
4291 dropped: self.dropped,
4292 need_drop: self.need_drop.clone(),
4293 }
4294 }
4295 }
4296
4297 impl Drop for CheckedCloneDrop {
4298 fn drop(&mut self) {
4299 if self.dropped {
4300 panic!("double drop");
4301 }
4302 self.dropped = true;
4303 }
4304 }
4305
4306 let dropped: Arc<AtomicI8> = Arc::new(AtomicI8::new(2));
4307
4308 let mut table = RawTable::new_in(MyAlloc {
4309 _inner: Arc::new(MyAllocInner {
4310 drop_count: dropped.clone(),
4311 }),
4312 });
4313
4314 for (idx, panic_in_clone) in core::iter::repeat(DISARMED).take(7).enumerate() {
4315 let idx = idx as u64;
4316 table.insert(
4317 idx,
4318 (
4319 idx,
4320 CheckedCloneDrop {
4321 panic_in_clone,
4322 dropped: false,
4323 need_drop: vec![idx],
4324 },
4325 ),
4326 |(k, _)| *k,
4327 );
4328 }
4329
4330 assert_eq!(table.len(), 7);
4331
4332 thread::scope(|s| {
4333 let result = s.spawn(|| {
4334 let armed_flags = [
4335 DISARMED, DISARMED, ARMED, DISARMED, DISARMED, DISARMED, DISARMED,
4336 ];
4337 let mut scope_table = RawTable::new_in(MyAlloc {
4338 _inner: Arc::new(MyAllocInner {
4339 drop_count: dropped.clone(),
4340 }),
4341 });
4342 for (idx, &panic_in_clone) in armed_flags.iter().enumerate() {
4343 let idx = idx as u64;
4344 scope_table.insert(
4345 idx,
4346 (
4347 idx,
4348 CheckedCloneDrop {
4349 panic_in_clone,
4350 dropped: false,
4351 need_drop: vec![idx + 100],
4352 },
4353 ),
4354 |(k, _)| *k,
4355 );
4356 }
4357 table.clone_from(&scope_table);
4358 });
4359 assert!(result.join().is_err());
4360 });
4361
4362 // Let's check that all iterators work fine and do not return elements
4363 // (especially `RawIterRange`, which does not depend on the number of
4364 // elements in the table, but looks directly at the control bytes)
4365 //
4366 // SAFETY: We know for sure that `RawTable` will outlive
4367 // the returned `RawIter / RawIterRange` iterator.
4368 assert_eq!(table.len(), 0);
4369 assert_eq!(unsafe { table.iter().count() }, 0);
4370 assert_eq!(unsafe { table.iter().iter.count() }, 0);
4371
4372 for idx in 0..table.buckets() {
4373 let idx = idx as u64;
4374 assert!(
4375 table.find(idx, |(k, _)| *k == idx).is_none(),
4376 "Index: {idx}"
4377 );
4378 }
4379
4380 // All allocator clones should already be dropped.
4381 assert_eq!(dropped.load(Ordering::SeqCst), 1);
4382 }
4383}