use crate::{Codec, CodecFor};
use core::result::Result;
pub struct PostcardCodec;
impl Codec for PostcardCodec {
type Error = postcard::Error;
}
impl<T> CodecFor<T> for PostcardCodec
where
T: serde::Serialize + serde::de::DeserializeOwned,
{
type Decoded<'buf>
= T
where
T: 'buf;
fn encode(msg: &T, buf: &mut [u8]) -> Result<usize, postcard::Error> {
let cap = buf.len();
let written = postcard::to_slice(msg, buf).inspect_err(|e| {
consortium_log::trace!("postcard encode failed into {}-byte buffer: {}", cap, e);
})?;
Ok(written.len())
}
fn decode<'buf>(buf: &'buf [u8]) -> Result<Self::Decoded<'buf>, postcard::Error>
where
T: 'buf,
{
postcard::from_bytes(buf).inspect_err(|e| {
consortium_log::trace!("postcard decode failed on {} bytes: {}", buf.len(), e);
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, PartialEq, Serialize)]
struct Message {
sequence: u32,
ready: bool,
}
#[test]
fn round_trips_owned_message() {
let msg = Message {
sequence: 42,
ready: true,
};
let mut buf = [0u8; 16];
let len = PostcardCodec::encode(&msg, &mut buf).expect("encode should fit");
let decoded = <PostcardCodec as CodecFor<Message>>::decode(&buf[..len])
.expect("decode should succeed");
assert_eq!(decoded, msg);
}
#[test]
fn rejects_buffer_that_is_too_small() {
let msg = Message {
sequence: u32::MAX,
ready: true,
};
let mut buf = [0u8; 1];
assert!(PostcardCodec::encode(&msg, &mut buf).is_err());
}
#[test]
fn rejects_truncated_message() {
let buf = [42u8];
assert!(<PostcardCodec as CodecFor<Message>>::decode(&buf).is_err());
}
}