1use core::fmt::Debug;
4use core::hash::Hash;
5
6use osom_lib_alloc::traits::Allocator;
7use osom_lib_primitives::{kvp::KVP, length::Length};
8use osom_lib_reprc::traits::ReprC;
9use osom_lib_try_clone::TryClone;
10
11use crate::{
12 abseil::{defaults::DefaultAbseilConfig, hash_table::AbseilHashTable},
13 errors::{HashTableError, TryCloneHashTableError},
14 traits::{ImmutableHashTable, MutableHashTable},
15};
16
17type InnerMap<TKey, TValue, TAllocator> = AbseilHashTable<TKey, TValue, DefaultAbseilConfig<TAllocator>>;
18
19#[repr(transparent)]
26#[must_use]
27pub struct DefaultHashTable<TKey, TValue, TAllocator>
28where
29 TKey: Eq + Hash,
30 TAllocator: Allocator,
31{
32 inner: InnerMap<TKey, TValue, TAllocator>,
33}
34
35impl<TKey, TValue, TAllocator> Debug for DefaultHashTable<TKey, TValue, TAllocator>
36where
37 TKey: Eq + Hash,
38 TAllocator: Allocator,
39{
40 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41 write!(f, "DefaultHashTable[{}]", stringify!(AbseilHashTable))
42 }
43}
44
45unsafe impl<TKey, TValue, TAllocator> Send for DefaultHashTable<TKey, TValue, TAllocator>
46where
47 TKey: Send + Eq + Hash,
48 TValue: Send,
49 TAllocator: Allocator + Send,
50 InnerMap<TKey, TValue, TAllocator>: Sync,
51{
52}
53
54unsafe impl<TKey, TValue, TAllocator> Sync for DefaultHashTable<TKey, TValue, TAllocator>
55where
56 TKey: Sync + Eq + Hash,
57 TValue: Sync,
58 TAllocator: Allocator + Sync,
59 InnerMap<TKey, TValue, TAllocator>: Sync,
60{
61}
62
63unsafe impl<TKey, TValue, TAllocator> ReprC for DefaultHashTable<TKey, TValue, TAllocator>
64where
65 TKey: Eq + Hash + ReprC,
66 TValue: ReprC,
67 TAllocator: Allocator + ReprC,
68 InnerMap<TKey, TValue, TAllocator>: ReprC,
69{
70 const CHECK: () = const {
71 osom_lib_reprc::hidden::is_reprc::<TKey>();
72 osom_lib_reprc::hidden::is_reprc::<TValue>();
73 osom_lib_reprc::hidden::is_reprc::<TAllocator>();
74 osom_lib_reprc::hidden::is_reprc::<InnerMap<TKey, TValue, TAllocator>>();
75 };
76}
77
78impl<TKey, TValue, TAllocator> DefaultHashTable<TKey, TValue, TAllocator>
79where
80 TKey: Eq + Hash,
81 TAllocator: Allocator,
82{
83 #[inline(always)]
85 pub fn new() -> Self
86 where
87 TAllocator: Default,
88 {
89 Self::with_allocator(TAllocator::default())
90 }
91
92 #[inline(always)]
94 pub fn with_allocator(allocator: TAllocator) -> Self {
95 Self {
96 inner: AbseilHashTable::with_config(DefaultAbseilConfig::with_allocator(allocator)),
97 }
98 }
99
100 #[inline(always)]
108 pub fn with_capacity(capacity: Length) -> Result<Self, HashTableError>
109 where
110 TAllocator: Default,
111 {
112 Self::with_capacity_and_allocator(capacity, TAllocator::default())
113 }
114
115 #[inline(always)]
123 pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, HashTableError> {
124 let inner = AbseilHashTable::with_capacity_and_config(capacity, DefaultAbseilConfig::with_allocator(allocator))?;
125 Ok(Self { inner })
126 }
127}
128
129impl<TKey, TValue, TAllocator> ImmutableHashTable<TKey, TValue> for DefaultHashTable<TKey, TValue, TAllocator>
130where
131 TKey: Eq + Hash,
132 TAllocator: Allocator,
133 InnerMap<TKey, TValue, TAllocator>: ImmutableHashTable<TKey, TValue>,
134{
135 #[inline(always)]
136 fn length(&self) -> Length {
137 self.inner.length()
138 }
139
140 #[inline(always)]
141 fn contains<Q>(&self, key: &Q) -> bool
142 where
143 TKey: core::borrow::Borrow<Q>,
144 Q: Eq + Hash + ?Sized,
145 {
146 self.inner.contains(key)
147 }
148
149 #[inline(always)]
150 fn get<Q>(&self, key: &Q) -> Option<&TValue>
151 where
152 TKey: core::borrow::Borrow<Q>,
153 Q: Eq + Hash + ?Sized,
154 {
155 self.inner.get(key)
156 }
157
158 #[inline(always)]
159 fn get_key_value<Q>(&self, key: &Q) -> Option<KVP<&TKey, &TValue>>
160 where
161 TKey: core::borrow::Borrow<Q>,
162 Q: Eq + Hash + ?Sized,
163 {
164 self.inner.get_key_value(key)
165 }
166
167 #[inline(always)]
168 fn iter<'a>(&'a self) -> impl Iterator<Item = KVP<&'a TKey, &'a TValue>>
169 where
170 TKey: 'a,
171 TValue: 'a,
172 Self: 'a,
173 {
174 self.inner.iter()
175 }
176}
177
178impl<TKey, TValue, TAllocator> MutableHashTable<TKey, TValue> for DefaultHashTable<TKey, TValue, TAllocator>
179where
180 TKey: Eq + Hash,
181 TAllocator: Allocator,
182 InnerMap<TKey, TValue, TAllocator>: MutableHashTable<TKey, TValue>,
183{
184 #[inline(always)]
185 fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut TValue>
186 where
187 TKey: core::borrow::Borrow<Q>,
188 Q: Eq + Hash + ?Sized,
189 {
190 self.inner.get_mut(key)
191 }
192
193 #[inline(always)]
194 fn get_key_value_mut<Q>(&mut self, key: &Q) -> Option<KVP<&TKey, &mut TValue>>
195 where
196 TKey: core::borrow::Borrow<Q>,
197 Q: Eq + Hash + ?Sized,
198 {
199 self.inner.get_key_value_mut(key)
200 }
201
202 #[inline(always)]
203 fn remove_entry<Q>(&mut self, key: &Q) -> Option<KVP<TKey, TValue>>
204 where
205 TKey: core::borrow::Borrow<Q>,
206 Q: Eq + Hash + ?Sized,
207 {
208 self.inner.remove_entry(key)
209 }
210
211 #[inline(always)]
212 fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = KVP<&'a TKey, &'a mut TValue>>
213 where
214 TKey: 'a,
215 TValue: 'a,
216 Self: 'a,
217 {
218 self.inner.iter_mut()
219 }
220
221 #[inline(always)]
222 fn try_insert_or_update_with<FAdd, FUpdate>(
223 &mut self,
224 key: TKey,
225 adder: FAdd,
226 updater: FUpdate,
227 ) -> Result<&mut TValue, crate::errors::HashTableError>
228 where
229 FAdd: FnOnce() -> TValue,
230 FUpdate: FnOnce(&mut TValue),
231 {
232 self.inner.try_insert_or_update_with(key, adder, updater)
233 }
234}
235
236impl<TKey, TValue, TAllocator> Default for DefaultHashTable<TKey, TValue, TAllocator>
237where
238 TKey: Eq + Hash,
239 TAllocator: Allocator + Default,
240 InnerMap<TKey, TValue, TAllocator>: Default,
241{
242 #[inline(always)]
243 fn default() -> Self {
244 Self::new()
245 }
246}
247
248impl<TKey, TValue, TAllocator> TryClone for DefaultHashTable<TKey, TValue, TAllocator>
249where
250 TKey: Eq + Hash,
251 TAllocator: Allocator,
252 InnerMap<TKey, TValue, TAllocator>: TryClone<Error = TryCloneHashTableError>,
253{
254 type Error = TryCloneHashTableError;
255
256 fn try_clone(&self) -> Result<Self, Self::Error> {
257 let inner = self.inner.try_clone()?;
258 Ok(Self { inner })
259 }
260}
261
262impl<TKey, TValue, TAllocator> Clone for DefaultHashTable<TKey, TValue, TAllocator>
263where
264 TKey: Eq + Hash,
265 TAllocator: Allocator,
266 InnerMap<TKey, TValue, TAllocator>: TryClone<Error = TryCloneHashTableError>,
267{
268 fn clone(&self) -> Self {
269 self.try_clone().expect("[DefaultHashTable::try_clone] failure")
270 }
271}
272
273impl<TKey, TValue, TAllocator> PartialEq for DefaultHashTable<TKey, TValue, TAllocator>
274where
275 TKey: Eq + Hash,
276 TAllocator: Allocator,
277 InnerMap<TKey, TValue, TAllocator>: PartialEq,
278{
279 fn eq(&self, other: &Self) -> bool {
280 self.inner == other.inner
281 }
282}
283
284impl<TKey, TValue, TAllocator> Eq for DefaultHashTable<TKey, TValue, TAllocator>
285where
286 TKey: Eq + Hash,
287 TAllocator: Allocator,
288 InnerMap<TKey, TValue, TAllocator>: Eq,
289{
290}
291
292impl<TKey, TValue, TAllocator> Hash for DefaultHashTable<TKey, TValue, TAllocator>
293where
294 TKey: Eq + Hash,
295 TAllocator: Allocator,
296 InnerMap<TKey, TValue, TAllocator>: Hash,
297{
298 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
299 self.inner.hash(state);
300 }
301}
302
303#[cfg(feature = "std")]
304use osom_lib_alloc::std_allocator::StdAllocator;
305
306#[cfg(feature = "std")]
307#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
308pub type StdDefaultHashTable<TKey, TValue> = DefaultHashTable<TKey, TValue, StdAllocator>;