-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add auto_state macro for state management
- Loading branch information
1 parent
e27af6d
commit 709c10f
Showing
1 changed file
with
49 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,58 @@ | ||
use proc_macro::TokenStream; | ||
use quote::quote; | ||
use syn::{parse_macro_input, ItemStruct, LitStr}; | ||
use quote::{format_ident, quote}; | ||
use syn::{parse_macro_input, Field, FieldsNamed, ItemStruct}; | ||
|
||
#[proc_macro] | ||
pub fn create_state(input: TokenStream) -> TokenStream { | ||
let input = parse_macro_input!(input as ItemStruct); | ||
let struct_name = &input.ident; | ||
let struct_def = &input; | ||
#[proc_macro_attribute] | ||
pub fn auto_state(_attr: TokenStream, item: TokenStream) -> TokenStream { | ||
let input = parse_macro_input!(item as ItemStruct); | ||
let name = &input.ident; | ||
|
||
// Extrair os campos da estrutura | ||
let fields = match &input.fields { | ||
syn::Fields::Named(FieldsNamed { named, .. }) => named, | ||
_ => panic!("AutoState only supports structs with named fields"), | ||
}; | ||
|
||
// Gerar a implementação de Fields | ||
let field_impls = fields.iter().map(|f: &Field| { | ||
let field_name = &f.ident; | ||
quote! { | ||
fields.push(&mut self.#field_name as &mut dyn ::std::any::Any); | ||
} | ||
}); | ||
|
||
let expanded = quote! { | ||
#[derive(Clone, Default)] | ||
#struct_def | ||
#input | ||
|
||
impl #name { | ||
fn new() -> Self { | ||
Self::default() | ||
} | ||
} | ||
|
||
impl Drop for #name { | ||
fn drop(&mut self) { | ||
::rustato::unregister_global_state(stringify!(#name)); | ||
} | ||
} | ||
|
||
rustato::GLOBAL_STATE_MANAGER.register_state::<#struct_name>(stringify!(#struct_name), #struct_name::default()); | ||
impl ::rustato::AutoState for #name {} | ||
|
||
impl ::rustato::Fields for #name { | ||
fn fields_mut(&mut self) -> Vec<&mut dyn ::std::any::Any> { | ||
let mut fields = Vec::new(); | ||
#(#field_impls)* | ||
fields | ||
} | ||
} | ||
|
||
::rustato::paste::paste! { | ||
#[::rustato::ctor::ctor] | ||
fn [<__register_ #name _state>]() { | ||
::rustato::__register_global_state_immediately(stringify!(#name), || ::rustato::GlobalState::new(#name::new())); | ||
} | ||
} | ||
}; | ||
|
||
TokenStream::from(expanded) | ||
} | ||
|
||
struct CreateStateInput { | ||
id: LitStr, | ||
struct_def: ItemStruct, | ||
} | ||
|
||
impl syn::parse::Parse for CreateStateInput { | ||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { | ||
let id = input.parse()?; | ||
input.parse::<syn::Token![,]>()?; | ||
let struct_def = input.parse()?; | ||
Ok(CreateStateInput { id, struct_def }) | ||
} | ||
} |