1use std::fmt;
51
52use serde::Serialize;
53use serde::de::DeserializeOwned;
54
55#[derive(Debug)]
57pub enum CodecError {
58 Encode(Box<dyn std::error::Error + Send + Sync>),
60 Decode(Box<dyn std::error::Error + Send + Sync>),
62}
63
64impl fmt::Display for CodecError {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 match self {
67 CodecError::Encode(e) => write!(f, "encode error: {}", e),
68 CodecError::Decode(e) => write!(f, "decode error: {}", e),
69 }
70 }
71}
72
73impl std::error::Error for CodecError {
74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75 match self {
76 CodecError::Encode(e) => Some(e.as_ref()),
77 CodecError::Decode(e) => Some(e.as_ref()),
78 }
79 }
80}
81
82pub trait MessageCodec: Clone + 'static {
94 fn encode<T: Serialize>(&self, msg: &T) -> Result<Vec<u8>, CodecError>;
100
101 fn decode<T: DeserializeOwned>(&self, buf: &[u8]) -> Result<T, CodecError>;
107}
108
109#[derive(Clone, Default, Debug, Copy)]
133pub struct JsonCodec;
134
135impl MessageCodec for JsonCodec {
136 fn encode<T: Serialize>(&self, msg: &T) -> Result<Vec<u8>, CodecError> {
137 serde_json::to_vec(msg).map_err(|e| CodecError::Encode(Box::new(e)))
138 }
139
140 fn decode<T: DeserializeOwned>(&self, buf: &[u8]) -> Result<T, CodecError> {
141 serde_json::from_slice(buf).map_err(|e| CodecError::Decode(Box::new(e)))
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use serde::{Deserialize, Serialize};
149
150 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
151 struct TestMessage {
152 id: u32,
153 content: String,
154 }
155
156 #[derive(Serialize, Deserialize, Debug, PartialEq)]
157 struct NestedMessage {
158 outer: String,
159 inner: TestMessage,
160 }
161
162 #[test]
163 fn test_json_codec_roundtrip() {
164 let codec = JsonCodec;
165 let msg = TestMessage {
166 id: 42,
167 content: "hello world".to_string(),
168 };
169
170 let bytes = codec.encode(&msg).expect("encode should succeed");
171 let decoded: TestMessage = codec.decode(&bytes).expect("decode should succeed");
172
173 assert_eq!(msg, decoded);
174 }
175
176 #[test]
177 fn test_json_codec_nested() {
178 let codec = JsonCodec;
179 let msg = NestedMessage {
180 outer: "outer".to_string(),
181 inner: TestMessage {
182 id: 1,
183 content: "inner".to_string(),
184 },
185 };
186
187 let bytes = codec.encode(&msg).expect("encode should succeed");
188 let decoded: NestedMessage = codec.decode(&bytes).expect("decode should succeed");
189
190 assert_eq!(msg, decoded);
191 }
192
193 #[test]
194 fn test_json_codec_primitives() {
195 let codec = JsonCodec;
196
197 let s = "test string".to_string();
199 let bytes = codec.encode(&s).expect("encode should succeed");
200 let decoded: String = codec.decode(&bytes).expect("decode should succeed");
201 assert_eq!(s, decoded);
202
203 let n = 12345u64;
205 let bytes = codec.encode(&n).expect("encode should succeed");
206 let decoded: u64 = codec.decode(&bytes).expect("decode should succeed");
207 assert_eq!(n, decoded);
208
209 let v = vec![1, 2, 3, 4, 5];
211 let bytes = codec.encode(&v).expect("encode should succeed");
212 let decoded: Vec<i32> = codec.decode(&bytes).expect("decode should succeed");
213 assert_eq!(v, decoded);
214 }
215
216 #[test]
217 fn test_json_codec_decode_error() {
218 let codec = JsonCodec;
219 let invalid_json = b"not valid json {";
220
221 let result: Result<TestMessage, CodecError> = codec.decode(invalid_json);
222 assert!(result.is_err());
223
224 let err = result.expect_err("decode should have failed");
225 assert!(matches!(err, CodecError::Decode(_)));
226 assert!(err.to_string().contains("decode error"));
227 }
228
229 #[test]
230 fn test_json_codec_type_mismatch() {
231 let codec = JsonCodec;
232 let msg = TestMessage {
233 id: 42,
234 content: "hello".to_string(),
235 };
236
237 let bytes = codec.encode(&msg).expect("encode should succeed");
238
239 let result: Result<String, CodecError> = codec.decode(&bytes);
241 assert!(result.is_err());
242 }
243
244 #[test]
245 fn test_codec_error_display() {
246 let encode_err = CodecError::Encode(Box::new(std::io::Error::other("test encode error")));
247 assert!(encode_err.to_string().contains("encode error"));
248
249 let decode_err = CodecError::Decode(Box::new(std::io::Error::other("test decode error")));
250 assert!(decode_err.to_string().contains("decode error"));
251 }
252
253 #[test]
254 fn test_json_codec_is_clone() {
255 let codec1 = JsonCodec;
256 let codec2 = codec1;
257
258 let msg = TestMessage {
259 id: 1,
260 content: "test".to_string(),
261 };
262
263 let bytes1 = codec1.encode(&msg).expect("encode should succeed");
265 let bytes2 = codec2.encode(&msg).expect("encode should succeed");
266 assert_eq!(bytes1, bytes2);
267 }
268
269 #[test]
270 fn test_json_codec_default() {
271 let codec = JsonCodec;
272 let msg = TestMessage {
273 id: 99,
274 content: "default".to_string(),
275 };
276
277 let bytes = codec.encode(&msg).expect("encode should succeed");
278 let decoded: TestMessage = codec.decode(&bytes).expect("decode should succeed");
279 assert_eq!(msg, decoded);
280 }
281
282 #[test]
283 fn test_json_codec_empty_struct() {
284 #[derive(Serialize, Deserialize, Debug, PartialEq)]
285 struct Empty {}
286
287 let codec = JsonCodec;
288 let msg = Empty {};
289
290 let bytes = codec.encode(&msg).expect("encode should succeed");
291 assert_eq!(&bytes, b"{}");
292
293 let decoded: Empty = codec.decode(&bytes).expect("decode should succeed");
294 assert_eq!(msg, decoded);
295 }
296
297 #[test]
298 fn test_json_codec_option() {
299 let codec = JsonCodec;
300
301 let some_val: Option<i32> = Some(42);
302 let bytes = codec.encode(&some_val).expect("encode should succeed");
303 let decoded: Option<i32> = codec.decode(&bytes).expect("decode should succeed");
304 assert_eq!(some_val, decoded);
305
306 let none_val: Option<i32> = None;
307 let bytes = codec.encode(&none_val).expect("encode should succeed");
308 let decoded: Option<i32> = codec.decode(&bytes).expect("decode should succeed");
309 assert_eq!(none_val, decoded);
310 }
311}