truffle_core/envelope/
codec.rs1use super::{Envelope, EnvelopeError};
8
9pub trait EnvelopeCodec: Send + Sync {
23 fn encode(&self, envelope: &Envelope) -> Result<Vec<u8>, EnvelopeError>;
25
26 fn decode(&self, data: &[u8]) -> Result<Envelope, EnvelopeError>;
28}
29
30#[derive(Debug, Clone, Default)]
39pub struct JsonCodec;
40
41impl EnvelopeCodec for JsonCodec {
42 fn encode(&self, envelope: &Envelope) -> Result<Vec<u8>, EnvelopeError> {
43 serde_json::to_vec(envelope).map_err(EnvelopeError::Serialization)
44 }
45
46 fn decode(&self, data: &[u8]) -> Result<Envelope, EnvelopeError> {
47 serde_json::from_slice(data).map_err(EnvelopeError::Deserialization)
48 }
49}
50
51#[cfg(test)]
56mod tests {
57 use super::*;
58 use serde_json::json;
59
60 #[test]
61 fn test_json_codec_encode_decode_roundtrip() {
62 let codec = JsonCodec;
63
64 let envelope = Envelope::new("chat", "message", json!({"text": "hello world"}));
65 let encoded = codec.encode(&envelope).expect("encode");
66 let decoded = codec.decode(&encoded).expect("decode");
67
68 assert_eq!(decoded.namespace, "chat");
69 assert_eq!(decoded.msg_type, "message");
70 assert_eq!(decoded.payload["text"], "hello world");
71 }
72
73 #[test]
74 fn test_json_codec_preserves_all_fields() {
75 let codec = JsonCodec;
76
77 let envelope = Envelope {
78 namespace: "ft".into(),
79 msg_type: "offer".into(),
80 payload: json!({"file": "data.bin"}),
81 timestamp: Some(1711234567890),
82 from: Some("peer-abc".into()),
83 };
84
85 let encoded = codec.encode(&envelope).expect("encode");
86 let decoded = codec.decode(&encoded).expect("decode");
87
88 assert_eq!(decoded.namespace, "ft");
89 assert_eq!(decoded.msg_type, "offer");
90 assert_eq!(decoded.payload["file"], "data.bin");
91 assert_eq!(decoded.timestamp, Some(1711234567890));
92 assert_eq!(decoded.from.as_deref(), Some("peer-abc"));
93 }
94
95 #[test]
96 fn test_json_codec_unknown_fields_forward_compat() {
97 let codec = JsonCodec;
98
99 let json_bytes = br#"{
101 "namespace": "v2",
102 "msg_type": "new_feature",
103 "payload": {},
104 "priority": "high",
105 "trace_id": "abc-123"
106 }"#;
107
108 let decoded = codec
109 .decode(json_bytes)
110 .expect("should decode with unknown fields");
111 assert_eq!(decoded.namespace, "v2");
112 assert_eq!(decoded.msg_type, "new_feature");
113 }
114
115 #[test]
116 fn test_json_codec_decode_error() {
117 let codec = JsonCodec;
118 let result = codec.decode(b"{{invalid");
119 assert!(result.is_err());
120 }
121
122 #[test]
123 fn test_json_codec_empty_payload() {
124 let codec = JsonCodec;
125
126 let envelope = Envelope::new("ping", "request", json!(null));
127 let encoded = codec.encode(&envelope).expect("encode");
128 let decoded = codec.decode(&encoded).expect("decode");
129
130 assert!(decoded.payload.is_null());
131 }
132
133 #[test]
134 fn test_json_codec_is_send_sync() {
135 fn assert_send_sync<T: Send + Sync>() {}
136 assert_send_sync::<JsonCodec>();
137 }
138
139 #[test]
140 fn test_json_codec_trait_object() {
141 let codec: std::sync::Arc<dyn EnvelopeCodec> = std::sync::Arc::new(JsonCodec);
143 let envelope = Envelope::new("test", "msg", json!("data"));
144 let encoded = codec.encode(&envelope).expect("encode");
145 let decoded = codec.decode(&encoded).expect("decode");
146 assert_eq!(decoded.namespace, "test");
147 }
148}