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