Skip to main content

osom_lib_hash_tables/
traits.rs

1//! Defines hash table traits.
2
3use core::borrow::Borrow;
4use core::hash::Hash;
5
6use osom_lib_primitives::kvp::KVP;
7use osom_lib_primitives::length::Length;
8
9use crate::errors::HashTableError;
10
11/// Represents an immutable hash table.
12pub trait ImmutableHashTable<TKey, TValue>: Sized
13where
14    TKey: Hash + Eq,
15{
16    /// Returns the number of `(TKey, TValue)` pairs the table
17    /// contains. This typically **does not** correspond to the actual
18    /// size of the table in bytes.
19    fn length(&self) -> Length;
20
21    /// Checks if the table contains the corresponding `key`.
22    ///
23    /// # Notes
24    ///
25    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
26    fn contains<Q>(&self, key: &Q) -> bool
27    where
28        TKey: Borrow<Q>,
29        Q: Eq + Hash + ?Sized;
30
31    /// Checks if the table contains the corresponding `key`, and if so then returns
32    /// the reference to the `TValue`, or `None` otherwise.
33    ///
34    /// # Notes
35    ///
36    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
37    fn get<Q>(&self, key: &Q) -> Option<&TValue>
38    where
39        TKey: Borrow<Q>,
40        Q: Eq + Hash + ?Sized;
41
42    /// Checks if the table contains the corresponding `key`, and if so then returns
43    /// the `(&TKey, &TValue)` pair or `None` otherwise.
44    ///
45    /// # Notes
46    ///
47    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
48    fn get_key_value<Q>(&self, key: &Q) -> Option<KVP<&TKey, &TValue>>
49    where
50        TKey: Borrow<Q>,
51        Q: Eq + Hash + ?Sized;
52
53    /// Checks if the table is empty. This does not mean that it doesn't take space
54    /// in memory. Equivalent to `self.length() == 0` check.
55    fn is_empty(&self) -> bool {
56        self.length() == Length::ZERO
57    }
58
59    /// Returns an iterator over the key-value pairs in the table.
60    ///
61    /// # Notes
62    ///
63    /// The iterator yields `(&TKey, &TValue)` tuples representing each key-value pair
64    /// in the hash table.
65    fn iter<'a>(&'a self) -> impl Iterator<Item = KVP<&'a TKey, &'a TValue>> + 'a
66    where
67        TKey: 'a,
68        TValue: 'a,
69        Self: 'a;
70}
71
72/// An extension of [`ImmutableHashTable`] that allows the actual modifications
73/// to the table.
74pub trait MutableHashTable<TKey, TValue>: ImmutableHashTable<TKey, TValue>
75where
76    TKey: Hash + Eq,
77{
78    /// Checks if the table contains the corresponding `key`, and if so then returns
79    /// a mutable reference to the `TValue`, or `None` otherwise.
80    ///
81    /// # Notes
82    ///
83    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
84    fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut TValue>
85    where
86        TKey: Borrow<Q>,
87        Q: Eq + Hash + ?Sized;
88
89    /// Checks if the table contains the corresponding `key`, and if so then returns
90    /// a mutable reference to the `TValue`, or `None` otherwise.
91    ///
92    /// # Notes
93    ///
94    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
95    fn get_key_value_mut<Q>(&mut self, key: &Q) -> Option<KVP<&TKey, &mut TValue>>
96    where
97        TKey: Borrow<Q>,
98        Q: Eq + Hash + ?Sized;
99
100    /// Inserts given `(TKey, TValue)` pair into the table.
101    ///
102    /// Return `None` if the `key` didn't already exist in the table.
103    ///
104    /// Otherwise returns the old `TValue`.
105    ///
106    /// # Panics
107    ///
108    /// Whenever the corresponding [`MutableHashTable::try_insert`] would fail.
109    fn insert(&mut self, key: TKey, value: TValue) -> Option<TValue> {
110        self.try_insert(key, value)
111            .expect("[MutableHashTable::try_insert] failure")
112    }
113
114    /// Tries to insert given `(TKey, TValue)` pair into the table.
115    ///
116    /// Return `None` if the `key` didn't already exist in the table.
117    ///
118    /// Otherwise returns the old `TValue`.
119    ///
120    /// # Errors
121    ///
122    /// For details see [`HashTableError`].
123    fn try_insert(&mut self, key: TKey, value: TValue) -> Result<Option<TValue>, HashTableError> {
124        let value_ptr = &raw const value;
125        let adder = || unsafe { value_ptr.read() };
126
127        let mut result: Option<TValue> = None;
128        let updater = |current: &mut TValue| {
129            let value = unsafe { value_ptr.read() };
130            let old_value = core::mem::replace(current, value);
131            result = Some(old_value);
132        };
133
134        let _ = self.try_insert_or_update_with(key, adder, updater)?;
135        core::mem::forget(value);
136        Ok(result)
137    }
138
139    /// Removes entire entry from the table. Returns `(TKey, TValue)` pair
140    /// for the matching `key` or `None` if there is no match.
141    ///
142    /// # Notes
143    ///
144    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
145    fn remove_entry<Q>(&mut self, key: &Q) -> Option<KVP<TKey, TValue>>
146    where
147        TKey: Borrow<Q>,
148        Q: Eq + Hash + ?Sized;
149
150    /// Searches the table for a given `key`. If the table contains it, then
151    /// it runs `updater` on the corresponding `TValue`. Otherwise runs `adder`
152    /// to add a new `TValue` to the table. Returns the mutable reference to the
153    /// final `TValue`.
154    ///
155    /// # Notes
156    ///
157    /// The implementation has to guarantee that one of: `adder` or `updater` will be called
158    /// during its execution, but not both.
159    ///
160    /// # Panics
161    ///
162    /// Whenever the corresponding [`MutableHashTable::try_insert_or_update_with`] would fail.
163    fn insert_or_update_with<FAdd, FUpdate>(&mut self, key: TKey, adder: FAdd, updater: FUpdate) -> &mut TValue
164    where
165        FAdd: FnOnce() -> TValue,
166        FUpdate: FnOnce(&mut TValue),
167    {
168        self.try_insert_or_update_with(key, adder, updater)
169            .expect("[MutableHashTable::try_insert_or_update_with] failure")
170    }
171
172    /// Searches the table for a given `key`. If the table contains it, then
173    /// it runs `updater` on the corresponding `TValue`. Otherwise runs `adder`
174    /// to add a new `TValue` to the table. Returns the mutable reference to the
175    /// final `TValue`.
176    ///
177    /// # Notes
178    ///
179    /// The implementation has to guarantee that one of: `adder` or `updater` will be called
180    /// during its execution, but not both.
181    ///
182    /// # Errors
183    ///
184    /// For details see [`HashTableError`].
185    fn try_insert_or_update_with<FAdd, FUpdate>(
186        &mut self,
187        key: TKey,
188        adder: FAdd,
189        updater: FUpdate,
190    ) -> Result<&mut TValue, HashTableError>
191    where
192        FAdd: FnOnce() -> TValue,
193        FUpdate: FnOnce(&mut TValue);
194
195    /// Removes entire entry from the table. Similar to [`MutableHashTable::remove_entry`],
196    /// but returns `TValue` only for the matching `key` or `None` if there is no match.
197    ///
198    /// # Notes
199    ///
200    /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
201    #[inline(always)]
202    fn remove<Q>(&mut self, key: &Q) -> Option<TValue>
203    where
204        TKey: Borrow<Q>,
205        Q: Eq + Hash + ?Sized,
206    {
207        if let Some(kvp) = self.remove_entry(key) {
208            let (_, value) = kvp.unpack();
209            Some(value)
210        } else {
211            None
212        }
213    }
214
215    /// Retrieves an existing `TValue`, or inserts a default one.
216    ///
217    /// Internally equivalent to `self.try_get_or_insert_default(key)`.
218    ///
219    /// # Panics
220    ///
221    /// Whenever the corresponding [`MutableHashTable::try_get_or_insert_default`] would fail.
222    #[inline(always)]
223    fn get_or_insert_default(&mut self, key: TKey) -> &mut TValue
224    where
225        TValue: Default,
226    {
227        self.try_get_or_insert_default(key)
228            .expect("[MutableHashTable::try_get_or_insert_default] failure")
229    }
230
231    /// Retrieves an existing `TValue`, or inserts a default one.
232    ///
233    /// Internally equivalent to `self.try_insert_or_update_with(key, TValue::default, |_| {})`.
234    ///
235    /// # Errors
236    ///
237    /// For details see [`HashTableError`].
238    #[inline(always)]
239    fn try_get_or_insert_default(&mut self, key: TKey) -> Result<&mut TValue, HashTableError>
240    where
241        TValue: Default,
242    {
243        self.try_insert_or_update_with(key, TValue::default, |_| {})
244    }
245
246    /// Retrieves an existing `TValue`, or inserts the passed one.
247    ///
248    /// Internally equivalent to `self.try_get_or_insert(key, value)`.
249    ///
250    /// # Panics
251    ///
252    /// Whenever the corresponding [`MutableHashTable::try_get_or_insert`] would fail.
253    #[inline(always)]
254    fn get_or_insert(&mut self, key: TKey, value: TValue) -> &mut TValue {
255        self.try_get_or_insert(key, value)
256            .expect("[MutableHashTable::try_get_or_insert] failure")
257    }
258
259    /// Retrieves an existing `TValue`, or inserts the passed one.
260    ///
261    /// Internally equivalent to `self.try_insert_or_update_with(key, || value, || {})`.
262    ///
263    /// # Errors
264    ///
265    /// For details see [`HashTableError`].
266    #[inline(always)]
267    fn try_get_or_insert(&mut self, key: TKey, value: TValue) -> Result<&mut TValue, HashTableError> {
268        self.try_insert_or_update_with(key, || value, |_| {})
269    }
270
271    /// Returns a mutable iterator over the key-value pairs in the table.
272    ///
273    /// # Notes
274    ///
275    /// The iterator yields `(&TKey, &mut TValue)` tuples representing each key-value pair
276    /// in the hash table.
277    fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = KVP<&'a TKey, &'a mut TValue>> + 'a
278    where
279        TKey: 'a,
280        TValue: 'a,
281        Self: 'a;
282}