pjson_rs/application/dto/
id_dto.rs1use crate::domain::value_objects::{Id, IdMarker, SessionMarker, StreamMarker};
7use serde::{Deserialize, Serialize};
8use std::marker::PhantomData;
9use uuid::Uuid;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
16#[serde(transparent)]
17pub struct IdDto<T: IdMarker> {
18 uuid: Uuid,
19 #[serde(skip)]
20 _marker: PhantomData<T>,
21}
22
23impl<T: IdMarker> IdDto<T> {
24 #[must_use]
26 pub fn new(uuid: Uuid) -> Self {
27 Self {
28 uuid,
29 _marker: PhantomData,
30 }
31 }
32
33 pub fn from_string(s: &str) -> Result<Self, uuid::Error> {
39 let uuid = Uuid::parse_str(s)?;
40 Ok(Self::new(uuid))
41 }
42
43 #[must_use]
45 pub fn uuid(self) -> Uuid {
46 self.uuid
47 }
48
49 #[must_use]
51 pub fn as_string(self) -> String {
52 self.uuid.to_string()
53 }
54}
55
56impl<T: IdMarker> From<Id<T>> for IdDto<T> {
57 fn from(id: Id<T>) -> Self {
58 Self::new(id.as_uuid())
59 }
60}
61
62impl<T: IdMarker> From<IdDto<T>> for Id<T> {
63 fn from(dto: IdDto<T>) -> Self {
64 Id::from_uuid(dto.uuid)
65 }
66}
67
68impl<T: IdMarker> std::fmt::Display for IdDto<T> {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 write!(f, "{}", self.uuid)
71 }
72}
73
74pub type SessionIdDto = IdDto<SessionMarker>;
76
77pub type StreamIdDto = IdDto<StreamMarker>;
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use crate::domain::value_objects::{SessionId, StreamId};
84
85 #[test]
86 fn test_session_id_dto_serialization() {
87 let session_id = SessionId::new();
88 let dto = SessionIdDto::from(session_id);
89
90 let json = serde_json::to_string(&dto).unwrap();
91 let deserialized: SessionIdDto = serde_json::from_str(&json).unwrap();
92
93 assert_eq!(deserialized.uuid(), dto.uuid());
94
95 let domain_session_id = Id::from(deserialized);
96 assert_eq!(domain_session_id.as_uuid(), session_id.as_uuid());
97 }
98
99 #[test]
100 fn test_stream_id_dto_serialization() {
101 let stream_id = StreamId::new();
102 let dto = StreamIdDto::from(stream_id);
103
104 let json = serde_json::to_string(&dto).unwrap();
105 let deserialized: StreamIdDto = serde_json::from_str(&json).unwrap();
106
107 assert_eq!(deserialized.uuid(), dto.uuid());
108 }
109
110 #[test]
111 fn test_id_dto_from_string() {
112 let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
113 let dto = SessionIdDto::from_string(uuid_str).unwrap();
114 assert_eq!(dto.as_string(), uuid_str);
115
116 assert!(SessionIdDto::from_string("invalid-uuid").is_err());
117 }
118
119 #[test]
120 fn test_conversion_traits() {
121 let session_id = SessionId::new();
122
123 let dto: SessionIdDto = session_id.into();
124 assert_eq!(dto.uuid(), session_id.as_uuid());
125
126 let converted = SessionId::from(dto);
127 assert_eq!(converted.as_uuid(), session_id.as_uuid());
128 }
129
130 #[test]
131 fn test_display() {
132 let dto = SessionIdDto::from_string("550e8400-e29b-41d4-a716-446655440000").unwrap();
133 assert_eq!(format!("{}", dto), "550e8400-e29b-41d4-a716-446655440000");
134 }
135}