use crate::DiagError;
pub trait FrameRead<'a>: Sized {
type Error: core::fmt::Debug;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error>;
}
mod sealed {
pub trait Sealed {}
}
pub trait Writer: sealed::Sealed {
fn write_bytes(&mut self, data: &[u8]) -> Result<(), DiagError>;
}
impl sealed::Sealed for &mut [u8] {}
impl Writer for &mut [u8] {
fn write_bytes(&mut self, data: &[u8]) -> Result<(), DiagError> {
if self.len() < data.len() {
return Err(DiagError::BufferOverflow);
}
self[..data.len()].copy_from_slice(data);
let tmp = core::mem::take(self);
*self = &mut tmp[data.len()..];
Ok(())
}
}
#[cfg(feature = "alloc")]
impl sealed::Sealed for bytes::BytesMut {}
#[cfg(feature = "alloc")]
impl Writer for bytes::BytesMut {
fn write_bytes(&mut self, data: &[u8]) -> Result<(), DiagError> {
self.extend_from_slice(data);
Ok(())
}
}
pub trait FrameWrite {
type Error: core::fmt::Debug;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error>;
}
pub trait FrameCodec<'a>: FrameRead<'a, Error = <Self as FrameWrite>::Error> + FrameWrite {}
impl<'a, T> FrameCodec<'a> for T
where
T: FrameRead<'a> + FrameWrite,
T: FrameRead<'a, Error = <T as FrameWrite>::Error>,
{
}
impl<'a> FrameRead<'a> for u8 {
type Error = DiagError;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
let val = buf.first().copied().ok_or(DiagError::LengthMismatch {
expected: 1,
actual: 0,
})?;
*buf = &buf[1..];
Ok(val)
}
}
impl<'a> FrameRead<'a> for u16 {
type Error = DiagError;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
if buf.len() < 2 {
return Err(DiagError::LengthMismatch {
expected: 2,
actual: buf.len(),
});
}
let val = u16::from_be_bytes([buf[0], buf[1]]);
*buf = &buf[2..];
Ok(val)
}
}
impl<'a> FrameRead<'a> for u32 {
type Error = DiagError;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
if buf.len() < 4 {
return Err(DiagError::LengthMismatch {
expected: 4,
actual: buf.len(),
});
}
let val = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
*buf = &buf[4..];
Ok(val)
}
}
impl<'a, const N: usize> FrameRead<'a> for [u8; N] {
type Error = DiagError;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
if buf.len() < N {
return Err(DiagError::LengthMismatch {
expected: N,
actual: buf.len(),
});
}
let mut arr = [0u8; N];
arr.copy_from_slice(&buf[..N]);
*buf = &buf[N..];
Ok(arr)
}
}
impl<'a> FrameRead<'a> for &'a [u8] {
type Error = DiagError;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
let slice = *buf;
*buf = &buf[buf.len()..];
Ok(slice)
}
}
impl<'a, T> FrameRead<'a> for Option<T>
where
T: FrameRead<'a>,
{
type Error = T::Error;
fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
if buf.is_empty() {
Ok(None)
} else {
Ok(Some(T::decode(buf)?))
}
}
}
impl FrameWrite for u8 {
type Error = DiagError;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
buf.write_bytes(&[*self])
}
}
impl FrameWrite for u16 {
type Error = DiagError;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
buf.write_bytes(&self.to_be_bytes())
}
}
impl FrameWrite for u32 {
type Error = DiagError;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
buf.write_bytes(&self.to_be_bytes())
}
}
impl<const N: usize> FrameWrite for [u8; N] {
type Error = DiagError;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
buf.write_bytes(self.as_ref())
}
}
impl FrameWrite for &[u8] {
type Error = DiagError;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
buf.write_bytes(self)
}
}
impl<T: FrameWrite> FrameWrite for Option<T> {
type Error = T::Error;
fn encode<W: Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
if let Some(inner) = self {
inner.encode(buf)?;
}
Ok(())
}
}
pub fn take_n<'a>(buf: &mut &'a [u8], n: usize) -> Result<&'a [u8], DiagError> {
if buf.len() < n {
return Err(DiagError::LengthMismatch {
expected: n,
actual: buf.len(),
});
}
let slice = &buf[..n];
*buf = &buf[n..];
Ok(slice)
}