from_repr

This commit is contained in:
2024-06-10 14:28:36 -04:00
parent a474488585
commit 4c0f94bd48
3 changed files with 79 additions and 4 deletions

View File

@@ -0,0 +1,64 @@
use proc_macro::{TokenStream};
const VALID: &[&'static str] = &[
"u8", "u16", "u32", "u64", "u128",
"i8", "i16", "i32", "i64", "i128",
];
pub fn derive_from_repr(input: TokenStream) -> TokenStream {
let syn::DeriveInput { attrs, ident, data, .. } = syn::parse_macro_input!(input);
let edata = match data {
syn::Data::Enum(edata) => edata,
_invalid => return TokenStream::from(quote::quote! { compile_error!("The identifier should not be empty"); }),
};
let repr_type = attrs.iter()
.filter_map(|attribute| {
// verify it is a repr type
attribute.path().get_ident()?
.to_string().eq("repr")
.then_some(())?;
let mut repr_type: Option<syn::Path> = None;
let _ = attribute.parse_nested_meta(|meta| {
for &v in VALID {
if meta.path.is_ident(v) {
repr_type = Some(meta.path);
return Ok(())
}
}
Err(meta.error("unrecognized repr"))
});
repr_type
}).next();
let repr = match repr_type {
Some(repr) => repr,
None => {
return TokenStream::from(quote::quote! {
compile_error!("PrimitiveEnum requires the #[repr(u/i*)] attribute");
})
}
};
let values = edata.variants.iter().filter_map(|variant| {
if let Some((_, desc)) = &variant.discriminant {
let variant = &variant.ident;
Some(quote::quote! {
#desc => Some(Self::#variant),
})
} else { None }
});
let name = &ident;
TokenStream::from(quote::quote! {
impl eset::FromRepr for #name {
type Repr = #repr;
fn from_repr(repr: #repr) -> Option<Self> {
match repr {
#(#values)*
_ => None
}
}
}
})
}

View File

@@ -5,8 +5,14 @@
use proc_macro::*; use proc_macro::*;
mod sigscan; mod sigscan;
mod from_repr;
#[proc_macro] #[proc_macro]
pub fn signature(input: TokenStream) -> TokenStream { pub fn signature(input: TokenStream) -> TokenStream {
sigscan::macro_proc(input) sigscan::macro_proc(input)
}
#[proc_macro_derive(FromRepr)]
pub fn derive_from_repr(input: TokenStream) -> TokenStream {
from_repr::derive_from_repr(input)
} }

View File

@@ -32,9 +32,6 @@ pub mod win32;
#[cfg(feature = "win32")] #[cfg(feature = "win32")]
pub use win32::{ image_base, image_header, find_kernel32, process_executable }; pub use win32::{ image_base, image_header, find_kernel32, process_executable };
/// re-export the signature macro
pub use xgen::signature;
mod time; mod time;
pub use time::dur; pub use time::dur;
@@ -45,4 +42,12 @@ mod strings;
pub use strings::*; pub use strings::*;
mod iter_tools; mod iter_tools;
pub use iter_tools::*; pub use iter_tools::*;
/// re-export the signature macro
pub use xgen::signature;
pub use xgen::FromRepr;
pub trait FromRepr: Sized {
type Repr;
fn from_repr(repr: Self::Repr) -> Option<Self>;
}