use std::error::Error;
use std::fmt::{Display, Formatter};
use std::marker::PhantomData;
pub trait PacketLengthSerializer: Send + Sync + 'static {
type Error: Error + Send + Sync;
const SIZE: usize;
fn serialize_packet_length(&self, length: usize) -> Result<Vec<u8>, Self::Error>;
fn deserialize_packet_length(
&self,
buffer: &[u8],
) -> Result<usize, PacketLengthDeserializationError<Self::Error>>;
}
#[derive(Debug, Clone)]
pub enum PacketLengthDeserializationError<E: Error> {
NeedMoreBytes(usize),
Err(E),
}
#[derive(Debug)]
pub struct PacketTooLargeError {
pub max_length: usize,
pub length: usize,
}
impl Display for PacketTooLargeError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"The packet is too large (length: {}, max_length: {})",
self.max_length, self.length
)
}
}
impl Error for PacketTooLargeError {}
#[derive(Default)]
pub struct LittleEndian<N>(PhantomData<N>);
#[derive(Default)]
pub struct BigEndian<N>(PhantomData<N>);
macro_rules! impl_pls {
($typ: ident $(<$generics: tt>)? = $to: ident & $from: ident => $number: ty) => {
impl PacketLengthSerializer for $typ $(<$generics>)? {
type Error = PacketTooLargeError;
const SIZE: usize = <$number>::BITS as usize / 8;
fn serialize_packet_length(&self, length: usize) -> Result<Vec<u8>, Self::Error> {
if length > <$number>::MAX as usize {
Err(PacketTooLargeError {
length,
max_length: <$number>::MAX as usize,
})
} else {
Ok((length as $number).$to().to_vec())
}
}
fn deserialize_packet_length(
&self,
buffer: &[u8],
) -> Result<usize, PacketLengthDeserializationError<Self::Error>> {
Ok(<$number>::$from(buffer.try_into().unwrap()) as usize)
}
}
};
}
macro_rules! impl_plss {
($endianness: ident = $to: ident & $from: ident: $($number: ty),+) => {
$(
impl_pls!($endianness<$number> = $to & $from => $number);
)*
};
}
impl_plss!(
LittleEndian = to_le_bytes & from_le_bytes: u8,
u16,
u32,
u64,
u128
);
impl_plss!(
BigEndian = to_be_bytes & from_be_bytes: u8,
u16,
u32,
u64,
u128
);