diff --git a/Cargo.toml b/Cargo.toml index fc4a67a..0bf3eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,20 @@ rust-version = "nightly" [package.metadata.docs.rs] rustdoc-args = ["--cfg", "nightly"] +[dependencies.hashbrown] +version = "0.15.1" +optional = true +default-features = false +features = [ + "nightly", + "default-hasher", + "inline-more", + "allocator-api2", + "equivalent", + "raw-entry" +] + [features] -default = [] +default = ["hash_collections"] +hash_collections = ["hashbrown"] no_std = [] diff --git a/README.md b/README.md index 04ba8b5..6dcf50a 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ The wrapper collection types provide two main benefits: * They can't be used incorrectly by virtue of lacking APIs which panic. * Provide additional convenience methods for working with the collection in a checked manner. +*N.B.:* You might find the [`heapless`](https://docs.rs/heapless/latest/heapless/) crate useful too! + ## Restrictions The crate requires a recent build of the Rust "nightly" compiler, as it uses the diff --git a/src/claim.rs b/src/claim.rs index 0703185..410efae 100644 --- a/src/claim.rs +++ b/src/claim.rs @@ -1,3 +1,4 @@ +use alloc::alloc::Global; use alloc::rc::Rc; use alloc::sync::Arc; use core::convert::Infallible; @@ -26,7 +27,7 @@ macro_rules! impl_claim_for { impl_claim_for! { (), u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, - f32, f64, bool, char + f32, f64, bool, char, Global } impl Claim for *const T {} diff --git a/src/hash/map.rs b/src/hash/map.rs new file mode 100644 index 0000000..286d212 --- /dev/null +++ b/src/hash/map.rs @@ -0,0 +1,106 @@ +use crate::claim::Claim; +use core::alloc::Allocator; +use core::hash::{BuildHasher, Hash}; +pub use hashbrown::hash_map::{Iter, IterMut, Keys, Values, ValuesMut}; +pub use hashbrown::DefaultHashBuilder; +use hashbrown::{HashMap as InnerHashMap, TryReserveError}; + +pub struct HashMap { + inner: InnerHashMap, +} + +impl HashMap { + #[inline] + pub fn new_in(alloc: A) -> Self { + Self::with_hasher_in(DefaultHashBuilder::default(), alloc) + } + + #[inline] + pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { + Self::with_capacity_and_hasher_in(capacity, DefaultHashBuilder::default(), alloc) + } +} + +impl HashMap { + #[inline] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } + + #[inline] + pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self { + Self { + inner: InnerHashMap::with_hasher_in(hash_builder, alloc), + } + } + + #[inline] + pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self { + Self { + inner: InnerHashMap::with_capacity_and_hasher_in(capacity, hash_builder, alloc), + } + } + + #[inline] + pub fn hasher(&self) -> &S { + self.inner.hasher() + } + + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + #[inline] + pub fn clear(&mut self) { + // TODO(amunra): May this reallocate memory? + } + + #[inline] + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + #[inline] + pub fn keys(&self) -> Keys<'_, K, V> { + self.inner.keys() + } + + #[inline] + pub fn values(&self) -> Values<'_, K, V> { + self.inner.values() + } + + #[inline] + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + self.inner.values_mut() + } + + #[inline] + pub fn iter(&self) -> Iter<'_, K, V> { + self.inner.iter() + } + + #[inline] + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + self.inner.iter_mut() + } +} + +impl HashMap +where + K: Eq + Hash, + A: Allocator + Claim, + S: BuildHasher, +{ + #[inline] + pub fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + + // #[inline] + // pub fn remove(&mut self, k: &Q) -> Option { + // // TODO(amunra): May this reallocate memory? + // self.inner.remove(k) + // } +} diff --git a/src/hash/mod.rs b/src/hash/mod.rs new file mode 100644 index 0000000..1d7f53b --- /dev/null +++ b/src/hash/mod.rs @@ -0,0 +1 @@ +pub mod map; diff --git a/src/lib.rs b/src/lib.rs index c42c6b0..fb6082c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,9 @@ pub mod try_clone; pub mod vec; pub mod vec_deque; +#[cfg(feature = "hash_collections")] +pub mod hash; + #[cfg(test)] pub(crate) mod testing;