use crate::{Handle, HandleMap};
#[derive(Debug, Clone)]
pub struct HandleAlloc {
inner: HandleMap<()>,
}
impl Default for HandleAlloc {
#[inline]
fn default() -> Self {
Self {
inner: HandleMap::new_with_map_id(0),
}
}
}
impl HandleAlloc {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
pub fn with_capacity(c: usize) -> Self {
let mut m = Self::new();
m.reserve(c);
m
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
}
pub fn reserve(&mut self, sz: usize) {
self.inner.reserve(sz);
}
#[inline]
pub fn alloc(&mut self) -> Handle {
self.inner.insert(())
}
#[inline]
pub fn dealloc(&mut self, h: Handle) -> bool {
if let Some(i) = self.test_handle(h) {
self.inner.raw_remove(i);
true
} else {
false
}
}
#[inline]
pub fn handle_for_index(&self, index: usize) -> Option<Handle> {
self.inner.handle_for_index(index)
}
#[inline]
pub fn test_handle(&self, h: Handle) -> Option<usize> {
if self.contains(h) {
Some(h.index())
} else {
None
}
}
#[inline]
pub fn contains(&self, h: Handle) -> bool {
let i = h.index() as usize;
let gen = h.generation();
if i >= self.inner.entries.len() || (gen & 1) != 0 || self.inner.entries[i].gen != gen {
super::unlikely_hint();
false
} else {
true
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_allocator() {
let mut a = HandleAlloc::with_capacity(10);
for i in 0..10 {
let v = a.alloc();
assert_eq!(v.generation(), 2);
assert_eq!(v.meta(), 0);
assert_eq!(v.index(), i);
}
assert_eq!(a.capacity(), 10);
assert_eq!(a.len(), 10);
for i in 0..10 {
assert_eq!(a.handle_for_index(i), Some(Handle::from_raw_parts(i, 2, 0)));
}
for i in (0..10).rev() {
assert_eq!(a.handle_for_index(i), Some(Handle::from_raw_parts(i, 2, 0)));
assert!(!a.dealloc(Handle::from_raw_parts(i, 1, 0))); assert!(!a.dealloc(Handle::from_raw_parts(i, 0, 0))); assert_eq!(a.test_handle(Handle::from_raw_parts(i, 2, 0)), Some(i));
assert_eq!(a.dealloc(Handle::from_raw_parts(i, 2, 0xff)), true);
assert_eq!(a.dealloc(Handle::from_raw_parts(i, 2, 0xff)), false);
assert_eq!(a.dealloc(Handle::from_raw_parts(i, 3, 0xff)), false);
}
assert!(a.is_empty());
}
}