pjson_rs/application/dto/
stream_id_dto.rs

1//! StreamId Data Transfer Object for serialization
2//!
3//! Handles serialization/deserialization of StreamId domain objects
4//! while keeping domain layer clean of serialization concerns.
5
6use crate::{
7    application::dto::priority_dto::{FromDto, ToDto},
8    domain::{DomainError, value_objects::StreamId},
9};
10use serde::{Deserialize, Serialize};
11use uuid::Uuid;
12
13/// Serializable representation of StreamId domain object
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(transparent)]
16pub struct StreamIdDto {
17    uuid: Uuid,
18}
19
20impl StreamIdDto {
21    /// Create from UUID
22    pub fn new(uuid: Uuid) -> Self {
23        Self { uuid }
24    }
25
26    /// Create from string with validation
27    pub fn from_string(s: &str) -> Result<Self, uuid::Error> {
28        let uuid = Uuid::parse_str(s)?;
29        Ok(Self { uuid })
30    }
31
32    /// Get UUID value
33    pub fn uuid(self) -> Uuid {
34        self.uuid
35    }
36
37    /// Get string representation
38    pub fn as_string(self) -> String {
39        self.uuid.to_string()
40    }
41}
42
43impl From<StreamId> for StreamIdDto {
44    fn from(stream_id: StreamId) -> Self {
45        Self {
46            uuid: stream_id.as_uuid(),
47        }
48    }
49}
50
51impl From<StreamIdDto> for StreamId {
52    fn from(dto: StreamIdDto) -> Self {
53        StreamId::from_uuid(dto.uuid)
54    }
55}
56
57/// Utility trait implementation for StreamId
58impl ToDto<StreamIdDto> for StreamId {
59    fn to_dto(self) -> StreamIdDto {
60        StreamIdDto::from(self)
61    }
62}
63
64/// Utility trait implementation for StreamId
65impl FromDto<StreamIdDto> for StreamId {
66    type Error = DomainError;
67
68    fn from_dto(dto: StreamIdDto) -> Result<Self, Self::Error> {
69        Ok(StreamId::from(dto))
70    }
71}
72
73impl std::fmt::Display for StreamIdDto {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        write!(f, "{}", self.uuid)
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82    use serde_json;
83
84    #[test]
85    fn test_stream_id_dto_serialization() {
86        let stream_id = StreamId::new();
87        let dto = StreamIdDto::from(stream_id);
88
89        // Test JSON serialization
90        let json = serde_json::to_string(&dto).unwrap();
91
92        // Test JSON deserialization
93        let deserialized: StreamIdDto = serde_json::from_str(&json).unwrap();
94        assert_eq!(deserialized.uuid(), dto.uuid());
95
96        // Test conversion back to domain
97        let domain_stream_id = StreamId::from_dto(deserialized).unwrap();
98        assert_eq!(domain_stream_id.as_uuid(), stream_id.as_uuid());
99    }
100
101    #[test]
102    fn test_stream_id_dto_from_string() {
103        let uuid_str = "550e8400-e29b-41d4-a716-446655440000";
104        let dto = StreamIdDto::from_string(uuid_str).unwrap();
105        assert_eq!(dto.as_string(), uuid_str);
106
107        // Test invalid UUID
108        assert!(StreamIdDto::from_string("invalid-uuid").is_err());
109    }
110
111    #[test]
112    fn test_conversion_traits() {
113        let stream_id = StreamId::new();
114
115        // Test ToDto trait
116        let dto = stream_id.to_dto();
117        assert_eq!(dto.uuid(), stream_id.as_uuid());
118
119        // Test FromDto trait
120        let converted = StreamId::from_dto(dto).unwrap();
121        assert_eq!(converted.as_uuid(), stream_id.as_uuid());
122    }
123}