use std::collections::HashMap;
use std::num::NonZero;
use std::sync::atomic::{AtomicU32, Ordering};
use crate::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Id(NonZero<u32>);
impl std::fmt::Display for Id {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.get())
}
}
static NEXT_ID: AtomicU32 = AtomicU32::new(1);
pub(crate) struct NonZeroSlab<T> {
map: HashMap<Id, T>,
}
impl<T> NonZeroSlab<T> {
pub fn insert(&mut self, value: T) -> Result<Id, Error> {
let raw = NEXT_ID.fetch_add(1, Ordering::Relaxed);
let id = Id::try_from(raw)?;
self.map.insert(id, value);
Ok(id)
}
pub fn get(&self, id: Id) -> Option<&T> {
self.map.get(&id)
}
pub fn get_mut(&mut self, id: Id) -> Option<&mut T> {
self.map.get_mut(&id)
}
pub fn remove(&mut self, id: Id) -> Option<T> {
self.map.remove(&id)
}
}
impl TryFrom<i32> for Id {
type Error = Error;
fn try_from(value: i32) -> Result<Self, Self::Error> {
Self::try_from(u32::try_from(value).map_err(|_| Error::InvalidId)?)
}
}
impl TryFrom<u32> for Id {
type Error = Error;
fn try_from(value: u32) -> Result<Self, Self::Error> {
i32::try_from(value).map_err(|_| Error::InvalidId)?;
NonZero::try_from(value).map(Id).map_err(|_| Error::InvalidId)
}
}
impl From<Id> for u32 {
fn from(value: Id) -> Self {
value.0.get()
}
}
impl From<Id> for i32 {
fn from(value: Id) -> Self {
value.0.get() as i32
}
}
impl<T> Default for NonZeroSlab<T> {
fn default() -> Self {
Self { map: HashMap::new() }
}
}