frozen_hashbrown/
iter.rs

1use crate::FrozenHashMap;
2
3/// An iterator that yields raw pointers to buckets
4pub struct RawBucketIter<'a> {
5    base: *const u8,
6    cur: *const u8,
7    end: *const u8,
8    bucket_size: usize,
9    items: usize,
10    _memory: &'a [u8],
11}
12
13impl<S> FrozenHashMap<S> {
14    pub fn raw_iter(&self) -> Option<RawBucketIter<'_>> {
15        if let Some((offset, layout)) = self.hashmap.table.table.reallocation(&self.table_layout) {
16            if self.memory.is_empty() {
17                return None;
18            }
19            if layout.size() != self.memory.len() {
20                return None;
21            }
22            let base = unsafe { self.memory.as_ptr().add(offset) };
23            Some(RawBucketIter {
24                base,
25                cur: base,
26                end: unsafe { self.memory.as_ptr().add(self.memory.len()) },
27                bucket_size: self.table_layout.size,
28                items: self.hashmap.table.table.items,
29                _memory: &self.memory,
30            })
31        } else {
32            None
33        }
34    }
35}
36
37impl<'a> Iterator for RawBucketIter<'a> {
38    /// memory address of the bucket
39    type Item = *const u8;
40
41    fn next(&mut self) -> Option<Self::Item> {
42        if self.items == 0 {
43            return None;
44        }
45        while self.cur < self.end {
46            // most significant bit = 0 means bucket is full
47            let full = (unsafe { *self.cur } & 0x80) == 0;
48            self.cur = unsafe { self.cur.add(1) };
49            if full {
50                let offset = unsafe { self.cur.offset_from(self.base) } * self.bucket_size as isize;
51                assert!(offset >= 0);
52                self.items -= 1;
53                return Some(unsafe { self.base.sub(offset as usize) });
54            }
55        }
56        return None;
57    }
58
59    #[inline]
60    fn size_hint(&self) -> (usize, Option<usize>) {
61        (self.items, Some(self.items))
62    }
63}