116 lines
2.8 KiB
Rust
116 lines
2.8 KiB
Rust
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
pub struct SlotId {
|
|
idx: u32,
|
|
genr: u32,
|
|
}
|
|
|
|
impl SlotId {
|
|
pub(crate) fn slot(self) -> u32 {
|
|
self.idx
|
|
}
|
|
|
|
/// A stable, collision-free `u64` encoding of this id -- for a caller
|
|
/// (accesskit's `NodeId`, today) that wants a flat integer key rather
|
|
/// than the two `u32`s. `idx` is offset by one so no real id ever
|
|
/// encodes to 0, which callers can then reserve for their own
|
|
/// out-of-band root/window node.
|
|
pub fn as_u64(&self) -> u64 {
|
|
((self.idx as u64) + 1) << 32 | self.genr as u64
|
|
}
|
|
}
|
|
|
|
pub struct SlotVec<T> {
|
|
data: Vec<(u32, Option<T>)>,
|
|
free: Vec<u32>,
|
|
len: usize,
|
|
}
|
|
|
|
impl<T> SlotVec<T> {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
data: Default::default(),
|
|
free: Default::default(),
|
|
len: 0,
|
|
}
|
|
}
|
|
|
|
pub fn add(&mut self, x: T) -> SlotId {
|
|
let id = if let Some(idx) = self.free.pop() {
|
|
let (genr, data) = &mut self.data[idx as usize];
|
|
*data = Some(x);
|
|
SlotId { idx, genr: *genr }
|
|
} else {
|
|
let idx = self.data.len() as u32;
|
|
let genr = 0;
|
|
self.data.push((genr, Some(x)));
|
|
SlotId { idx, genr }
|
|
};
|
|
self.len += 1;
|
|
id
|
|
}
|
|
|
|
pub fn free(&mut self, id: SlotId) {
|
|
let _ = self.remove(id);
|
|
}
|
|
|
|
pub fn remove(&mut self, id: SlotId) -> Option<T> {
|
|
self.remove_inner(id, true)
|
|
}
|
|
|
|
pub fn remove_unrecycled(&mut self, id: SlotId) -> Option<T> {
|
|
self.remove_inner(id, false)
|
|
}
|
|
|
|
fn remove_inner(&mut self, id: SlotId, recycle: bool) -> Option<T> {
|
|
let (genr, data) = &mut self.data[id.idx as usize];
|
|
if *genr != id.genr {
|
|
return None;
|
|
}
|
|
*genr += 1;
|
|
let value = data.take()?;
|
|
self.len -= 1;
|
|
if recycle {
|
|
self.free.push(id.idx);
|
|
}
|
|
Some(value)
|
|
}
|
|
|
|
pub fn get(&self, id: SlotId) -> Option<&T> {
|
|
let slot = &self.data[id.idx as usize];
|
|
if slot.0 != id.genr {
|
|
return None;
|
|
}
|
|
slot.1.as_ref()
|
|
}
|
|
|
|
pub fn get_mut(&mut self, id: SlotId) -> Option<&mut T> {
|
|
let slot = &mut self.data[id.idx as usize];
|
|
if slot.0 != id.genr {
|
|
return None;
|
|
}
|
|
slot.1.as_mut()
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.len
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
|
self.data.iter_mut().filter_map(|(_, value)| value.as_mut())
|
|
}
|
|
|
|
pub fn capacity(&self) -> usize {
|
|
self.data.len()
|
|
}
|
|
}
|
|
|
|
impl<T> Default for SlotVec<T> {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|