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