Add derive macro support for PopFromNe and PopFromLe

This commit is contained in:
Lucas Schumacher 2025-07-21 20:58:52 -04:00
parent 456ff355ed
commit b3bf6dcac1

View File

@ -5,7 +5,74 @@ use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, DeriveInput}; use syn::{spanned::Spanned, DeriveInput};
#[proc_macro_derive(PushPopParse)] #[proc_macro_derive(PushPopParse)]
pub fn pushpop_derive_macro(item: TokenStream) -> TokenStream { pub fn poppable_derive_macro(item: TokenStream) -> TokenStream {
let mut pop_from_ne = pop_ne_derive_macro(item.clone());
let pop_from_le = pop_le_derive_macro(item.clone());
let pop_from_be = pop_be_derive_macro(item);
pop_from_ne.extend([pop_from_le, pop_from_be]);
pop_from_ne
}
macro_rules! pop_derive_macro {
(
$fn_name:ident,
$trait_name:ident,
$trait_pop_fn:ident,
$trait_push_fn:ident
) => {
#[proc_macro_derive($trait_name)]
pub fn $fn_name(item: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(item).unwrap();
let struct_ident = ast.ident;
let struct_data: syn::DataStruct = match ast.data {
syn::Data::Struct(struct_data) => struct_data,
syn::Data::Enum(_) => panic!("Error: Enum support not implemented"),
syn::Data::Union(_) => panic!("Error: Union support not implemented"),
};
let recursive = struct_data.fields.iter().map(|f| {
let name = &f.ident;
let ty = &f.ty;
quote_spanned!(f.span()=> let #name = <#ty>::$trait_pop_fn(&mut source)?;)
});
let names = struct_data.fields.iter().map(|f| {
let name = &f.ident;
quote_spanned!(f.span()=> #name)
});
let pop = struct_data.fields.iter().map(|f| {
let name = &f.ident;
quote_spanned!(f.span()=> $trait_name::$trait_push_fn(&self.#name, dest)?;)
});
quote!(
impl $trait_name for #struct_ident {
fn $trait_pop_fn(mut source: &mut &[u8]) -> anyhow::Result<Self>
where
Self: Sized,
{
#(#recursive)*
Ok(#struct_ident{
#(#names),*
})
}
fn $trait_push_fn<T: Pushable>(&self, dest: &mut T) -> anyhow::Result<()> {
#(#pop)*
Ok(())
}
})
.into()
}
};
}
pop_derive_macro!(pop_ne_derive_macro, PopFromNE, pop_ne_from, push_ne_into);
pop_derive_macro!(pop_le_derive_macro, PopFromLE, pop_le_from, push_le_into);
pop_derive_macro!(pop_be_derive_macro, PopFromBE, pop_be_from, push_be_into);
/*
#[proc_macro_derive(PopFromNE)]
pub fn pop_ne_derive_macro(item: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(item).unwrap(); let ast: DeriveInput = syn::parse(item).unwrap();
let struct_ident = ast.ident; let struct_ident = ast.ident;
let struct_data: syn::DataStruct = match ast.data { let struct_data: syn::DataStruct = match ast.data {
@ -46,4 +113,4 @@ pub fn pushpop_derive_macro(item: TokenStream) -> TokenStream {
} }
}) })
.into() .into()
} }*/