Use macro rules for impls

This commit is contained in:
Lucas Schumacher 2024-04-02 22:28:34 -04:00
parent 51666b629c
commit 61b34768e6

View File

@ -72,11 +72,7 @@ pub trait PopFromNE {
// //
// Impl PopFromNE, PopFromLE, PopFromBE for core primitive types // Impl PopFromNE, PopFromLE, PopFromBE for core primitive types
// TODO: Create macro(s) for impls. Most of these impls are the same except for the the type name.
// TODO: Impl for u128 and i128
// TODO: Impl for usize and isize
// //
impl PopFromNE for u8 { impl PopFromNE for u8 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self> fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where where
@ -113,7 +109,8 @@ impl PopFromBE for u8 {
where where
Self: Sized, Self: Sized,
{ {
u8::pop_ne_from(source) let x = u8::from_be(u8::pop_ne_from(source)?);
Ok(x)
} }
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
@ -121,423 +118,121 @@ impl PopFromBE for u8 {
} }
} }
// Impls for u16 macro_rules! core_impl_pop_ne {
impl PopFromNE for u16 { ($int_type: ident) => {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self> impl PopFromNE for $int_type {
where fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
Self: Sized, where
{ Self: Sized,
const SIZE: usize = std::mem::size_of::<u16>(); {
if source.len() < SIZE { const SIZE: usize = std::mem::size_of::<$int_type>();
anyhow::bail!("Buffer too small to pop u16"); if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop {}", stringify!($int_type));
}
let value = $int_type::from_ne_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
} }
let value = u16::from_be_bytes(source[..SIZE].try_into()?); };
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
} }
impl PopFromLE for u16 { macro_rules! int_impl_pop_non_ne {
fn pop_le_from(source: &mut &[u8]) -> Result<Self> ($int_type: ident) => {
where impl PopFromLE for $int_type {
Self: Sized, fn pop_le_from(source: &mut &[u8]) -> Result<Self>
{ where
Ok(Self::from_le(Self::pop_ne_from(source)?)) Self: Sized,
} {
Ok(Self::from_le(Self::pop_ne_from(source)?))
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_le_bytes()) dest.push_slice(&self.to_le_bytes())
} }
}
impl PopFromBE for u16 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
//Impls for u32
impl PopFromNE for u32 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<u32>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop u32");
} }
let value = u32::from_be_bytes(source[..SIZE].try_into()?); impl PopFromBE for $int_type {
*source = &source[SIZE..]; fn pop_be_from(source: &mut &[u8]) -> Result<Self>
Ok(value) where
} Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes()) dest.push_slice(&self.to_be_bytes())
} }
}
impl PopFromLE for u32 {
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_le(Self::pop_ne_from(source)?))
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_le_bytes())
}
}
impl PopFromBE for u32 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
//Impls for u64
impl PopFromNE for u64 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<u64>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop u64");
} }
let value = u64::from_be_bytes(source[..SIZE].try_into()?); };
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
} }
impl PopFromLE for u64 { macro_rules! flt_impl_pop_non_ne {
fn pop_le_from(source: &mut &[u8]) -> Result<Self> ($flt_type: ident) => {
where impl PopFromLE for $flt_type {
Self: Sized, fn pop_le_from(source: &mut &[u8]) -> Result<Self>
{ where
Ok(Self::from_le(Self::pop_ne_from(source)?)) Self: Sized,
} {
const SIZE: usize = std::mem::size_of::<$flt_type>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop $flt_type");
}
let value = $flt_type::from_le_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_le_bytes()) dest.push_slice(&self.to_le_bytes())
} }
}
impl PopFromBE for u64 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
impl PopFromNE for i8 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<i8>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop i8");
} }
impl PopFromBE for $flt_type {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<$flt_type>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop $flt_type");
}
let value = $flt_type::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
let value = source[0] as i8; fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
*source = &source[SIZE..]; dest.push_slice(&self.to_be_bytes())
Ok(value) }
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_u8(&(*self as u8))
}
}
impl PopFromLE for i8 {
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
i8::pop_ne_from(source)
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
self.push_ne_into(dest)
}
}
impl PopFromBE for i8 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
i8::pop_ne_from(source)
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
self.push_ne_into(dest)
}
}
impl PopFromNE for i16 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<i16>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop i16");
} }
};
let value = i16::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
}
impl PopFromNE for i32 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<i32>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop i32");
}
let value = i32::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
}
impl PopFromNE for i64 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<i64>();
if source.len() < SIZE {
anyhow::bail!("Buffer too small to pop i64");
}
let value = i64::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
} }
impl PopFromLE for i16 { core_impl_pop_ne!(u16);
fn pop_le_from(source: &mut &[u8]) -> Result<Self> core_impl_pop_ne!(u32);
where core_impl_pop_ne!(u64);
Self: Sized, core_impl_pop_ne!(u128);
{ core_impl_pop_ne!(usize);
Ok(Self::from_le(Self::pop_ne_from(source)?)) core_impl_pop_ne!(i16);
} core_impl_pop_ne!(i32);
core_impl_pop_ne!(i64);
core_impl_pop_ne!(i128);
core_impl_pop_ne!(isize);
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { int_impl_pop_non_ne!(u16);
dest.push_slice(&self.to_le_bytes()) int_impl_pop_non_ne!(u32);
} int_impl_pop_non_ne!(u64);
} int_impl_pop_non_ne!(u128);
impl PopFromLE for i32 { int_impl_pop_non_ne!(usize);
fn pop_le_from(source: &mut &[u8]) -> Result<Self> int_impl_pop_non_ne!(i16);
where int_impl_pop_non_ne!(i32);
Self: Sized, int_impl_pop_non_ne!(i64);
{ int_impl_pop_non_ne!(i128);
Ok(Self::from_le(Self::pop_ne_from(source)?)) int_impl_pop_non_ne!(isize);
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { core_impl_pop_ne!(f32);
dest.push_slice(&self.to_le_bytes()) flt_impl_pop_non_ne!(f32);
}
}
impl PopFromLE for i64 {
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_le(Self::pop_ne_from(source)?))
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> { core_impl_pop_ne!(f64);
dest.push_slice(&self.to_le_bytes()) flt_impl_pop_non_ne!(f64);
}
}
impl PopFromBE for i16 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
impl PopFromBE for i32 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
impl PopFromBE for i64 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
Ok(Self::from_be(Self::pop_ne_from(source)?))
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
//
// Floating Point
//
impl PopFromNE for f32 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f32>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f32");
}
let value = f32::from_ne_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
}
impl PopFromLE for f32 {
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f32>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f32");
}
let value = f32::from_le_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_le_bytes())
}
}
impl PopFromBE for f32 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f32>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f32");
}
let value = f32::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}
impl PopFromNE for f64 {
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f64>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f64");
}
let value = f64::from_ne_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_ne_bytes())
}
}
impl PopFromLE for f64 {
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f64>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f64");
}
let value = f64::from_le_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_le_bytes())
}
}
impl PopFromBE for f64 {
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
where
Self: Sized,
{
const SIZE: usize = std::mem::size_of::<f64>();
if source.len() < SIZE {
anyhow::bail!("Buffer to small to pop f64");
}
let value = f64::from_be_bytes(source[..SIZE].try_into()?);
*source = &source[SIZE..];
Ok(value)
}
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
dest.push_slice(&self.to_be_bytes())
}
}