From b3bf6dcac1a76204585fb81bfe14d850165e9efb Mon Sep 17 00:00:00 2001 From: Lucas Schumacher Date: Mon, 21 Jul 2025 20:58:52 -0400 Subject: [PATCH] Add derive macro support for PopFromNe and PopFromLe --- poppable-derive/src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/poppable-derive/src/lib.rs b/poppable-derive/src/lib.rs index 87fac06..bf4deab 100644 --- a/poppable-derive/src/lib.rs +++ b/poppable-derive/src/lib.rs @@ -5,7 +5,74 @@ use quote::{quote, quote_spanned}; use syn::{spanned::Spanned, DeriveInput}; #[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 + where + Self: Sized, + { + #(#recursive)* + Ok(#struct_ident{ + #(#names),* + }) + } + fn $trait_push_fn(&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 struct_ident = ast.ident; let struct_data: syn::DataStruct = match ast.data { @@ -46,4 +113,4 @@ pub fn pushpop_derive_macro(item: TokenStream) -> TokenStream { } }) .into() -} +}*/