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.decode(json_bytes).expect("should decode with unknown fields");
109 assert_eq!(decoded.namespace, "v2");
110 assert_eq!(decoded.msg_type, "new_feature");
111 }
112
113 #[test]
114 fn test_json_codec_decode_error() {
115 let codec = JsonCodec;
116 let result = codec.decode(b"{{invalid");
117 assert!(result.is_err());
118 }
119
120 #[test]
121 fn test_json_codec_empty_payload() {
122 let codec = JsonCodec;
123
124 let envelope = Envelope::new("ping", "request", json!(null));
125 let encoded = codec.encode(&envelope).expect("encode");
126 let decoded = codec.decode(&encoded).expect("decode");
127
128 assert!(decoded.payload.is_null());
129 }
130
131 #[test]
132 fn test_json_codec_is_send_sync() {
133 fn assert_send_sync<T: Send + Sync>() {}
134 assert_send_sync::<JsonCodec>();
135 }
136
137 #[test]
138 fn test_json_codec_trait_object() {
139 let codec: std::sync::Arc<dyn EnvelopeCodec> = std::sync::Arc::new(JsonCodec);
141 let envelope = Envelope::new("test", "msg", json!("data"));
142 let encoded = codec.encode(&envelope).expect("encode");
143 let decoded = codec.decode(&encoded).expect("decode");
144 assert_eq!(decoded.namespace, "test");
145 }
146}