use serde::{Deserialize, Serialize};
use std::fmt;
use uuid::Uuid;
macro_rules! define_id {
($name:ident) => {
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
)]
#[repr(transparent)]
pub struct $name(Uuid);
impl $name {
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub fn from_uuid(uuid: Uuid) -> Self {
Self(uuid)
}
pub fn from_bytes(bytes: [u8; 16]) -> Self {
Self(Uuid::from_bytes(bytes))
}
pub fn as_uuid(&self) -> Uuid {
self.0
}
pub fn as_bytes(&self) -> &[u8; 16] {
self.0.as_bytes()
}
}
impl Default for $name {
fn default() -> Self {
Self::new()
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
define_id!(NodeId);
define_id!(EdgeId);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ids_are_unique_and_ordered() {
let a = NodeId::new();
let b = NodeId::new();
assert_ne!(a, b);
assert!(a < b, "UUIDv7 should produce monotonically ordered IDs");
}
#[test]
fn node_and_edge_ids_are_distinct_types() {
let n = NodeId::new();
let e = EdgeId::from_uuid(n.as_uuid());
assert_eq!(n.as_uuid(), e.as_uuid());
}
}