//! Implement Fallible HashMap use super::TryClone; use crate::TryReserveError; use core::borrow::Borrow; use core::default::Default; use core::fmt::Debug; use core::hash::Hash; #[cfg(not(all(feature = "std", feature = "rust_1_57")))] type HashMap = hashbrown::hash_map::HashMap; #[cfg(all(feature = "std", feature = "rust_1_57"))] type HashMap = std::collections::HashMap; #[cfg(not(all(feature = "std", feature = "rust_1_57")))] use hashbrown::hash_map::{Iter, IntoIter}; #[cfg(all(feature = "std", feature = "rust_1_57"))] use std::collections::hash_map::{Iter, IntoIter}; pub struct TryHashMap { inner: HashMap, } impl Default for TryHashMap { #[inline(always)] fn default() -> Self { Self { inner: Default::default(), } } } impl Debug for TryHashMap { #[inline] fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.inner.fmt(f) } } impl TryHashMap where K: Eq + Hash, { #[inline] pub fn with_capacity(capacity: usize) -> Result { let mut map = Self { inner: HashMap::new(), }; map.reserve(capacity)?; Ok(map) } #[inline(always)] pub fn get(&self, k: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq, { self.inner.get(k) } #[inline] pub fn insert(&mut self, k: K, v: V) -> Result, TryReserveError> { self.reserve(if self.inner.capacity() == 0 { 4 } else { 1 })?; Ok(self.inner.insert(k, v)) } #[inline(always)] pub fn iter(&self) -> Iter<'_, K, V> { self.inner.iter() } #[inline(always)] pub fn len(&self) -> usize { self.inner.len() } #[inline(always)] pub fn remove(&mut self, k: &Q) -> Option where K: Borrow, Q: Hash + Eq, { self.inner.remove(k) } #[inline(always)] fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { #[cfg(not(all(feature = "std", feature = "rust_1_57")))] { self.inner.try_reserve(additional) } #[cfg(all(feature = "std", feature = "rust_1_57"))] { self.inner.try_reserve(additional).map_err(|_| { crate::make_try_reserve_error(self.len(), additional, core::mem::size_of::() + core::mem::size_of::(), core::mem::align_of::().max(core::mem::align_of::()), ) }) } } } impl IntoIterator for TryHashMap { type Item = (K, V); type IntoIter = IntoIter; #[inline(always)] fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl TryClone for TryHashMap where K: Eq + Hash + TryClone, V: TryClone, { fn try_clone(&self) -> Result { let mut clone = Self::with_capacity(self.inner.len())?; for (key, value) in self.inner.iter() { clone.insert(key.try_clone()?, value.try_clone()?)?; } Ok(clone) } } #[test] fn tryhashmap_oom() { match TryHashMap::::default().reserve(core::usize::MAX) { Ok(_) => panic!("it should be OOM"), _ => (), } }