1use serde::{Deserialize, Serialize};
2use std::fmt;
3use uuid::Uuid;
4
5macro_rules! define_id {
6 ($name:ident) => {
7 #[derive(
8 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
9 )]
10 #[repr(transparent)]
11 pub struct $name(Uuid);
12
13 impl $name {
14 pub fn new() -> Self {
15 Self(Uuid::now_v7())
16 }
17
18 pub fn from_uuid(uuid: Uuid) -> Self {
19 Self(uuid)
20 }
21
22 pub fn from_bytes(bytes: [u8; 16]) -> Self {
23 Self(Uuid::from_bytes(bytes))
24 }
25
26 pub fn as_uuid(&self) -> Uuid {
27 self.0
28 }
29
30 pub fn as_bytes(&self) -> &[u8; 16] {
31 self.0.as_bytes()
32 }
33 }
34
35 impl Default for $name {
36 fn default() -> Self {
37 Self::new()
38 }
39 }
40
41 impl fmt::Display for $name {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "{}", self.0)
44 }
45 }
46 };
47}
48
49define_id!(NodeId);
50define_id!(EdgeId);
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn ids_are_unique_and_ordered() {
58 let a = NodeId::new();
59 let b = NodeId::new();
60 assert_ne!(a, b);
61 assert!(a < b, "UUIDv7 should produce monotonically ordered IDs");
62 }
63
64 #[test]
65 fn node_and_edge_ids_are_distinct_types() {
66 let n = NodeId::new();
67 let e = EdgeId::from_uuid(n.as_uuid());
68 assert_eq!(n.as_uuid(), e.as_uuid());
69 }
70}