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 CborCodec;
30
31impl<T> Codec<T> for CborCodec
32where
33 T: Serialize + DeserializeOwned,
34{
35 fn encode(&self, value: &T) -> Result<Vec<u8>> {
36 let mut buffer = Vec::new();
37 ciborium::into_writer(value, &mut buffer)
38 .map_err(|error| Error::Codec(error.to_string()))?;
39 Ok(buffer)
40 }
41
42 fn decode(&self, bytes: &[u8]) -> Result<T> {
43 ciborium::from_reader(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_tuple() {
53 let codec = CborCodec;
54 let value = (42u32, true, vec![1u8, 2, 3]);
55 let encoded = codec.encode(&value).expect("encode");
56 let decoded: (u32, bool, Vec<u8>) = codec.decode(&encoded).expect("decode");
57 assert_eq!(decoded, value);
58 }
59
60 #[test]
61 fn decoding_truncated_input_is_a_codec_error() {
62 let codec = CborCodec;
63 let result: Result<(u32, u32)> = codec.decode(&[]);
64 assert!(matches!(result, Err(Error::Codec(_))));
65 }
66}