1 use crate::error::OutOfMemory;
2 use core::{
3     borrow::Borrow,
4     fmt,
5     hash::{BuildHasher, Hash},
6     mem,
7 };
8 
9 #[cfg(feature = "std")]
10 use std::{collections::hash_map as inner, hash::RandomState as DefaultHashBuilder};
11 
12 #[cfg(not(feature = "std"))]
13 use hashbrown::{DefaultHashBuilder, hash_map as inner};
14 use wasmtime_core::alloc::TryClone;
15 
16 /// A wrapper type around [`hashbrown::hash_map::HashMap`] that only exposes
17 /// fallible allocation.
18 pub struct TryHashMap<K, V, S = DefaultHashBuilder> {
19     inner: inner::HashMap<K, V, S>,
20 }
21 
22 impl<K, V, S> TryClone for TryHashMap<K, V, S>
23 where
24     K: Eq + Hash + TryClone,
25     V: TryClone,
26     S: BuildHasher + TryClone,
27 {
try_clone(&self) -> Result<Self, OutOfMemory>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 
38 impl<K, V, S> Default for TryHashMap<K, V, S>
39 where
40     S: Default,
41 {
default() -> Self42     fn default() -> Self {
43         Self {
44             inner: inner::HashMap::default(),
45         }
46     }
47 }
48 
49 impl<K, V, S> PartialEq for TryHashMap<K, V, S>
50 where
51     K: Eq + Hash,
52     V: PartialEq,
53     S: BuildHasher,
54 {
eq(&self, other: &Self) -> bool55     fn eq(&self, other: &Self) -> bool {
56         self.inner.eq(&other.inner)
57     }
58 }
59 
60 impl<K, V, S> Eq for TryHashMap<K, V, S>
61 where
62     K: Eq + Hash,
63     V: Eq,
64     S: BuildHasher,
65 {
66 }
67 
68 impl<K, V, S> fmt::Debug for TryHashMap<K, V, S>
69 where
70     K: fmt::Debug,
71     V: fmt::Debug,
72 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result73     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74         fmt::Debug::fmt(&self.inner, f)
75     }
76 }
77 
78 impl<K, V> TryHashMap<K, V, DefaultHashBuilder> {
79     /// Same as [`hashbrown::hash_map::HashMap::new`].
new() -> Self80     pub fn new() -> Self {
81         Self {
82             inner: inner::HashMap::new(),
83         }
84     }
85 }
86 
87 impl<K, V> TryHashMap<K, V, DefaultHashBuilder>
88 where
89     K: Eq + Hash,
90 {
91     /// Same as [`hashbrown::hash_map::HashMap::with_capacity`] but returns an
92     /// error on allocation failure.
with_capacity(capacity: usize) -> Result<Self, OutOfMemory>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 
100 impl<K, V, S> TryHashMap<K, V, S> {
101     /// Same as [`hashbrown::hash_map::HashMap::with_hasher`].
with_hasher(hasher: S) -> Self102     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`].
hasher(&self) -> &S109     pub fn hasher(&self) -> &S {
110         self.inner.hasher()
111     }
112 
113     /// Same as [`hashbrown::hash_map::HashMap::capacity`].
capacity(&self) -> usize114     pub fn capacity(&self) -> usize {
115         self.inner.capacity()
116     }
117 
118     /// Same as [`hashbrown::hash_map::HashMap::len`].
len(&self) -> usize119     pub fn len(&self) -> usize {
120         self.inner.len()
121     }
122 
123     /// Same as [`hashbrown::hash_map::HashMap::is_empty`].
is_empty(&self) -> bool124     pub fn is_empty(&self) -> bool {
125         self.inner.is_empty()
126     }
127 
128     /// Same as [`hashbrown::hash_map::HashMap::drain`].
drain(&mut self) -> inner::Drain<'_, K, V>129     pub fn drain(&mut self) -> inner::Drain<'_, K, V> {
130         self.inner.drain()
131     }
132 
133     /// Same as [`hashbrown::hash_map::HashMap::retain`].
retain<F>(&mut self, f: F) where F: FnMut(&K, &mut V) -> bool,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`].
extract_if<F>(&mut self, f: F) -> inner::ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool,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`].
clear(&mut self)150     pub fn clear(&mut self) {
151         self.inner.clear();
152     }
153 
154     /// Same as [`hashbrown::hash_map::HashMap::iter`].
iter(&self) -> inner::Iter<'_, K, V>155     pub fn iter(&self) -> inner::Iter<'_, K, V> {
156         self.inner.iter()
157     }
158 
159     /// Same as [`hashbrown::hash_map::HashMap::iter_mut`].
iter_mut(&mut self) -> inner::IterMut<'_, K, V>160     pub fn iter_mut(&mut self) -> inner::IterMut<'_, K, V> {
161         self.inner.iter_mut()
162     }
163 }
164 
165 impl<K, V, S> TryHashMap<K, V, S>
166 where
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.
with_capacity_and_hasher(capacity: usize, hasher: S) -> Result<Self, OutOfMemory>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.
reserve(&mut self, additional: usize) -> Result<(), OutOfMemory>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`].
contains_key<Q>(&self, key: &Q) -> bool where Q: Hash + Eq + ?Sized, K: Borrow<Q>,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`].
get<Q>(&self, value: &Q) -> Option<&V> where Q: Hash + Eq + ?Sized, K: Borrow<Q>,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.
insert(&mut self, key: K, value: V) -> Result<Option<V>, OutOfMemory>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`].
remove<Q>(&mut self, key: &Q) -> Option<V> where Q: Hash + Eq + ?Sized, K: Borrow<Q>,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 
226 impl<'a, K, V, S> IntoIterator for &'a TryHashMap<K, V, S> {
227     type Item = (&'a K, &'a V);
228 
229     type IntoIter = inner::Iter<'a, K, V>;
230 
into_iter(self) -> Self::IntoIter231     fn into_iter(self) -> Self::IntoIter {
232         self.iter()
233     }
234 }
235 
236 impl<'a, K, V, S> IntoIterator for &'a mut TryHashMap<K, V, S> {
237     type Item = (&'a K, &'a mut V);
238 
239     type IntoIter = inner::IterMut<'a, K, V>;
240 
into_iter(self) -> Self::IntoIter241     fn into_iter(self) -> Self::IntoIter {
242         self.iter_mut()
243     }
244 }
245 
246 impl<K, V, S> IntoIterator for TryHashMap<K, V, S> {
247     type Item = (K, V);
248 
249     type IntoIter = inner::IntoIter<K, V>;
250 
into_iter(self) -> Self::IntoIter251     fn into_iter(self) -> Self::IntoIter {
252         self.inner.into_iter()
253     }
254 }
255 
256 impl<K, V, S> From<TryHashMap<K, V, S>> for inner::HashMap<K, V, S> {
from(map: TryHashMap<K, V, S>) -> Self257     fn from(map: TryHashMap<K, V, S>) -> Self {
258         map.inner
259     }
260 }
261