1use serde::de::DeserializeOwned;
4use serde::Serialize;
5
6use pamoja_core::{Error, Result};
7
8use crate::Codec;
9
10#[derive(Clone, Copy, Debug, Default)]
29pub struct JsonCodec;
30
31impl<T> Codec<T> for JsonCodec
32where
33 T: Serialize + DeserializeOwned,
34{
35 fn encode(&self, value: &T) -> Result<Vec<u8>> {
36 serde_json::to_vec(value).map_err(|error| Error::Codec(error.to_string()))
37 }
38
39 fn decode(&self, bytes: &[u8]) -> Result<T> {
40 serde_json::from_slice(bytes).map_err(|error| Error::Codec(error.to_string()))
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn round_trips_a_map() {
50 use std::collections::BTreeMap;
51
52 let codec = JsonCodec;
53 let mut value = BTreeMap::new();
54 value.insert("sensor".to_owned(), 21i64);
55 let encoded = codec.encode(&value).expect("encode");
56 let decoded: BTreeMap<String, i64> = codec.decode(&encoded).expect("decode");
57 assert_eq!(decoded, value);
58 }
59
60 #[test]
61 fn decoding_invalid_json_is_a_codec_error() {
62 let codec = JsonCodec;
63 let result: Result<Vec<i32>> = codec.decode(b"not json");
64 assert!(matches!(result, Err(Error::Codec(_))));
65 }
66}