derive macro

This commit is contained in:
Lucas Schumacher 2024-04-03 23:56:14 -04:00
parent 61b34768e6
commit e283a36945
2 changed files with 72 additions and 7 deletions

View File

@ -1,8 +1,49 @@
use proc_macro::TokenStream; use core::panic;
use syn::DeriveInput;
#[proc_macro_derive(PushPop)] 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 { pub fn pushpop_derive_macro(item: TokenStream) -> TokenStream {
let _ast: DeriveInput = syn::parse(item).unwrap(); let ast: DeriveInput = syn::parse(item).unwrap();
todo!() 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]) -> Result<Self>
where
Self: Sized,
{
#(#recursive)*
Ok(#struct_ident{
#(#names),*
})
}
fn push_ne_into<T: Pushable>(&self, dest: &mut T) -> Result<()> {
#(#pop)*
Ok(())
}
})
.into()
} }

View File

@ -1,6 +1,5 @@
use std::u16;
use anyhow::{Ok, Result}; use anyhow::{Ok, Result};
pub use poppable_derive::PushPopParse;
//pub type BytesRef = AsRef<u8>; //pub type BytesRef = AsRef<u8>;
@ -236,3 +235,28 @@ flt_impl_pop_non_ne!(f32);
core_impl_pop_ne!(f64); core_impl_pop_ne!(f64);
flt_impl_pop_non_ne!(f64); flt_impl_pop_non_ne!(f64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let mut s: &[u8] = &vec![4, 8, 15, 16, 23, 42];
let ans = u8::pop_ne_from(&mut s).unwrap();
assert_eq!(ans, 4);
}
#[test]
fn derive_test() {
#[derive(PushPopParse)]
struct Thing {
a: u8,
b: u8,
}
let mut s: &[u8] = &vec![4, 8, 15, 16, 23, 42];
let thing = Thing::pop_ne_from(&mut s).unwrap();
assert_eq!(thing.a, 4);
assert_eq!(thing.b, 8);
}
}