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::{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 = (&'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.key, &kvp.value));
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.elements_count
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).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(pair) => Some(pair.1),
96            None => None,
97        }
98    }
99
100    #[inline(never)]
101    fn get_key_value<Q>(&self, key: &Q) -> Option<(&TKey, &TValue)>
102    where
103        TKey: Borrow<Q>,
104        Q: Eq + Hash + ?Sized,
105    {
106        if self.blocks_count.value() == 0 {
107            return None;
108        }
109
110        unsafe {
111            let mut entry = self.get_entry_by_key(key);
112            let control_byte = ptr_to_ref!(entry.control_byte());
113            if !control_byte.is_direct_hit() {
114                return None;
115            }
116
117            loop {
118                let kvp = ptr_to_ref!(entry.kvp());
119                if kvp.key.borrow() == key {
120                    return Some((&kvp.key, &kvp.value));
121                }
122                if let Some(next) = entry.next_link() {
123                    entry = next;
124                } else {
125                    return None;
126                }
127            }
128        }
129    }
130
131    #[inline(always)]
132    fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a TKey, &'a TValue)>
133    where
134        TKey: 'a,
135        TValue: 'a,
136        Self: 'a,
137    {
138        BytellImmutableIter::from_hash_table(self)
139    }
140}