Skip to main content

pjson_rs/application/dto/
priority_dto.rs

1//! Priority Data Transfer Object for serialization
2//!
3//! Handles serialization/deserialization of Priority domain objects
4//! while keeping domain layer clean of serialization concerns.
5
6use crate::domain::value_objects::Priority;
7use crate::domain::{DomainError, DomainResult};
8use serde::{Deserialize, Serialize};
9
10/// Serializable representation of Priority domain object
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(transparent)]
13pub struct PriorityDto {
14    value: u8,
15}
16
17impl PriorityDto {
18    /// Create from raw value with validation
19    pub fn new(value: u8) -> DomainResult<Self> {
20        // Validate using domain rules
21        Priority::new(value)?;
22        Ok(Self { value })
23    }
24
25    /// Get raw value
26    pub fn value(self) -> u8 {
27        self.value
28    }
29}
30
31impl From<Priority> for PriorityDto {
32    fn from(priority: Priority) -> Self {
33        Self {
34            value: priority.value(),
35        }
36    }
37}
38
39impl TryFrom<PriorityDto> for Priority {
40    type Error = DomainError;
41
42    fn try_from(dto: PriorityDto) -> Result<Self, Self::Error> {
43        Priority::new(dto.value)
44    }
45}
46
47/// Utility trait for converting domain objects to DTOs
48pub trait ToDto<T> {
49    /// Convert this domain object into its DTO representation.
50    fn to_dto(self) -> T;
51}
52
53impl ToDto<PriorityDto> for Priority {
54    fn to_dto(self) -> PriorityDto {
55        PriorityDto::from(self)
56    }
57}
58
59/// Utility trait for converting DTOs to domain objects
60pub trait FromDto<T> {
61    /// Error returned when the DTO cannot be reconstructed into a valid domain object.
62    type Error;
63
64    /// Convert a DTO into its domain representation, validating invariants.
65    fn from_dto(dto: T) -> Result<Self, Self::Error>
66    where
67        Self: Sized;
68}
69
70impl FromDto<PriorityDto> for Priority {
71    type Error = DomainError;
72
73    fn from_dto(dto: PriorityDto) -> Result<Self, Self::Error> {
74        Priority::try_from(dto)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use serde_json;
82
83    #[test]
84    fn test_priority_dto_serialization() {
85        let priority = Priority::CRITICAL;
86        let dto = PriorityDto::from(priority);
87
88        // Test JSON serialization
89        let json = serde_json::to_string(&dto).unwrap();
90        assert_eq!(json, "100");
91
92        // Test JSON deserialization
93        let deserialized: PriorityDto = serde_json::from_str(&json).unwrap();
94        assert_eq!(deserialized.value(), 100);
95
96        // Test conversion back to domain
97        let domain_priority = Priority::from_dto(deserialized).unwrap();
98        assert_eq!(domain_priority, Priority::CRITICAL);
99    }
100
101    #[test]
102    fn test_priority_dto_validation() {
103        // Valid priority
104        assert!(PriorityDto::new(100).is_ok());
105
106        // Invalid priority (zero)
107        assert!(PriorityDto::new(0).is_err());
108    }
109
110    #[test]
111    fn test_conversion_traits() {
112        let priority = Priority::HIGH;
113
114        // Test ToDto trait
115        let dto = priority.to_dto();
116        assert_eq!(dto.value(), 80);
117
118        // Test FromDto trait
119        let converted = Priority::from_dto(dto).unwrap();
120        assert_eq!(converted, Priority::HIGH);
121    }
122}