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::length::Length;
7
8/// Represents an immutable hash table.
9pub trait ImmutableHashTable<TKey, TValue>
10where
11 TKey: Hash + Eq,
12{
13 /// Returns the number of `(TKey, TValue)` pairs the table
14 /// contains. This typically **does not** correspond to the actual
15 /// size of the table in bytes.
16 fn length(&self) -> Length;
17
18 /// Checks if the table contains the corresponding `key`.
19 ///
20 /// # Notes
21 ///
22 /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
23 fn contains<Q>(&self, key: &Q) -> bool
24 where
25 TKey: Borrow<Q>,
26 Q: Eq + Hash + ?Sized;
27
28 /// Checks if the table contains the corresponding `key`, and if so then returns
29 /// the reference to the `TValue`, or `None` otherwise.
30 ///
31 /// # Notes
32 ///
33 /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
34 fn get<Q>(&self, key: &Q) -> Option<&TValue>
35 where
36 TKey: Borrow<Q>,
37 Q: Eq + Hash + ?Sized;
38
39 /// Checks if the table contains the corresponding `key`, and if so then returns
40 /// the `(&TKey, &TValue)` pair or `None` otherwise.
41 ///
42 /// # Notes
43 ///
44 /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
45 fn get_key_value<Q>(&self, key: &Q) -> Option<(&TKey, &TValue)>
46 where
47 TKey: Borrow<Q>,
48 Q: Eq + Hash + ?Sized;
49
50 /// Checks if the table is empty. This does not mean that it doesn't take space
51 /// in memory. Equivalent to `self.length() == 0` check.
52 fn is_empty(&self) -> bool {
53 self.length() == Length::ZERO
54 }
55
56 /// Returns an iterator over the key-value pairs in the table.
57 ///
58 /// # Notes
59 ///
60 /// The iterator yields `(&TKey, &TValue)` tuples representing each key-value pair
61 /// in the hash table.
62 fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a TKey, &'a TValue)>
63 where
64 TKey: 'a,
65 TValue: 'a,
66 Self: 'a;
67}
68
69/// An extension of [`ImmutableHashTable`] that allows the actual modifications
70/// to the table.
71pub trait MutableHashTable<TKey, TValue>: ImmutableHashTable<TKey, TValue>
72where
73 TKey: Hash + Eq,
74{
75 /// Inserts given `(TKey, TValue)` pair into the table.
76 ///
77 /// Return `None` if the `key` didn't already exist in the table.
78 ///
79 /// Otherwise returns the old `TValue`.
80 fn insert(&mut self, key: TKey, value: TValue) -> Option<TValue>;
81
82 /// Removes entire entry from the table. Returns `(TKey, TValue)` pair
83 /// for the matching `key` or `None` if there is no match.
84 ///
85 /// # Notes
86 ///
87 /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
88 fn remove_entry<Q>(&mut self, key: &Q) -> Option<(TKey, TValue)>
89 where
90 TKey: Borrow<Q>,
91 Q: Eq + Hash + ?Sized;
92
93 /// Searches the table for a given `key`. If the table contains it, then
94 /// it runs `updater` on the corresponding `TValue`. Otherwise runs `adder`
95 /// to add a new `TValue` to the table. Returns the mutable reference to the
96 /// final `TValue`.
97 ///
98 /// # Notes
99 ///
100 /// The implementation has to guarantee that one of: `adder` or `updater` will be called
101 /// during its execution, but not both.
102 fn insert_or_update_with<FAdd, FUpdate>(&mut self, key: TKey, adder: FAdd, updater: FUpdate) -> &mut TValue
103 where
104 FAdd: FnOnce() -> TValue,
105 FUpdate: FnOnce(&mut TValue);
106
107 /// Removes entire entry from the table. Similar to [`MutableHashTable::remove_entry`],
108 /// but returns `TValue` only for the matching `key` or `None` if there is no match.
109 ///
110 /// # Notes
111 ///
112 /// The borrowed `Q` type's `Hash` and `Eq` must match those for `TKey`.
113 #[inline(always)]
114 fn remove<Q>(&mut self, key: &Q) -> Option<TValue>
115 where
116 TKey: Borrow<Q>,
117 Q: Eq + Hash + ?Sized,
118 {
119 if let Some((_, value)) = self.remove_entry(key) {
120 Some(value)
121 } else {
122 None
123 }
124 }
125
126 /// Retrieves an existing `TValue`, or inserts a default one.
127 ///
128 /// Internally equivalent to `self.insert_or_update_with(key, TValue::default, |_| {})`.
129 #[inline(always)]
130 fn get_or_insert_default(&mut self, key: TKey) -> &mut TValue
131 where
132 TValue: Default,
133 {
134 self.insert_or_update_with(key, TValue::default, |_| {})
135 }
136
137 /// Retrieves an existing `TValue`, or inserts the passed one.
138 ///
139 /// Internally equivalent to `self.insert_or_update_with(key, || value, || {})`.
140 #[inline(always)]
141 fn get_or_insert(&mut self, key: TKey, value: TValue) -> &mut TValue {
142 self.insert_or_update_with(key, || value, |_| {})
143 }
144
145 /// Returns a mutable iterator over the key-value pairs in the table.
146 ///
147 /// # Notes
148 ///
149 /// The iterator yields `(&TKey, &mut TValue)` tuples representing each key-value pair
150 /// in the hash table.
151 fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = (&'a TKey, &'a mut TValue)>
152 where
153 TKey: 'a,
154 TValue: 'a,
155 Self: 'a;
156}