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