Skip to main content

scenix_core/
ids.rs

1use core::fmt;
2
3macro_rules! id_type {
4    ($name:ident, $doc:literal) => {
5        #[doc = $doc]
6        #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
7        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8        pub struct $name(u64);
9
10        impl $name {
11            /// Creates an ID from a raw value.
12            #[inline]
13            pub const fn new(value: u64) -> Self {
14                Self(value)
15            }
16
17            /// Returns the raw ID value.
18            #[inline]
19            pub const fn get(self) -> u64 {
20                self.0
21            }
22
23            /// Returns whether this ID is the default zero sentinel.
24            #[inline]
25            pub const fn is_null(self) -> bool {
26                self.0 == 0
27            }
28        }
29
30        impl fmt::Debug for $name {
31            #[inline]
32            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33                write!(f, "{}({})", stringify!($name), self.0)
34            }
35        }
36
37        impl From<u64> for $name {
38            #[inline]
39            fn from(value: u64) -> Self {
40                Self::new(value)
41            }
42        }
43
44        impl From<$name> for u64 {
45            #[inline]
46            fn from(value: $name) -> Self {
47                value.get()
48            }
49        }
50    };
51}
52
53id_type!(NodeId, "Typed identifier for a scene node.");
54id_type!(MeshId, "Typed identifier for a mesh resource.");
55id_type!(MaterialId, "Typed identifier for a material resource.");
56id_type!(TextureId, "Typed identifier for a texture resource.");
57id_type!(LightId, "Typed identifier for a light resource.");
58id_type!(CameraId, "Typed identifier for a camera resource.");
59id_type!(AssetId, "Typed identifier for an imported asset package.");
60id_type!(SkinId, "Typed identifier for imported skinning metadata.");
61id_type!(
62    AnimationClipId,
63    "Typed identifier for an imported animation clip."
64);
65
66#[cfg(all(test, feature = "std"))]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn id_newtypes_are_copy_hashable_and_debuggable() {
72        let id = NodeId::new(42);
73        let copied = id;
74        assert_eq!(copied.get(), 42);
75        assert_eq!(format!("{id:?}"), "NodeId(42)");
76    }
77}