1use std::collections::HashMap;
2use std::num::NonZero;
3use std::sync::atomic::{AtomicU32, Ordering};
4
5use crate::Error;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub struct Id(NonZero<u32>);
14
15impl std::fmt::Display for Id {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "{}", self.0.get())
18 }
19}
20
21static NEXT_ID: AtomicU32 = AtomicU32::new(1);
23
24pub(crate) struct NonZeroSlab<T> {
30 map: HashMap<Id, T>,
31}
32
33impl<T> NonZeroSlab<T> {
34 pub fn insert(&mut self, value: T) -> Result<Id, Error> {
35 let raw = NEXT_ID.fetch_add(1, Ordering::Relaxed);
36 let id = Id::try_from(raw)?;
37 self.map.insert(id, value);
38 Ok(id)
39 }
40
41 pub fn get(&self, id: Id) -> Option<&T> {
42 self.map.get(&id)
43 }
44
45 pub fn get_mut(&mut self, id: Id) -> Option<&mut T> {
46 self.map.get_mut(&id)
47 }
48
49 pub fn remove(&mut self, id: Id) -> Option<T> {
50 self.map.remove(&id)
51 }
52}
53
54impl TryFrom<i32> for Id {
55 type Error = Error;
56
57 fn try_from(value: i32) -> Result<Self, Self::Error> {
58 Self::try_from(u32::try_from(value).map_err(|_| Error::InvalidId)?)
59 }
60}
61
62impl TryFrom<u32> for Id {
63 type Error = Error;
64
65 fn try_from(value: u32) -> Result<Self, Self::Error> {
66 i32::try_from(value).map_err(|_| Error::InvalidId)?;
68 NonZero::try_from(value).map(Id).map_err(|_| Error::InvalidId)
69 }
70}
71
72impl From<Id> for u32 {
73 fn from(value: Id) -> Self {
74 value.0.get()
75 }
76}
77
78impl From<Id> for i32 {
79 fn from(value: Id) -> Self {
80 value.0.get() as i32
82 }
83}
84
85impl<T> Default for NonZeroSlab<T> {
86 fn default() -> Self {
87 Self { map: HashMap::new() }
88 }
89}