1#![doc = include_str!("../README.md")]
2#![no_std]
3
4extern crate alloc;
5
6use airbender_core::wire::FramedRead;
7use alloc::vec::Vec;
8use core::fmt;
9
10#[cfg(test)]
11extern crate std;
12
13pub const AIRBENDER_CODEC_V0: u32 = 0;
15
16pub trait AirbenderCodec {
18 const VERSION: u32;
20
21 fn encode<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, CodecError>;
23
24 fn decode<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T, CodecError>;
26}
27
28pub struct AirbenderCodecV0;
30
31impl AirbenderCodec for AirbenderCodecV0 {
32 const VERSION: u32 = AIRBENDER_CODEC_V0;
33
34 fn encode<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, CodecError> {
35 bincode::serde::encode_to_vec(value, bincode::config::standard())
36 .map_err(CodecError::Encode)
37 }
38
39 fn decode<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T, CodecError> {
40 let (decoded, read_len) =
41 bincode::serde::decode_from_slice(bytes, bincode::config::standard())
42 .map_err(CodecError::Decode)?;
43 if read_len != bytes.len() {
44 return Err(CodecError::TrailingBytes {
45 expected: bytes.len(),
46 read: read_len,
47 });
48 }
49 Ok(decoded)
50 }
51}
52
53struct FramedBincodeReader<'a, R: FramedRead>(&'a mut R);
57
58impl<R: FramedRead> bincode::de::read::Reader for FramedBincodeReader<'_, R> {
59 fn read(&mut self, bytes: &mut [u8]) -> Result<(), bincode::error::DecodeError> {
60 self.0
61 .read(bytes)
62 .map_err(|end| bincode::error::DecodeError::UnexpectedEnd {
63 additional: end.shortfall,
64 })
65 }
66}
67
68impl AirbenderCodecV0 {
69 pub fn decode_from_reader<T, R>(reader: &mut R) -> Result<T, CodecError>
86 where
87 T: serde::de::DeserializeOwned,
88 R: FramedRead,
89 {
90 bincode::serde::decode_from_reader(FramedBincodeReader(reader), bincode::config::standard())
91 .map_err(CodecError::Decode)
92 }
93}
94
95#[derive(Debug)]
96pub enum CodecError {
97 Encode(bincode::error::EncodeError),
98 Decode(bincode::error::DecodeError),
99 TrailingBytes { expected: usize, read: usize },
100}
101
102impl fmt::Display for CodecError {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match self {
105 CodecError::Encode(_) => f.write_str("failed to encode value"),
106 CodecError::Decode(_) => f.write_str("failed to decode value"),
107 CodecError::TrailingBytes { expected, read } => {
108 write!(f, "decoded {read} bytes but expected {expected}")
109 }
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117 use alloc::vec;
118
119 #[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
120 struct Sample {
121 value: u32,
122 payload: alloc::vec::Vec<u8>,
123 }
124
125 #[test]
126 fn codec_roundtrip() {
127 let sample = Sample {
128 value: 42,
129 payload: vec![1u8, 2, 3, 4, 5],
130 };
131 let encoded = AirbenderCodecV0::encode(&sample).expect("encode");
132 let decoded: Sample = AirbenderCodecV0::decode(&encoded).expect("decode");
133 assert_eq!(decoded, sample);
134 }
135}