Skip to main content

wasmtime_environ/collections/
hash_map.rs

1use crate::error::OutOfMemory;
2use core::{
3    borrow::Borrow,
4    fmt,
5    hash::{BuildHasher, Hash},
6    mem,
7};
8
9#[cfg(feature = "std")]
10use std::{collections::hash_map as inner, hash::RandomState as DefaultHashBuilder};
11
12#[cfg(not(feature = "std"))]
13use hashbrown::{DefaultHashBuilder, hash_map as inner};
14use wasmtime_core::alloc::TryClone;
15
16/// A wrapper type around [`hashbrown::hash_map::HashMap`] that only exposes
17/// fallible allocation.
18pub struct HashMap<K, V, S = DefaultHashBuilder> {
19    inner: inner::HashMap<K, V, S>,
20}
21
22impl<K, V, S> TryClone for HashMap<K, V, S>
23where
24    K: Eq + Hash + TryClone,
25    V: TryClone,
26    S: BuildHasher + TryClone,
27{
28    fn try_clone(&self) -> Result<Self, OutOfMemory> {
29        let mut map = Self::with_capacity_and_hasher(self.len(), self.hasher().try_clone()?)?;
30        for (k, v) in self {
31            map.insert(k.try_clone()?, v.try_clone()?)
32                .expect("reserved capacity");
33        }
34        Ok(map)
35    }
36}
37
38impl<K, V, S> Default for HashMap<K, V, S>
39where
40    S: Default,
41{
42    fn default() -> Self {
43        Self {
44            inner: inner::HashMap::default(),
45        }
46    }
47}
48
49impl<K, V, S> PartialEq for HashMap<K, V, S>
50where
51    K: Eq + Hash,
52    V: PartialEq,
53    S: BuildHasher,
54{
55    fn eq(&self, other: &Self) -> bool {
56        self.inner.eq(&other.inner)
57    }
58}
59
60impl<K, V, S> Eq for HashMap<K, V, S>
61where
62    K: Eq + Hash,
63    V: Eq,
64    S: BuildHasher,
65{
66}
67
68impl<K, V, S> fmt::Debug for HashMap<K, V, S>
69where
70    K: fmt::Debug,
71    V: fmt::Debug,
72{
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        fmt::Debug::fmt(&self.inner, f)
75    }
76}
77
78impl<K, V> HashMap<K, V, DefaultHashBuilder> {
79    /// Same as [`hashbrown::hash_map::HashMap::new`].
80    pub fn new() -> Self {
81        Self {
82            inner: inner::HashMap::new(),
83        }
84    }
85}
86
87impl<K, V> HashMap<K, V, DefaultHashBuilder>
88where
89    K: Eq + Hash,
90{
91    /// Same as [`hashbrown::hash_map::HashMap::with_capacity`] but returns an
92    /// error on allocation failure.
93    pub fn with_capacity(capacity: usize) -> Result<Self, OutOfMemory> {
94        let mut map = Self::new();
95        map.reserve(capacity)?;
96        Ok(map)
97    }
98}
99
100impl<K, V, S> HashMap<K, V, S> {
101    /// Same as [`hashbrown::hash_map::HashMap::with_hasher`].
102    pub const fn with_hasher(hasher: S) -> Self {
103        Self {
104            inner: inner::HashMap::with_hasher(hasher),
105        }
106    }
107
108    /// Same as [`hashbrown::hash_map::HashMap::hasher`].
109    pub fn hasher(&self) -> &S {
110        self.inner.hasher()
111    }
112
113    /// Same as [`hashbrown::hash_map::HashMap::capacity`].
114    pub fn capacity(&self) -> usize {
115        self.inner.capacity()
116    }
117
118    /// Same as [`hashbrown::hash_map::HashMap::len`].
119    pub fn len(&self) -> usize {
120        self.inner.len()
121    }
122
123    /// Same as [`hashbrown::hash_map::HashMap::is_empty`].
124    pub fn is_empty(&self) -> bool {
125        self.inner.is_empty()
126    }
127
128    /// Same as [`hashbrown::hash_map::HashMap::drain`].
129    pub fn drain(&mut self) -> inner::Drain<'_, K, V> {
130        self.inner.drain()
131    }
132
133    /// Same as [`hashbrown::hash_map::HashMap::retain`].
134    pub fn retain<F>(&mut self, f: F)
135    where
136        F: FnMut(&K, &mut V) -> bool,
137    {
138        self.inner.retain(f);
139    }
140
141    /// Same as [`hashbrown::hash_map::HashMap::extract_if`].
142    pub fn extract_if<F>(&mut self, f: F) -> inner::ExtractIf<'_, K, V, F>
143    where
144        F: FnMut(&K, &mut V) -> bool,
145    {
146        self.inner.extract_if(f)
147    }
148
149    /// Same as [`hashbrown::hash_map::HashMap::clear`].
150    pub fn clear(&mut self) {
151        self.inner.clear();
152    }
153
154    /// Same as [`hashbrown::hash_map::HashMap::iter`].
155    pub fn iter(&self) -> inner::Iter<'_, K, V> {
156        self.inner.iter()
157    }
158
159    /// Same as [`hashbrown::hash_map::HashMap::iter_mut`].
160    pub fn iter_mut(&mut self) -> inner::IterMut<'_, K, V> {
161        self.inner.iter_mut()
162    }
163}
164
165impl<K, V, S> HashMap<K, V, S>
166where
167    K: Eq + Hash,
168    S: BuildHasher,
169{
170    /// Same as [`hashbrown::hash_map::HashMap::with_capacity_and_hasher`] but
171    /// returns an error on allocation failure.
172    pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Result<Self, OutOfMemory> {
173        let mut map = Self::with_hasher(hasher);
174        map.reserve(capacity)?;
175        Ok(map)
176    }
177
178    /// Same as [`hashbrown::hash_map::HashMap::reserve`] but returns an error
179    /// on allocation failure.
180    pub fn reserve(&mut self, additional: usize) -> Result<(), OutOfMemory> {
181        self.inner.try_reserve(additional).map_err(|_| {
182            let new_len = self.len().saturating_add(additional);
183            OutOfMemory::new(
184                new_len
185                    .saturating_mul(mem::size_of::<K>())
186                    .saturating_add(new_len.saturating_mul(mem::size_of::<V>())),
187            )
188        })
189    }
190
191    /// Same as [`hashbrown::hash_map::HashMap::contains_key`].
192    pub fn contains_key<Q>(&self, key: &Q) -> bool
193    where
194        Q: Hash + Eq + ?Sized,
195        K: Borrow<Q>,
196    {
197        self.inner.contains_key(key)
198    }
199
200    /// Same as [`hashbrown::hash_map::HashMap::get`].
201    pub fn get<Q>(&self, value: &Q) -> Option<&V>
202    where
203        Q: Hash + Eq + ?Sized,
204        K: Borrow<Q>,
205    {
206        self.inner.get(value)
207    }
208
209    /// Same as [`hashbrown::hash_map::HashMap::insert`] but returns an error on
210    /// allocation failure.
211    pub fn insert(&mut self, key: K, value: V) -> Result<Option<V>, OutOfMemory> {
212        self.reserve(1)?;
213        Ok(self.inner.insert(key, value))
214    }
215
216    /// Same as [`hashbrown::hash_map::HashMap::remove`].
217    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
218    where
219        Q: Hash + Eq + ?Sized,
220        K: Borrow<Q>,
221    {
222        self.inner.remove(key)
223    }
224}
225
226impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
227    type Item = (&'a K, &'a V);
228
229    type IntoIter = inner::Iter<'a, K, V>;
230
231    fn into_iter(self) -> Self::IntoIter {
232        self.iter()
233    }
234}
235
236impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
237    type Item = (&'a K, &'a mut V);
238
239    type IntoIter = inner::IterMut<'a, K, V>;
240
241    fn into_iter(self) -> Self::IntoIter {
242        self.iter_mut()
243    }
244}
245
246impl<K, V, S> IntoIterator for HashMap<K, V, S> {
247    type Item = (K, V);
248
249    type IntoIter = inner::IntoIter<K, V>;
250
251    fn into_iter(self) -> Self::IntoIter {
252        self.inner.into_iter()
253    }
254}