Start stdin
This commit is contained in:
@@ -10,3 +10,4 @@ proc-macro = true
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2", features = ["full"] }
|
||||
zyn = "0.5"
|
||||
|
||||
@@ -1,27 +1,44 @@
|
||||
use core::iter::Iterator;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{Meta, parse_macro_input, spanned::Spanned};
|
||||
use syn::{Meta, spanned::Spanned};
|
||||
use zyn::zyn;
|
||||
|
||||
#[proc_macro_derive(VolatilePackedStruct, attributes(read_only))]
|
||||
pub fn derive_volatile_packed_struct(item: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(item as syn::DeriveInput);
|
||||
#[zyn::element(debug)]
|
||||
fn struct_getter(field: syn::Field) -> zyn::TokenStream {
|
||||
let field_name = field.ident.as_ref().unwrap();
|
||||
|
||||
zyn! {
|
||||
pub fn {{ field_name | ident:"get_{}" }}(self: *const Self) -> {{ field.ty }} {
|
||||
unsafe {
|
||||
(&raw const (*self).{{ field_name }}).read_volatile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[zyn::element]
|
||||
fn struct_setter(field: syn::Field) -> zyn::TokenStream {
|
||||
let field_name = field.ident.as_ref().unwrap();
|
||||
|
||||
zyn! {
|
||||
pub fn {{ field_name | ident:"set_{}" }}(self: *mut Self, value: {{ field.ty }}) {
|
||||
unsafe {
|
||||
(&raw mut (*self).{{ field_name }}).write_volatile(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[zyn::derive("VolatilePackedStruct", attributes(read_only), debug)]
|
||||
pub fn derive_volatile_packed_struct(#[zyn(input)] input: syn::DeriveInput) -> TokenStream {
|
||||
if !input.attrs.iter().any(|attr| match &attr.meta {
|
||||
Meta::List(list) => list.path.segments.last().is_some_and(|s| s.ident == "repr"),
|
||||
_ => false,
|
||||
}) {
|
||||
return syn::Error::new(
|
||||
input.span(),
|
||||
"Item should use a #[repr(packed)] representation",
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
bail!("Item should use a #[repr(packed)] representation");
|
||||
}
|
||||
|
||||
let fields = match input.data {
|
||||
syn::Data::Struct(data_struct) => match data_struct.fields {
|
||||
let fields = match &input.data {
|
||||
syn::Data::Struct(data_struct) => match &data_struct.fields {
|
||||
syn::Fields::Named(fields_named) => fields_named,
|
||||
syn::Fields::Unnamed(_) | syn::Fields::Unit => unimplemented!(),
|
||||
},
|
||||
@@ -29,42 +46,16 @@ pub fn derive_volatile_packed_struct(item: TokenStream) -> TokenStream {
|
||||
syn::Data::Union(_) => unimplemented!(),
|
||||
};
|
||||
|
||||
let mut getters = Vec::new();
|
||||
let mut setters = Vec::new();
|
||||
|
||||
for field in fields.named {
|
||||
let field_name = field.ident.unwrap();
|
||||
if field_name.to_string().starts_with("_") {
|
||||
continue;
|
||||
}
|
||||
let ty = field.ty;
|
||||
let getter_name = format_ident!("get_{}", field_name);
|
||||
let setter_name = format_ident!("set_{}", field_name);
|
||||
|
||||
getters.push(quote! {
|
||||
pub fn #getter_name(self: *const Self) -> #ty {
|
||||
unsafe {
|
||||
(&raw const (*self).#field_name).read_volatile()
|
||||
}
|
||||
}
|
||||
});
|
||||
setters.push(quote! {
|
||||
pub fn #setter_name(self: *mut Self, value: #ty) {
|
||||
unsafe {
|
||||
(&raw mut (*self).#field_name).write_volatile(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let struct_path = input.ident;
|
||||
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
quote! {
|
||||
impl #impl_generics #struct_path #type_generics #where_clause {
|
||||
#(#getters)*
|
||||
#(#setters)*
|
||||
zyn! {
|
||||
impl {{ impl_generics }} {{ input.ident }} {{ type_generics }} {{ where_clause }} {
|
||||
@for (field in &fields.named) {
|
||||
@if (!field.ident.as_ref().unwrap().to_string().starts_with("_")) {
|
||||
@struct_getter(field = field.clone())
|
||||
@struct_setter(field = field.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user