Skip to main content

osom_lib_hash_tables/
defaults.rs

1//! Contains the default, recommended choice for the hash table.
2
3use core::hash::Hash;
4
5use osom_lib_alloc::traits::Allocator;
6use osom_lib_primitives::length::Length;
7use osom_lib_reprc::{macros::reprc, traits::ReprC};
8
9use crate::{
10    bytell::{defaults::DefaultBytellConfig, errors::BytellError, hash_table::BytellHashTable},
11    traits::{ImmutableHashTable, MutableHashTable},
12};
13
14/// Represents a general possible error for the default hash table.
15#[reprc]
16#[repr(u8)]
17#[must_use]
18pub enum DefaultHashTableError {
19    /// The underlying allocator returned an error, likely due to out of memory.
20    AllocationError = 0,
21
22    /// The table is too big to be allocated.
23    TableTooBigError = 1,
24}
25
26impl From<BytellError> for DefaultHashTableError {
27    fn from(error: BytellError) -> Self {
28        match error {
29            BytellError::AllocationError => DefaultHashTableError::AllocationError,
30            BytellError::TableTooBigError => DefaultHashTableError::TableTooBigError,
31        }
32    }
33}
34
35/// Represents the default hash table.
36///
37/// # Notes
38///
39/// At the moment it uses [`BytellHashTable`] as the underlying implementation.
40/// This can change in the future though.
41#[derive(PartialEq, Eq, Hash, Clone)]
42#[repr(transparent)]
43#[must_use]
44pub struct DefaultHashTable<TKey, TValue, TAllocator>
45where
46    TKey: Eq + Hash,
47    TAllocator: Allocator,
48{
49    inner: BytellHashTable<TKey, TValue, DefaultBytellConfig<TAllocator>>,
50}
51
52unsafe impl<TKey, TValue, TAllocator> ReprC for DefaultHashTable<TKey, TValue, TAllocator>
53where
54    TKey: Eq + Hash + ReprC,
55    TValue: ReprC,
56    TAllocator: Allocator + ReprC,
57{
58    const CHECK: () = const {
59        let () = <BytellHashTable<TKey, TValue, DefaultBytellConfig<TAllocator>> as ReprC>::CHECK;
60    };
61}
62
63impl<TKey, TValue, TAllocator> DefaultHashTable<TKey, TValue, TAllocator>
64where
65    TKey: Eq + Hash,
66    TAllocator: Allocator,
67{
68    /// Creates a new, empty [`DefaultHashTable`] with the default allocator.
69    #[inline(always)]
70    pub fn new() -> Self {
71        Self::with_allocator(TAllocator::default())
72    }
73
74    /// Creates a new, empty [`DefaultHashTable`] with the specified allocator.
75    #[inline(always)]
76    pub fn with_allocator(allocator: TAllocator) -> Self {
77        Self {
78            inner: BytellHashTable::with_config(DefaultBytellConfig::with_allocator(allocator)),
79        }
80    }
81
82    /// Creates a new [`DefaultHashTable`] with the specified capacity and the default allocator.
83    ///
84    /// This likely will (over)allocate memory.
85    ///
86    /// # Errors
87    ///
88    /// See [`DefaultHashTableError`] for details.
89    #[inline(always)]
90    pub fn with_capacity(capacity: Length) -> Result<Self, DefaultHashTableError> {
91        Self::with_capacity_and_allocator(capacity, TAllocator::default())
92    }
93
94    /// Creates a new [`DefaultHashTable`] with the specified capacity and the specified allocator.
95    ///
96    /// This likely will (over)allocate memory.
97    ///
98    /// # Errors
99    ///
100    /// See [`DefaultHashTableError`] for details.
101    #[inline(always)]
102    pub fn with_capacity_and_allocator(capacity: Length, allocator: TAllocator) -> Result<Self, DefaultHashTableError> {
103        let inner = BytellHashTable::with_capacity_and_config(
104            capacity.as_u32(),
105            DefaultBytellConfig::with_allocator(allocator),
106        )?;
107        Ok(Self { inner })
108    }
109}
110
111impl<TKey, TValue, TAllocator> ImmutableHashTable<TKey, TValue> for DefaultHashTable<TKey, TValue, TAllocator>
112where
113    TKey: Eq + Hash,
114    TAllocator: Allocator,
115{
116    #[inline(always)]
117    fn length(&self) -> Length {
118        self.inner.length()
119    }
120
121    #[inline(always)]
122    fn contains<Q>(&self, key: &Q) -> bool
123    where
124        TKey: core::borrow::Borrow<Q>,
125        Q: Eq + Hash + ?Sized,
126    {
127        self.inner.contains(key)
128    }
129
130    #[inline(always)]
131    fn get<Q>(&self, key: &Q) -> Option<&TValue>
132    where
133        TKey: core::borrow::Borrow<Q>,
134        Q: Eq + Hash + ?Sized,
135    {
136        self.inner.get(key)
137    }
138
139    #[inline(always)]
140    fn get_key_value<Q>(&self, key: &Q) -> Option<(&TKey, &TValue)>
141    where
142        TKey: core::borrow::Borrow<Q>,
143        Q: Eq + Hash + ?Sized,
144    {
145        self.inner.get_key_value(key)
146    }
147
148    #[inline(always)]
149    fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a TKey, &'a TValue)>
150    where
151        TKey: 'a,
152        TValue: 'a,
153        Self: 'a,
154    {
155        self.inner.iter()
156    }
157}
158
159impl<TKey, TValue, TAllocator> MutableHashTable<TKey, TValue> for DefaultHashTable<TKey, TValue, TAllocator>
160where
161    TKey: Eq + Hash,
162    TAllocator: Allocator,
163{
164    #[inline(always)]
165    fn insert(&mut self, key: TKey, value: TValue) -> Option<TValue> {
166        self.inner.insert(key, value)
167    }
168
169    #[inline(always)]
170    fn remove_entry<Q>(&mut self, key: &Q) -> Option<(TKey, TValue)>
171    where
172        TKey: core::borrow::Borrow<Q>,
173        Q: Eq + Hash + ?Sized,
174    {
175        self.inner.remove_entry(key)
176    }
177
178    #[inline(always)]
179    fn insert_or_update_with<FAdd, FUpdate>(&mut self, key: TKey, adder: FAdd, updater: FUpdate) -> &mut TValue
180    where
181        FAdd: FnOnce() -> TValue,
182        FUpdate: FnOnce(&mut TValue),
183    {
184        self.inner.insert_or_update_with(key, adder, updater)
185    }
186
187    #[inline(always)]
188    fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = (&'a TKey, &'a mut TValue)>
189    where
190        TKey: 'a,
191        TValue: 'a,
192        Self: 'a,
193    {
194        self.inner.iter_mut()
195    }
196}
197
198impl<TKey, TValue, TAllocator> Default for DefaultHashTable<TKey, TValue, TAllocator>
199where
200    TKey: Eq + Hash,
201    TAllocator: Allocator,
202{
203    #[inline(always)]
204    fn default() -> Self {
205        Self::new()
206    }
207}
208
209#[cfg(feature = "std")]
210use osom_lib_alloc::std_allocator::StdAllocator;
211
212#[cfg(feature = "std")]
213#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
214/// An alias for [`DefaultHashTable`] with [`StdAllocator`]. Requires `std` feature.
215pub type StdHashTable<TKey, TValue> = DefaultHashTable<TKey, TValue, StdAllocator>;