use core::marker::PhantomData;
use serde::{
de::DeserializeOwned,
Serialize,
};
use embrio_core::io::{
Read,
Write,
};
use async_codec::{
Decode,
DecodeResult,
Encode,
EncodeResult,
Framed,
};
pub struct PostCardCodec<T> {
_ph: PhantomData<T>,
}
impl<T> Default for PostCardCodec<T> {
fn default() -> Self {
Self {
_ph: Default::default(),
}
}
}
impl<T> PostCardCodec<T>
where
T: DeserializeOwned,
{
pub fn stream<S: Read, B: Default + AsRef<[u8]> + AsMut<[u8]>>(
stream: S,
) -> Framed<S, Self, B> {
Framed::new(stream, Self::default(), B::default())
}
}
impl<T> PostCardCodec<T> {
pub fn framed<S, B: Default + AsRef<[u8]> + AsMut<[u8]>>(stream: S) -> Framed<S, Self, B> {
Framed::new(stream, Self::default(), B::default())
}
}
impl<T> PostCardCodec<T>
where
T: Serialize,
{
pub fn sink<S: Write, B: Default + AsRef<[u8]> + AsMut<[u8]>>(stream: S) -> Framed<S, Self, B> {
Framed::new(stream, Self::default(), B::default())
}
}
impl<T> Encode for PostCardCodec<T>
where
T: Serialize,
{
type Item = T;
type Error = postcard::Error;
fn encode(&mut self, item: &T, buf: &mut [u8]) -> EncodeResult<Self::Error> {
match postcard::to_slice_cobs(item, buf) {
Ok(buf) => Ok(buf.len()).into(),
Err(postcard::Error::SerializeBufferFull) => EncodeResult::Overflow(0),
Err(e) => Err(e).into(),
}
}
}
impl<T> Decode for PostCardCodec<T>
where
T: DeserializeOwned,
{
type Item = T;
type Error = postcard::Error;
fn decode(&mut self, buf: &mut [u8]) -> (usize, DecodeResult<T, postcard::Error>) {
let end = match buf.iter().position(|b| *b == 0x00) {
Some(pos) => pos + 1,
None => return (0, DecodeResult::UnexpectedEnd),
};
(end, postcard::from_bytes_cobs(&mut buf[..end]).into())
}
}