1use serde::{Deserialize, Serialize};
2use std::fmt;
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
7#[serde(transparent)]
8pub struct TaskId(Uuid);
9
10impl TaskId {
11 pub fn new() -> Self {
13 Self(Uuid::now_v7())
14 }
15
16 pub fn from_uuid(uuid: Uuid) -> Self {
18 Self(uuid)
19 }
20
21 pub fn as_uuid(&self) -> &Uuid {
23 &self.0
24 }
25}
26
27impl Default for TaskId {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl fmt::Display for TaskId {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 self.0.fmt(f)
36 }
37}
38
39impl From<Uuid> for TaskId {
40 fn from(uuid: Uuid) -> Self {
41 Self(uuid)
42 }
43}
44
45impl From<TaskId> for Uuid {
46 fn from(id: TaskId) -> Self {
47 id.0
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn task_id_ordering() {
57 let id1 = TaskId::new();
58 let id2 = TaskId::new();
59 assert!(id1 < id2, "UUID v7 should be time-ordered");
60 }
61
62 #[test]
63 fn task_id_display() {
64 let id = TaskId::new();
65 let s = id.to_string();
66 assert!(!s.is_empty());
67 assert_eq!(s.len(), 36);
69 }
70
71 #[test]
72 fn task_id_serde_roundtrip() {
73 let id = TaskId::new();
74 let json = serde_json::to_string(&id).unwrap();
75 let deserialized: TaskId = serde_json::from_str(&json).unwrap();
76 assert_eq!(id, deserialized);
77 }
78}