Skip to main content

osom_lib_hash_tables/bytell/hash_table/
bytell_immutable.rs

1use core::{borrow::Borrow, hash::Hash, marker::PhantomData};
2
3use osom_lib_primitives::{kvp::KVP, length::Length, power_of_two::PowerOfTwo32};
4
5use crate::{
6    bytell::{
7        configuration::BytellConfig,
8        hash_table::{BytellHashTable, block_layout::BlockLayoutHolder, entry::Entry},
9    },
10    helpers::ptr_to_ref,
11    traits::ImmutableHashTable,
12};
13
14struct BytellImmutableIter<'a, TKey: 'a, TValue: 'a, TConfig> {
15    data: *mut u8,
16    last_element_index: u32,
17    blocks_count: PowerOfTwo32,
18    _marker: PhantomData<(&'a TKey, &'a TValue, TConfig)>,
19}
20
21impl<'a, TKey: 'a, TValue: 'a, TConfig> BytellImmutableIter<'a, TKey, TValue, TConfig>
22where
23    TKey: Eq + Hash,
24    TConfig: BytellConfig,
25{
26    #[inline(always)]
27    pub const fn from_hash_table(
28        table: &'a BytellHashTable<TKey, TValue, TConfig>,
29    ) -> BytellImmutableIter<'a, TKey, TValue, TConfig> {
30        Self {
31            data: table.data,
32            last_element_index: 0,
33            blocks_count: table.blocks_count,
34            _marker: PhantomData,
35        }
36    }
37}
38
39impl<'a, TKey: 'a, TValue: 'a, TConfig> Iterator for BytellImmutableIter<'a, TKey, TValue, TConfig> {
40    type Item = KVP<&'a TKey, &'a TValue>;
41
42    fn next(&mut self) -> Option<Self::Item> {
43        let elements_count = BlockLayoutHolder::<TKey, TValue>::LAYOUT.block_capacity().value();
44        let capacity = self.blocks_count.value() * elements_count;
45        let mut el_idx = self.last_element_index;
46
47        loop {
48            unsafe {
49                if el_idx == capacity {
50                    self.last_element_index = el_idx;
51                    return None;
52                }
53
54                let entry = Entry::<TKey, TValue>::new(self.data, self.blocks_count, el_idx as usize);
55                el_idx += 1;
56
57                if !(*entry.control_byte()).contains_data() {
58                    continue;
59                }
60
61                let kvp = ptr_to_ref!(entry.kvp());
62                self.last_element_index = el_idx;
63                return Some(kvp.as_ref_kvp());
64            }
65        }
66    }
67}
68
69impl<TKey, TValue, TConfig> ImmutableHashTable<TKey, TValue> for BytellHashTable<TKey, TValue, TConfig>
70where
71    TKey: Eq + Hash,
72    TConfig: BytellConfig,
73{
74    #[inline(always)]
75    fn length(&self) -> Length {
76        self.length()
77    }
78
79    #[inline(always)]
80    fn contains<Q>(&self, key: &Q) -> bool
81    where
82        TKey: Borrow<Q>,
83        Q: Eq + Hash + ?Sized,
84    {
85        self.get_key_value(key).is_some()
86    }
87
88    #[inline(always)]
89    fn get<Q>(&self, key: &Q) -> Option<&TValue>
90    where
91        TKey: Borrow<Q>,
92        Q: Eq + Hash + ?Sized,
93    {
94        match self.get_key_value(key) {
95            Some(kvp) => Some(kvp.value),
96            None => None,
97        }
98    }
99
100    fn get_key_value<Q>(&self, key: &Q) -> Option<KVP<&TKey, &TValue>>
101    where
102        TKey: Borrow<Q>,
103        Q: Eq + Hash + ?Sized,
104    {
105        unsafe {
106            let result = self.get_key_value_raw(key)?;
107            Some(result.as_ref_unchecked().as_ref_kvp())
108        }
109    }
110
111    #[inline(always)]
112    fn iter<'a>(&'a self) -> impl Iterator<Item = KVP<&'a TKey, &'a TValue>>
113    where
114        TKey: 'a,
115        TValue: 'a,
116        Self: 'a,
117    {
118        BytellImmutableIter::from_hash_table(self)
119    }
120}