Remove hashbrown from object.rs

This commit is contained in:
Gwilym Kuiper 2022-03-18 00:47:10 +00:00
parent 5edd46e085
commit f7eb1866c2
3 changed files with 93 additions and 34 deletions

View file

@ -25,7 +25,6 @@ agb_sound_converter = { version = "0.1.0", path = "../agb-sound-converter" }
agb_macros = { version = "0.1.0", path = "../agb-macros" } agb_macros = { version = "0.1.0", path = "../agb-macros" }
agb_fixnum = { version = "0.1.0", path = "../agb-fixnum" } agb_fixnum = { version = "0.1.0", path = "../agb-fixnum" }
bare-metal = "1" bare-metal = "1"
hashbrown = "0.12"
modular-bitfield = "0.11" modular-bitfield = "0.11"
rustc-hash = { version = "1", default-features = false } rustc-hash = { version = "1", default-features = false }

View file

@ -6,9 +6,6 @@ use core::ptr::NonNull;
use core::slice; use core::slice;
use modular_bitfield::prelude::{B10, B2, B3, B4, B5, B8, B9}; use modular_bitfield::prelude::{B10, B2, B3, B4, B5, B8, B9};
use modular_bitfield::{bitfield, BitfieldSpecifier}; use modular_bitfield::{bitfield, BitfieldSpecifier};
use rustc_hash::FxHasher;
use hashbrown::HashMap;
const BYTES_PER_TILE_4BPP: usize = 32; const BYTES_PER_TILE_4BPP: usize = 32;
@ -18,6 +15,7 @@ use crate::agb_alloc::block_allocator::BlockAllocator;
use crate::agb_alloc::bump_allocator::StartEnd; use crate::agb_alloc::bump_allocator::StartEnd;
use crate::dma; use crate::dma;
use crate::fixnum::Vector2D; use crate::fixnum::Vector2D;
use crate::hash_map::HashMap;
use attributes::*; use attributes::*;
@ -316,8 +314,8 @@ pub struct Object<'a, 'b> {
} }
struct SpriteControllerInner { struct SpriteControllerInner {
palette: HashMap<PaletteId, Storage, BuildHasherDefault<FxHasher>>, palette: HashMap<PaletteId, Storage>,
sprite: HashMap<SpriteId, Storage, BuildHasherDefault<FxHasher>>, sprite: HashMap<SpriteId, Storage>,
} }
pub struct SpriteController { pub struct SpriteController {
@ -629,36 +627,31 @@ impl SpriteControllerInner {
} }
fn return_sprite(&mut self, sprite: &'static Sprite) { fn return_sprite(&mut self, sprite: &'static Sprite) {
self.sprite let storage = self.sprite.get_mut(&sprite.get_id());
.entry(sprite.get_id())
.and_replace_entry_with(|_, mut storage| { if let Some(storage) = storage {
storage.count -= 1; storage.count -= 1;
if storage.count == 0 {
unsafe { SPRITE_ALLOCATOR.dealloc(storage.as_sprite_ptr(), sprite.layout()) } if storage.count == 0 {
None unsafe { SPRITE_ALLOCATOR.dealloc(storage.as_sprite_ptr(), sprite.layout()) };
} else { self.sprite.remove(&sprite.get_id());
Some(storage) }
} }
});
self.return_palette(sprite.palette) self.return_palette(sprite.palette)
} }
fn return_palette(&mut self, palette: &'static Palette16) { fn return_palette(&mut self, palette: &'static Palette16) {
let id = palette.get_id(); let id = palette.get_id();
self.palette
.entry(id) if let Some(storage) = self.palette.get_mut(&id) {
.and_replace_entry_with(|_, mut storage| { storage.count -= 1;
storage.count -= 1;
if storage.count == 0 { if storage.count == 0 {
unsafe { unsafe { PALETTE_ALLOCATOR.dealloc(storage.as_palette_ptr(), Palette16::layout()) };
PALETTE_ALLOCATOR.dealloc(storage.as_palette_ptr(), Palette16::layout()); self.palette.remove(&id);
} }
None }
} else {
Some(storage)
}
});
} }
} }

View file

@ -244,8 +244,11 @@ where
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
let hash = self.hash(key); let hash = self.hash(key);
self.get_location(key, hash) if let Some(location) = self.get_location(key, hash) {
.map(|location| &mut self.nodes.0[location].as_mut().unwrap().value) Some(&mut self.nodes.0[location].as_mut().unwrap().value)
} else {
None
}
} }
pub fn remove(&mut self, key: &K) -> Option<V> { pub fn remove(&mut self, key: &K) -> Option<V> {
@ -271,8 +274,6 @@ where
} }
} }
impl<K, V> HashMap<K, V> {}
pub struct Iter<'a, K: 'a, V: 'a> { pub struct Iter<'a, K: 'a, V: 'a> {
map: &'a HashMap<K, V>, map: &'a HashMap<K, V>,
at: usize, at: usize,
@ -306,6 +307,72 @@ impl<'a, K, V> IntoIterator for &'a HashMap<K, V> {
} }
} }
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
entry: &'a mut Node<K, V>,
}
pub struct VacantEntry<'a, K: 'a, V: 'a> {
key: K,
map: &'a mut HashMap<K, V>,
}
impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
pub fn insert(self, value: V)
where
K: Hash + Eq,
{
self.map.insert(self.key, value);
}
}
pub enum Entry<'a, K: 'a, V: 'a> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
impl<'a, K, V> Entry<'a, K, V>
where
K: Hash + Eq,
{
pub fn or_insert(self, value: V) {
match self {
Entry::Occupied(_) => {}
Entry::Vacant(e) => e.insert(value),
}
}
pub fn and_modify<F>(self, f: F) -> Self
where
F: FnOnce(&mut V),
{
match self {
Entry::Occupied(e) => {
f(&mut e.entry.value);
Entry::Occupied(e)
}
Entry::Vacant(e) => Entry::Vacant(e),
}
}
}
impl<'a, K, V> HashMap<K, V>
where
K: Hash + Eq,
{
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
let hash = self.hash(&key);
let location = self.get_location(&key, hash);
if let Some(location) = location {
Entry::Occupied(OccupiedEntry {
entry: self.nodes.0[location].as_mut().unwrap(),
})
} else {
Entry::Vacant(VacantEntry { key, map: self })
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;