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