1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6use uuid::Uuid;
7
8#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub struct NodeId(pub u64);
11
12impl NodeId {
13 pub fn new() -> Self {
15 Self(rand_u64())
16 }
17
18 pub const fn from_raw(value: u64) -> Self {
20 Self(value)
21 }
22
23 pub const fn as_u64(&self) -> u64 {
25 self.0
26 }
27}
28
29impl Default for NodeId {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl fmt::Debug for NodeId {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "NodeId({:016x})", self.0)
38 }
39}
40
41impl fmt::Display for NodeId {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "{:016x}", self.0)
44 }
45}
46
47impl FromStr for NodeId {
48 type Err = std::num::ParseIntError;
49
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
51 u64::from_str_radix(s, 16).map(NodeId)
52 }
53}
54
55#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
57pub struct TaskId(pub Uuid);
58
59impl TaskId {
60 pub fn new() -> Self {
62 Self(Uuid::now_v7())
63 }
64
65 pub const fn from_uuid(uuid: Uuid) -> Self {
67 Self(uuid)
68 }
69
70 pub const fn as_uuid(&self) -> &Uuid {
72 &self.0
73 }
74
75 pub fn parse(s: &str) -> Result<Self, uuid::Error> {
77 Ok(Self(Uuid::parse_str(s)?))
78 }
79}
80
81impl Default for TaskId {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl fmt::Debug for TaskId {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 write!(f, "TaskId({})", self.0)
90 }
91}
92
93impl fmt::Display for TaskId {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "{}", self.0)
96 }
97}
98
99#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
101pub struct InstanceId(pub Uuid);
102
103impl InstanceId {
104 pub fn new() -> Self {
106 Self(Uuid::now_v7())
107 }
108
109 pub const fn from_uuid(uuid: Uuid) -> Self {
111 Self(uuid)
112 }
113
114 pub const fn as_uuid(&self) -> &Uuid {
116 &self.0
117 }
118
119 pub fn parse(s: &str) -> Result<Self, uuid::Error> {
121 Ok(Self(Uuid::parse_str(s)?))
122 }
123}
124
125impl Default for InstanceId {
126 fn default() -> Self {
127 Self::new()
128 }
129}
130
131impl fmt::Debug for InstanceId {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "InstanceId({})", self.0)
134 }
135}
136
137impl fmt::Display for InstanceId {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 write!(f, "{}", self.0)
140 }
141}
142
143fn rand_u64() -> u64 {
145 use std::time::{SystemTime, UNIX_EPOCH};
146 use std::cell::Cell;
147
148 thread_local! {
149 static STATE: Cell<u64> = Cell::new(
150 SystemTime::now()
151 .duration_since(UNIX_EPOCH)
152 .unwrap()
153 .as_nanos() as u64
154 );
155 }
156
157 STATE.with(|state| {
158 let mut x = state.get();
159 x ^= x << 13;
160 x ^= x >> 7;
161 x ^= x << 17;
162 state.set(x);
163 x
164 })
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_node_id_unique() {
173 let id1 = NodeId::new();
174 let id2 = NodeId::new();
175 assert_ne!(id1, id2);
176 }
177
178 #[test]
179 fn test_task_id_parse() {
180 let id = TaskId::new();
181 let parsed = TaskId::parse(&id.to_string()).unwrap();
182 assert_eq!(id, parsed);
183 }
184
185 #[test]
186 fn test_instance_id_ordered() {
187 let id1 = InstanceId::new();
188 std::thread::sleep(std::time::Duration::from_millis(1));
189 let id2 = InstanceId::new();
190 assert!(id1.0 < id2.0);
192 }
193}