first commit
This commit is contained in:
commit
51666b629c
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
workspace = { members = ["poppable-derive"] }
|
||||
[package]
|
||||
name = "poppable"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
poppable-derive = { path = "poppable-derive"}
|
||||
13
poppable-derive/Cargo.toml
Normal file
13
poppable-derive/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "poppable-derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.35"
|
||||
syn = "2.0.57"
|
||||
|
||||
[lib]
|
||||
proc_macro = true
|
||||
8
poppable-derive/src/lib.rs
Normal file
8
poppable-derive/src/lib.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use proc_macro::TokenStream;
|
||||
use syn::DeriveInput;
|
||||
|
||||
#[proc_macro_derive(PushPop)]
|
||||
pub fn pushpop_derive_macro(item: TokenStream) -> TokenStream {
|
||||
let _ast: DeriveInput = syn::parse(item).unwrap();
|
||||
todo!()
|
||||
}
|
||||
543
src/lib.rs
Normal file
543
src/lib.rs
Normal file
@ -0,0 +1,543 @@
|
||||
use std::u16;
|
||||
|
||||
use anyhow::{Ok, Result};
|
||||
|
||||
//pub type BytesRef = AsRef<u8>;
|
||||
|
||||
pub trait Pushable {
|
||||
fn push_u8(&mut self, byte: &u8) -> Result<()>;
|
||||
fn push_vec(&mut self, bytes: Vec<u8>) -> Result<()>;
|
||||
fn push_slice(&mut self, bytes: &[u8]) -> Result<()>;
|
||||
}
|
||||
impl Pushable for Vec<u8> {
|
||||
fn push_u8(&mut self, byte: &u8) -> Result<()> {
|
||||
// TODO: push can panic. Return Err instead of panicing.
|
||||
self.push(byte.to_owned());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_vec(&mut self, mut bytes: Vec<u8>) -> Result<()> {
|
||||
// TODO: append can panic. Return Err instead of panicing.
|
||||
self.append(&mut bytes);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn push_slice(&mut self, bytes: &[u8]) -> Result<()> {
|
||||
// TODO: extend can also panic. Return Err instead of panicing.
|
||||
// https://doc.rust-lang.org/src/alloc/vec/mod.rs.html#2970 rustdoc 1.77.1 (7cf61ebde 2024-03-27)
|
||||
// http://web.archive.org/web/20240324062202/doc.rust-lang.org/src/alloc/vec/mod.rs.html#2970
|
||||
self.extend(bytes);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Poppable {
|
||||
fn try_pop_be<T: PopFromBE>(&mut self) -> Result<T>;
|
||||
fn try_pop_le<T: PopFromLE>(&mut self) -> Result<T>;
|
||||
fn try_pop_ne<T: PopFromNE>(&mut self) -> Result<T>;
|
||||
}
|
||||
impl Poppable for &[u8] {
|
||||
fn try_pop_be<T: PopFromBE>(&mut self) -> Result<T> {
|
||||
Ok(T::pop_be_from(self)?)
|
||||
}
|
||||
|
||||
fn try_pop_le<T: PopFromLE>(&mut self) -> Result<T> {
|
||||
Ok(T::pop_le_from(self)?)
|
||||
}
|
||||
|
||||
fn try_pop_ne<T: PopFromNE>(&mut self) -> Result<T> {
|
||||
Ok(T::pop_ne_from(self)?)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PopFromBE {
|
||||
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()>;
|
||||
}
|
||||
pub trait PopFromLE {
|
||||
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait PopFromNE {
|
||||
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()>;
|
||||
}
|
||||
|
||||
//
|
||||
// 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 {
|
||||
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
const SIZE: usize = std::mem::size_of::<u8>();
|
||||
if source.len() < SIZE {
|
||||
anyhow::bail!("Buffer too small to pop u8");
|
||||
}
|
||||
|
||||
let value = source[0];
|
||||
*source = &source[SIZE..];
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
|
||||
dest.push_u8(self)
|
||||
}
|
||||
}
|
||||
impl PopFromLE for u8 {
|
||||
fn pop_le_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
u8::pop_ne_from(source)
|
||||
}
|
||||
|
||||
fn push_le_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
|
||||
dest.push_u8(self)
|
||||
}
|
||||
}
|
||||
impl PopFromBE for u8 {
|
||||
fn pop_be_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
u8::pop_ne_from(source)
|
||||
}
|
||||
|
||||
fn push_be_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
|
||||
dest.push_u8(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Impls for u16
|
||||
impl PopFromNE for u16 {
|
||||
fn pop_ne_from(source: &mut &[u8]) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
const SIZE: usize = std::mem::size_of::<u16>();
|
||||
if source.len() < SIZE {
|
||||
anyhow::bail!("Buffer too small to pop u16");
|
||||
}
|
||||
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 {
|
||||
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 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()?);
|
||||
*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 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 {
|
||||
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 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");
|
||||
}
|
||||
|
||||
let value = source[0] as i8;
|
||||
*source = &source[SIZE..];
|
||||
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 {
|
||||
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 PopFromLE for i32 {
|
||||
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 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<()> {
|
||||
dest.push_slice(&self.to_le_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user