osom_lib_hash_tables/bytell/hash_table/
bytell_immutable.rs1use 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}