diff --git a/src/texture/slotmap.rs b/src/texture/slotmap.rs index a19dfe75..8b25b598 100644 --- a/src/texture/slotmap.rs +++ b/src/texture/slotmap.rs @@ -1,30 +1,7 @@ // Heavily reduced version of the `slotmap` crate: https://github.com/orlp/slotmap use miniquad::TextureId; -use std::fmt; -use std::num::NonZeroU32; -#[derive(Copy, Clone, PartialEq)] -pub(crate) struct TextureSlotId { - idx: u32, - version: NonZeroU32, -} - -impl fmt::Debug for TextureSlotId { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}v{}", self.idx, self.version.get()) - } -} - -impl TextureSlotId { - fn new(idx: u32, version: u32) -> Self { - debug_assert!(version > 0); - - Self { - idx, - version: unsafe { NonZeroU32::new_unchecked(version | 1) }, - } - } -} +pub(crate) type TextureSlotId = u32; // Storage inside a slot or metadata for the freelist when vacant. union SlotUnion { @@ -32,16 +9,9 @@ union SlotUnion { next_free: u32, } -// A slot, which represents storage for a value and a current version. -// Can be occupied or vacant. -struct Slot { - u: SlotUnion, - version: u32, // Even = vacant, odd = occupied. -} - /// Slot map, storage with stable unique keys. pub(crate) struct TextureIdSlotMap { - slots: Vec, + slots: Vec, free_head: u32, num_elems: u32, } @@ -49,10 +19,7 @@ pub(crate) struct TextureIdSlotMap { impl TextureIdSlotMap { /// Constructs a new, empty [`TextureIdSlotMap`]. pub fn new() -> Self { - let slots = vec![Slot { - u: SlotUnion { next_free: 0 }, - version: 0, - }]; + let slots = vec![SlotUnion { next_free: 0 }]; Self { slots, @@ -69,9 +36,7 @@ impl TextureIdSlotMap { /// Returns [`true`] if the slot map contains `key`. #[inline(always)] fn contains_key(&self, key: TextureSlotId) -> bool { - self.slots - .get(key.idx as usize) - .map_or(false, |slot| slot.version == key.version.get()) + self.slots.get(key as usize).is_some() } /// Inserts a value into the slot map. Returns a unique key that can be used @@ -88,29 +53,23 @@ impl TextureIdSlotMap { } if let Some(slot) = self.slots.get_mut(self.free_head as usize) { - let occupied_version = slot.version | 1; - let kd = TextureSlotId::new(self.free_head, occupied_version); + let kd = self.free_head; // Update. unsafe { - self.free_head = slot.u.next_free; - slot.u.value = value; - slot.version = occupied_version; + self.free_head = slot.next_free; + slot.value = value; } self.num_elems = new_num_elems; return kd; } - let version = 1; - let kd = TextureSlotId::new(self.slots.len() as u32, version); + let kd = self.slots.len() as u32; // Create new slot before adjusting freelist in case f or the allocation panics or errors. - self.slots.push(Slot { - u: SlotUnion { value }, - version, - }); + self.slots.push(SlotUnion { value }); - self.free_head = kd.idx + 1; + self.free_head = kd + 1; self.num_elems = new_num_elems; kd } @@ -118,24 +77,22 @@ impl TextureIdSlotMap { /// Removes a key from the slot map if it is present. pub fn remove(&mut self, key: TextureSlotId) { if self.contains_key(key) { - let idx = key.idx as usize; + let idx = key as usize; // This is safe because we know that the slot is occupied. let slot = unsafe { self.slots.get_unchecked_mut(idx) }; // Maintain freelist. - slot.u.next_free = self.free_head; + slot.next_free = self.free_head; self.free_head = idx as u32; self.num_elems -= 1; - slot.version = slot.version.wrapping_add(1); } } /// Returns a reference to the value corresponding to the key. pub fn get(&self, key: TextureSlotId) -> Option { self.slots - .get(key.idx as usize) - .filter(|slot| slot.version == key.version.get()) - .map(|slot| unsafe { slot.u.value }) + .get(key as usize) + .map(|slot| unsafe { slot.value }) } }