1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
14#[repr(transparent)]
15pub struct NodeId(u32);
16
17impl NodeId {
18 #[inline]
20 pub const fn new(id: u32) -> Self {
21 Self(id)
22 }
23
24 #[inline]
26 pub const fn from_le_bytes(bytes: [u8; 4]) -> Self {
27 Self(u32::from_le_bytes(bytes))
28 }
29
30 #[inline]
32 pub const fn from_be_bytes(bytes: [u8; 4]) -> Self {
33 Self(u32::from_be_bytes(bytes))
34 }
35
36 #[inline]
38 pub const fn as_u32(self) -> u32 {
39 self.0
40 }
41
42 #[inline]
44 pub const fn to_le_bytes(self) -> [u8; 4] {
45 self.0.to_le_bytes()
46 }
47
48 #[inline]
50 pub const fn to_be_bytes(self) -> [u8; 4] {
51 self.0.to_be_bytes()
52 }
53
54 #[inline]
56 pub const fn is_null(self) -> bool {
57 self.0 == 0
58 }
59
60 pub const NULL: Self = Self(0);
62}
63
64impl From<u32> for NodeId {
65 #[inline]
66 fn from(id: u32) -> Self {
67 Self(id)
68 }
69}
70
71impl From<NodeId> for u32 {
72 #[inline]
73 fn from(id: NodeId) -> Self {
74 id.0
75 }
76}
77
78#[cfg(feature = "std")]
79impl core::fmt::Display for NodeId {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 write!(f, "{:08X}", self.0)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_node_id_roundtrip() {
91 let id = NodeId::new(0xDEADBEEF);
92 let bytes = id.to_le_bytes();
93 let recovered = NodeId::from_le_bytes(bytes);
94 assert_eq!(id, recovered);
95 }
96
97 #[test]
98 fn test_node_id_null() {
99 assert!(NodeId::NULL.is_null());
100 assert!(NodeId::new(0).is_null());
101 assert!(!NodeId::new(1).is_null());
102 }
103}