50 lines
1.5 KiB
Rust
50 lines
1.5 KiB
Rust
use core::panic;
|
|
|
|
use proc_macro::TokenStream;
|
|
use quote::{quote, quote_spanned};
|
|
use syn::{spanned::Spanned, DeriveInput};
|
|
|
|
#[proc_macro_derive(PushPopParse)]
|
|
pub fn pushpop_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 {
|
|
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>::pop_ne_from(&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()=> PopFromNE::push_ne_into(&self.#name, dest)?;)
|
|
});
|
|
|
|
quote!(
|
|
impl PopFromNE for #struct_ident {
|
|
fn pop_ne_from(mut source: &mut &[u8]) -> anyhow::Result<Self>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
#(#recursive)*
|
|
Ok(#struct_ident{
|
|
#(#names),*
|
|
})
|
|
}
|
|
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> anyhow::Result<()> {
|
|
#(#pop)*
|
|
Ok(())
|
|
}
|
|
})
|
|
.into()
|
|
}
|