use bytes::BufMut;
use std::{
fmt,
hash::Hash,
io,
marker::PhantomData,
ops::{Deref, DerefMut},
};
use crate::{
io::{BufMutExt, ParseBuf},
proto::{MyDeserialize, MySerialize},
};
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct RawInt<T: IntRepr>(pub T::Primitive, PhantomData<T>);
impl<T: IntRepr> fmt::Debug for RawInt<T>
where
T::Primitive: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: IntRepr> RawInt<T> {
pub fn new(x: T::Primitive) -> Self {
Self(x, PhantomData)
}
}
impl<T: IntRepr> Deref for RawInt<T> {
type Target = T::Primitive;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: IntRepr> DerefMut for RawInt<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'de, T: IntRepr> MyDeserialize<'de> for RawInt<T> {
const SIZE: Option<usize> = T::SIZE;
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
T::deserialize(buf).map(Self::new)
}
}
impl<T: IntRepr> MySerialize for RawInt<T> {
fn serialize(&self, buf: &mut Vec<u8>) {
T::serialize(self.0, buf);
}
}
pub trait IntRepr {
const SIZE: Option<usize>;
type Primitive: fmt::Debug + Default + Copy + Eq + Ord + Hash;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>);
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive>;
}
impl IntRepr for u8 {
const SIZE: Option<usize> = Some(1);
type Primitive = Self;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
buf.put_u8(val)
}
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
Ok(buf.eat_u8())
}
}
impl IntRepr for i8 {
const SIZE: Option<usize> = Some(1);
type Primitive = Self;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
buf.put_i8(val)
}
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
Ok(buf.eat_i8())
}
}
macro_rules! def_end_repr {
($( $(#[$m:meta])* $name:ident, $t:ty, $size:expr, $ser:ident, $de:ident; )+) => {
$(
$(#[$m])*
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $name;
impl IntRepr for $name {
const SIZE: Option<usize> = $size;
type Primitive = $t;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
buf.$ser(val)
}
fn deserialize<'de>(buf: &mut ParseBuf<'de>) -> io::Result<Self::Primitive> {
Ok(buf.$de())
}
}
)+
};
($( $(#[$m:meta])* checked $name:ident, $t:ty, $size:expr, $ser:ident, $de:ident; )+) => {
$(
$(#[$m])*
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $name;
impl IntRepr for $name {
const SIZE: Option<usize> = $size;
type Primitive = $t;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
buf.$ser(val)
}
fn deserialize<'de>(buf: &mut ParseBuf<'de>) -> io::Result<Self::Primitive> {
buf.$de().ok_or_else(crate::misc::unexpected_buf_eof)
}
}
)+
};
}
def_end_repr! {
LeU16, u16, Some(2), put_u16_le, eat_u16_le;
LeU24, u32, Some(3), put_u24_le, eat_u24_le;
LeU32, u32, Some(4), put_u32_le, eat_u32_le;
LeU48, u64, Some(6), put_u48_le, eat_u48_le;
LeU56, u64, Some(7), put_u56_le, eat_u56_le;
LeU64, u64, Some(8), put_u64_le, eat_u64_le;
LeI16, i16, Some(2), put_i16_le, eat_i16_le;
LeI24, i32, Some(3), put_i24_le, eat_i24_le;
LeI32, i32, Some(4), put_i32_le, eat_i32_le;
LeI56, i64, Some(7), put_i56_le, eat_i56_le;
LeI64, i64, Some(8), put_i64_le, eat_i64_le;
}
def_end_repr! {
checked LenEnc, u64, None, put_lenenc_int, checked_eat_lenenc_int;
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LeU32LowerHalf;
impl IntRepr for LeU32LowerHalf {
const SIZE: Option<usize> = Some(2);
type Primitive = u32;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
LeU16::serialize((val & 0x0000_FFFF) as u16, buf);
}
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
LeU16::deserialize(buf).map(|x| x as u32)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LeU32UpperHalf;
impl IntRepr for LeU32UpperHalf {
const SIZE: Option<usize> = Some(2);
type Primitive = u32;
fn serialize(val: Self::Primitive, buf: &mut Vec<u8>) {
LeU16::serialize((val >> 16) as u16, buf);
}
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
LeU16::deserialize(buf).map(|x| (x as u32) << 16)
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConstU8<T, const N: u8>(PhantomData<T>);
impl<T, const N: u8> ConstU8<T, N> {
pub const fn new() -> Self {
Self(PhantomData)
}
pub const fn value(&self) -> u8 {
N
}
}
impl<'de, T, const N: u8> MyDeserialize<'de> for ConstU8<T, N>
where
T: std::error::Error + Send + Sync + 'static,
T: Default,
{
const SIZE: Option<usize> = Some(1);
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
if buf.eat_u8() == N {
Ok(Self(PhantomData))
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, T::default()))
}
}
}
impl<T, const N: u8> MySerialize for ConstU8<T, N> {
fn serialize(&self, buf: &mut Vec<u8>) {
buf.put_u8(N);
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConstU32<T, const N: u32>(PhantomData<T>);
impl<T, const N: u32> ConstU32<T, N> {
pub fn new() -> Self {
Self(PhantomData)
}
}
impl<'de, T, const N: u32> MyDeserialize<'de> for ConstU32<T, N>
where
T: std::error::Error + Send + Sync + 'static,
T: Default,
{
const SIZE: Option<usize> = Some(4);
type Ctx = ();
fn deserialize((): Self::Ctx, buf: &mut ParseBuf<'de>) -> io::Result<Self> {
if buf.eat_u32_le() == N {
Ok(Self(PhantomData))
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, T::default()))
}
}
}
impl<T, const N: u32> MySerialize for ConstU32<T, N> {
fn serialize(&self, buf: &mut Vec<u8>) {
buf.put_u32_le(N);
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VarLen;
impl IntRepr for VarLen {
const SIZE: Option<usize> = None;
type Primitive = u32;
fn serialize(mut val: Self::Primitive, buf: &mut Vec<u8>) {
loop {
let mut byte = (val & 0x7F) as u8;
val >>= 7;
if val != 0 {
byte |= 0x80;
buf.put_u8(byte);
break;
} else {
buf.put_u8(byte);
}
}
}
fn deserialize(buf: &mut ParseBuf<'_>) -> io::Result<Self::Primitive> {
const MAX_REPR_LEN: usize = 5;
let mut len = 0_u64;
for i in 0..MAX_REPR_LEN {
let byte = *buf.parse::<RawInt<u8>>(())? as u64;
len |= (byte & 0x7f) << (7 * i);
if byte & 0x80 == 0 {
if len > (u32::MAX as u64) {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"invalid variable-length value (> u32::MAX)",
));
}
return Ok(len as u32);
}
}
Err(io::Error::new(
io::ErrorKind::InvalidData,
"invalid variable-length value (more than 5 bytes)",
))
}
}