use crate::packer::Codec;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ReadError {
#[error("not enough bytes: expected {0} but got {1}")]
NotEnoughBytes(usize, usize),
#[error("unconsumed data: {0} bytes left")]
UnconsumedData(usize),
#[error("too much bytes: expected {0} but got {1}")]
SizeTooBig(usize, usize),
#[error("invalid structure: {0}")]
StructureInvalid(String),
#[error("unknown tag: {0}")]
UnknownTag(u32),
#[error("invalid structure: {0}")]
InvalidData(String),
#[error(transparent)]
IoError(#[from] std::io::Error),
}
#[derive(Debug, Error)]
pub enum WriteError {
#[error(transparent)]
IoError(#[from] std::io::Error),
}
pub trait Serialize {
fn serialize<W: std::io::Write>(&self, codec: &mut Codec<W>) -> Result<(), WriteError>;
fn serialized_size(&self) -> usize {
self.serialize_as_vec().unwrap().len()
}
fn serialize_as_vec(&self) -> Result<Vec<u8>, WriteError> {
let mut data = Vec::new();
self.serialize(&mut Codec::new(&mut data))?;
Ok(data)
}
}
impl<T: Serialize> Serialize for &T {
fn serialize<W: std::io::Write>(&self, codec: &mut Codec<W>) -> Result<(), WriteError> {
(*self).serialize(codec)
}
}
pub trait Deserialize: Sized {
fn deserialize<R: std::io::Read>(codec: &mut Codec<R>) -> Result<Self, ReadError>;
fn deserialize_validate<R: std::io::Read>(codec: &mut Codec<R>) -> Result<(), ReadError> {
Self::deserialize(codec).map(|_| ())
}
}
pub trait DeserializeFromSlice: Sized {
fn deserialize_from_slice(codec: &mut Codec<&[u8]>) -> Result<Self, ReadError>;
fn deserialize_validate_from_slice(codec: &mut Codec<&[u8]>) -> Result<(), ReadError> {
Self::deserialize_from_slice(codec).map(|_| ())
}
}
impl<T: Deserialize> DeserializeFromSlice for T {
fn deserialize_from_slice(codec: &mut Codec<&[u8]>) -> Result<Self, ReadError> {
Self::deserialize(codec)
}
}
impl Deserialize for () {
fn deserialize<R: std::io::Read>(_: &mut Codec<R>) -> Result<(), ReadError> {
Ok(())
}
}
impl<const N: usize> Deserialize for [u8; N] {
fn deserialize<R: std::io::Read>(codec: &mut Codec<R>) -> Result<Self, ReadError> {
let mut buf = [0u8; N];
codec.copy_to_slice(&mut buf)?;
Ok(buf)
}
}
impl<const N: usize> Serialize for [u8; N] {
fn serialize<W: std::io::Write>(&self, codec: &mut Codec<W>) -> Result<(), WriteError> {
codec.put_bytes(self)
}
fn serialized_size(&self) -> usize {
std::mem::size_of::<[u8; N]>()
}
}