1use core::{marker::PhantomData, mem, ptr::NonNull};
2
3use crate::raw::util::{unlikely, SizedTypeProperties};
4
5cfg_if! {
6 if #[cfg(all(
15 target_feature = "sse2",
16 any(target_arch = "x86", target_arch = "x86_64"),
17 ))] {
18 mod sse2;
19 use sse2 as imp;
20 } else if #[cfg(all(
21 target_arch = "aarch64",
22 target_feature = "neon",
23 target_endian = "little",
26 ))] {
27 mod neon;
28 use neon as imp;
29 } else {
30 mod generic;
31 use generic as imp;
32 }
33}
34
35mod bitmask;
36pub mod iter;
37pub mod util;
38
39pub(crate) use imp::{BitMaskWord, Group};
40
41use self::{
42 bitmask::{BitMask, BitMaskIter},
43 util::Bucket,
44};
45
46const MIN_HASH_LEN: usize = if mem::size_of::<usize>() < mem::size_of::<u64>() {
48 mem::size_of::<usize>()
49} else {
50 mem::size_of::<u64>()
51};
52
53pub(crate) const EMPTY: u8 = 0b1111_1111;
55pub(crate) const DELETED: u8 = 0b1000_0000;
57
58#[inline]
60#[allow(clippy::cast_possible_truncation)]
61pub(crate) fn h2(hash: u64) -> u8 {
62 let top7 = hash >> (MIN_HASH_LEN * 8 - 7);
67 (top7 & 0x7f) as u8 }
69
70pub struct RawIterInner<T> {
71 len: usize,
72 current_group: BitMaskIter,
73 group_offset: usize,
74 _marker: PhantomData<T>,
75}
76
77unsafe impl<T> Send for RawIterInner<T> {}
78unsafe impl<T> Sync for RawIterInner<T> {}
79
80impl<T> RawIterInner<T> {
81 #[inline]
82 pub(crate) unsafe fn new(init_group: BitMask, len: usize) -> Self {
83 Self {
84 len,
85 current_group: init_group.into_iter(),
86 group_offset: 0,
87 _marker: PhantomData,
88 }
89 }
90
91 #[inline]
92 unsafe fn next_impl(&mut self, group_base: NonNull<u8>, base: Bucket<T>) -> Bucket<T> {
93 loop {
94 if let Some(index) = self.current_group.next() {
95 return base.next_n(index + self.group_offset);
96 }
97
98 self.group_offset += Group::WIDTH;
99 self.current_group = Group::load_aligned(group_base.as_ptr().add(self.group_offset))
100 .match_full()
101 .into_iter();
102 }
103 }
104
105 #[inline]
106 pub(crate) fn next(&mut self, group_base: NonNull<u8>, base: Bucket<T>) -> Option<Bucket<T>> {
107 if unlikely(self.len == 0) {
108 return None;
109 }
110 self.len -= 1;
111 Some(unsafe { self.next_impl(group_base, base) })
112 }
113
114 #[inline]
115 pub(crate) fn size_hint(&self) -> (usize, Option<usize>) {
116 (self.len, Some(self.len))
117 }
118
119 #[inline]
120 pub(crate) fn len(&self) -> usize {
121 self.len
122 }
123}
124
125impl<T> RawIterInner<T> {
126 pub(crate) unsafe fn drop_elements(&mut self, group_base: NonNull<u8>, base: Bucket<T>) {
127 if T::NEEDS_DROP && self.len != 0 {
128 while let Some(item) = self.next(group_base, base.clone()) {
129 item.drop();
130 }
131 }
132 }
133}