Skip to main content

rskit_messaging/
translator.rs

1//! Message translation between wire format and domain types.
2
3use rskit_errors::{AppError, AppResult, ErrorCode};
4use serde::{Serialize, de::DeserializeOwned};
5
6/// Translates messages between wire format and domain types.
7///
8/// `W` is the wire type carried inside [`Message<W>`](crate::Message) and
9/// `D` is the domain type the application works with.
10pub trait MessageTranslator<W, D>: Send + Sync + 'static {
11    /// Serializes a domain type to wire format.
12    fn serialize(&self, domain: &D) -> AppResult<W>;
13
14    /// Deserializes wire format to domain type.
15    fn deserialize(&self, raw: &W) -> AppResult<D>;
16}
17
18/// JSON translator for `Vec<u8>` ↔ serde-compatible types.
19///
20/// Serializes domain objects to JSON bytes and deserializes them back.
21#[derive(Debug, Clone, Copy, Default)]
22pub struct JsonTranslator;
23
24impl<D> MessageTranslator<Vec<u8>, D> for JsonTranslator
25where
26    D: Serialize + DeserializeOwned + Send + Sync + 'static,
27{
28    fn serialize(&self, domain: &D) -> AppResult<Vec<u8>> {
29        serde_json::to_vec(domain).map_err(|e| {
30            AppError::new(
31                ErrorCode::Internal,
32                format!("JSON serialization failed: {e}"),
33            )
34        })
35    }
36
37    fn deserialize(&self, raw: &Vec<u8>) -> AppResult<D> {
38        serde_json::from_slice(raw).map_err(|e| {
39            AppError::new(
40                ErrorCode::Internal,
41                format!("JSON deserialization failed: {e}"),
42            )
43        })
44    }
45}
46
47/// JSON translator for `String` ↔ serde-compatible types.
48///
49/// Serializes domain objects to JSON strings and deserializes them back.
50#[derive(Debug, Clone, Copy, Default)]
51pub struct JsonStringTranslator;
52
53impl<D> MessageTranslator<String, D> for JsonStringTranslator
54where
55    D: Serialize + DeserializeOwned + Send + Sync + 'static,
56{
57    fn serialize(&self, domain: &D) -> AppResult<String> {
58        serde_json::to_string(domain).map_err(|e| {
59            AppError::new(
60                ErrorCode::Internal,
61                format!("JSON serialization failed: {e}"),
62            )
63        })
64    }
65
66    fn deserialize(&self, raw: &String) -> AppResult<D> {
67        serde_json::from_str(raw).map_err(|e| {
68            AppError::new(
69                ErrorCode::Internal,
70                format!("JSON deserialization failed: {e}"),
71            )
72        })
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use serde::{Deserialize, Serialize};
80
81    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82    struct User {
83        name: String,
84        age: u32,
85    }
86
87    #[test]
88    fn json_translator_round_trip() {
89        let translator = JsonTranslator;
90        let user = User {
91            name: "Alice".into(),
92            age: 30,
93        };
94
95        let bytes: Vec<u8> =
96            MessageTranslator::<Vec<u8>, User>::serialize(&translator, &user).unwrap();
97        let restored: User =
98            MessageTranslator::<Vec<u8>, User>::deserialize(&translator, &bytes).unwrap();
99        assert_eq!(restored, user);
100    }
101
102    #[test]
103    fn json_string_translator_round_trip() {
104        let translator = JsonStringTranslator;
105        let user = User {
106            name: "Bob".into(),
107            age: 25,
108        };
109
110        let json: String =
111            MessageTranslator::<String, User>::serialize(&translator, &user).unwrap();
112        assert!(json.contains("Bob"));
113        let restored: User =
114            MessageTranslator::<String, User>::deserialize(&translator, &json).unwrap();
115        assert_eq!(restored, user);
116    }
117
118    #[test]
119    fn json_translator_bad_input() {
120        let translator = JsonTranslator;
121        let bad = vec![0xFF, 0xFE];
122        let result: AppResult<User> =
123            MessageTranslator::<Vec<u8>, User>::deserialize(&translator, &bad);
124        assert!(result.is_err());
125    }
126}