moq/
id.rs

1use std::num::NonZero;
2
3use crate::Error;
4
5/// Opaque resource identifier returned to C code.
6///
7/// Non-zero u32 value that uniquely identifies resources like sessions,
8/// origins, broadcasts, tracks, etc. Zero is reserved to indicate "none"
9/// or optional parameters.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub struct Id(NonZero<u32>);
12
13impl std::fmt::Display for Id {
14	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15		write!(f, "{}", self.0.get())
16	}
17}
18
19/// Slab allocator that only returns non-zero IDs.
20///
21/// Wraps [slab::Slab] to ensure all IDs start from 1 instead of 0,
22/// allowing 0 to represent null/none in the FFI layer.
23pub(crate) struct NonZeroSlab<T>(slab::Slab<T>);
24
25impl<T> NonZeroSlab<T> {
26	pub fn insert(&mut self, value: T) -> Id {
27		let id = self.0.insert(value) + 1;
28		let id = u32::try_from(id).expect("u32 overflow");
29		Id(unsafe { NonZero::new_unchecked(id) })
30	}
31
32	pub fn get(&self, id: Id) -> Option<&T> {
33		let id = (id.0.get() - 1) as usize;
34		self.0.get(id)
35	}
36
37	pub fn get_mut(&mut self, id: Id) -> Option<&mut T> {
38		let id = (id.0.get() - 1) as usize;
39		self.0.get_mut(id)
40	}
41
42	pub fn remove(&mut self, id: Id) -> Option<T> {
43		let id = (id.0.get() - 1) as usize;
44		self.0.try_remove(id)
45	}
46}
47
48impl TryFrom<i32> for Id {
49	type Error = Error;
50
51	fn try_from(value: i32) -> Result<Self, Self::Error> {
52		Self::try_from(u32::try_from(value).map_err(|_| Error::InvalidId)?)
53	}
54}
55
56impl TryFrom<u32> for Id {
57	type Error = Error;
58
59	fn try_from(value: u32) -> Result<Self, Self::Error> {
60		NonZero::try_from(value).map(Id).map_err(|_| Error::InvalidId)
61	}
62}
63
64impl From<Id> for u32 {
65	fn from(value: Id) -> Self {
66		value.0.get()
67	}
68}
69
70impl TryFrom<Id> for i32 {
71	type Error = Error;
72
73	fn try_from(value: Id) -> Result<Self, Self::Error> {
74		i32::try_from(u32::from(value)).map_err(|_| Error::InvalidId)
75	}
76}
77
78impl<T> Default for NonZeroSlab<T> {
79	fn default() -> Self {
80		Self(slab::Slab::new())
81	}
82}