diff --git a/agb-hashmap/Cargo.toml b/agb-hashmap/Cargo.toml index 717c9ad7..4468e05b 100644 --- a/agb-hashmap/Cargo.toml +++ b/agb-hashmap/Cargo.toml @@ -6,6 +6,9 @@ license = "MPL-2.0" description = "A simple no_std hashmap implementation intended for use in the `agb` library" repository = "https://github.com/agbrs/agb" +[features] +allocator_api = [] + [dependencies] rustc-hash = { version = "1", default-features = false } diff --git a/agb-hashmap/src/lib.rs b/agb-hashmap/src/lib.rs index 7114232c..898e712c 100644 --- a/agb-hashmap/src/lib.rs +++ b/agb-hashmap/src/lib.rs @@ -1,7 +1,7 @@ //! A lot of the documentation for this module was copied straight out of the rust //! standard library. The implementation however is not. #![no_std] -#![feature(allocator_api)] +#![cfg_attr(feature = "allocator_api", feature(allocator_api))] #![deny(clippy::all)] #![deny(clippy::must_use_candidate)] #![deny(missing_docs)] @@ -26,9 +26,25 @@ extern crate alloc; -use alloc::{alloc::Global, vec::Vec}; +pub(crate) use allocate::{Allocator, Global}; + +#[cfg(not(feature = "allocator_api"))] +mod allocate { + pub trait Allocator {} + + #[derive(Copy, Clone)] + pub struct Global; + + impl Allocator for Global {} +} + +#[cfg(feature = "allocator_api")] +mod allocate { + pub(crate) use alloc::alloc::Global; + pub(crate) use core::alloc::Allocator; +} + use core::{ - alloc::Allocator, borrow::Borrow, fmt::Debug, hash::{BuildHasher, BuildHasherDefault, Hash}, @@ -174,12 +190,6 @@ impl HashMap { pub fn with_capacity(capacity: usize) -> Self { Self::with_capacity_in(capacity, Global) } - - #[doc(hidden)] - #[must_use] - pub fn distance_histogram(&self) -> (Vec, usize) { - self.nodes.distance_histogram() - } } impl HashMap { @@ -583,7 +593,8 @@ impl IntoIterator for HashMap for HashType { mod test { use core::{cell::RefCell, hash::Hasher}; + use alloc::vec::Vec; + use super::*; #[test] diff --git a/agb-hashmap/src/node_storage.rs b/agb-hashmap/src/node_storage.rs index e7483671..90a3ea6e 100644 --- a/agb-hashmap/src/node_storage.rs +++ b/agb-hashmap/src/node_storage.rs @@ -1,12 +1,14 @@ -use core::{alloc::Allocator, borrow::Borrow, mem}; - -use alloc::{alloc::Global, vec::Vec}; +use core::{borrow::Borrow, mem}; +use crate::allocate::{Allocator, Global}; use crate::{node::Node, number_before_resize, ClonableAllocator, HashType}; +mod vec; +use vec::MyVec; + #[derive(Clone)] pub(crate) struct NodeStorage { - nodes: Vec, ALLOCATOR>, + nodes: MyVec, ALLOCATOR>, max_distance_to_initial_bucket: i32, number_of_items: usize, @@ -17,7 +19,7 @@ impl NodeStorage { pub(crate) fn with_size_in(capacity: usize, alloc: ALLOCATOR) -> Self { assert!(capacity.is_power_of_two(), "Capacity must be a power of 2"); - let mut nodes = Vec::with_capacity_in(capacity, alloc); + let mut nodes = MyVec::with_capacity_in(capacity, alloc); for _ in 0..capacity { nodes.push(Node::new()); } @@ -202,22 +204,6 @@ impl NodeStorage { self.nodes.get_unchecked_mut(at) } - pub(crate) fn distance_histogram(&self) -> (Vec, usize) { - let mut ret = Vec::new(); - - for node in self.nodes.iter() { - let distance = node.distance(); - - if distance >= 0 { - let distance = distance as usize; - ret.resize(ret.len().max(distance + 1), 0); - ret[distance] += 1; - } - } - - (ret, self.max_distance_to_initial_bucket as usize) - } - pub(crate) fn clear(&mut self) { self.max_distance_to_initial_bucket = 0; self.number_of_items = 0; diff --git a/agb-hashmap/src/node_storage/vec.rs b/agb-hashmap/src/node_storage/vec.rs new file mode 100644 index 00000000..2873a5a2 --- /dev/null +++ b/agb-hashmap/src/node_storage/vec.rs @@ -0,0 +1,66 @@ +use core::ops::{Deref, DerefMut}; + +use alloc::vec::Vec; + +use crate::{Allocator, Global}; + +pub(crate) use inner::MyVec; + +#[cfg(not(feature = "allocator_api"))] +mod inner { + use super::*; + + #[derive(Clone)] + pub(crate) struct MyVec(Vec, A); + + impl MyVec { + pub(crate) fn with_capacity_in(capacity: usize, allocator: A) -> Self { + Self(Vec::with_capacity(capacity), allocator) + } + + pub(crate) fn allocator(&self) -> &A { + &self.1 + } + } + impl Deref for MyVec { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl DerefMut for MyVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } +} + +#[cfg(feature = "allocator_api")] +mod inner { + use super::*; + + #[derive(Clone)] + pub(crate) struct MyVec(Vec); + + impl MyVec { + pub(crate) fn with_capacity_in(capacity: usize, allocator: A) -> Self { + Self(Vec::with_capacity_in(capacity, allocator)) + } + } + + impl Deref for MyVec { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl DerefMut for MyVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } +} diff --git a/agb/Cargo.toml b/agb/Cargo.toml index 1d884349..0755aadb 100644 --- a/agb/Cargo.toml +++ b/agb/Cargo.toml @@ -19,7 +19,7 @@ agb_image_converter = { version = "0.19.1", path = "../agb-image-converter" } agb_sound_converter = { version = "0.19.1", path = "../agb-sound-converter" } agb_macros = { version = "0.19.1", path = "../agb-macros" } agb_fixnum = { version = "0.19.1", path = "../agb-fixnum" } -agb_hashmap = { version = "0.19.1", path = "../agb-hashmap" } +agb_hashmap = { version = "0.19.1", path = "../agb-hashmap", features = ["allocator_api"] } bilge = "0.2" qrcodegen-no-heap = { version = "1.8", optional = true } portable-atomic = { version = "1.6.0", default-features = false, features = ["unsafe-assume-single-core"] }