diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-02-04 00:27:16 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-02-04 00:27:16 +0800 |
| commit | d19e5d84ee21502fd3440511d4ffb1ee1f49d3b2 (patch) | |
| tree | fb8efef6f8e9a26c5b60d4ac220b11d6c6f0775e /macros/render_system_macros/src | |
| parent | 7ee0d3f20c875e7405bb8442c5eb0228d1599a03 (diff) | |
Refactor build system and implement complete renderer system
- Split monolithic build.rs into modular async generators
- Add renderer override system with type-safe dispatch
- Implement command template macro for consistent command definitions
- Add proc-macro crates for command and renderer systems
- Reorganize directory structure for better separation of concerns
- Update documentation to reflect new architecture
Diffstat (limited to 'macros/render_system_macros/src')
| -rw-r--r-- | macros/render_system_macros/src/lib.rs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/macros/render_system_macros/src/lib.rs b/macros/render_system_macros/src/lib.rs new file mode 100644 index 0000000..7466b53 --- /dev/null +++ b/macros/render_system_macros/src/lib.rs @@ -0,0 +1,143 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{ItemFn, Type, parse_macro_input, spanned::Spanned}; + +/// Macro for simplifying renderer definitions +/// +/// Expands the `#[result_renderer(Renderer)]` macro into the corresponding struct and trait implementation +/// +/// # Example +/// ```ignore +/// #[result_renderer(MyRenderer)] +/// async fn render(data: &Output) -> Result<JVRenderResult, CmdRenderError> { +/// // Rendering logic +/// } +/// ``` +/// +/// Expands to: +/// ```ignore +/// pub struct MyRenderer; +/// +/// impl JVResultRenderer<Output> for MyRenderer { +/// async fn render(data: &Output) -> Result<JVRenderResult, CmdRenderError> { +/// // Rendering logic +/// } +/// } +/// +/// impl JVResultAutoRenderer<Output> for MyRenderer { +/// fn get_type_id(&self) -> std::any::TypeId { +/// std::any::TypeId::of::<Self>() +/// } +/// +/// fn get_data_type_id(&self) -> std::any::TypeId { +/// std::any::TypeId::of::<Output>() +/// } +/// } +/// ``` +#[proc_macro_attribute] +pub fn result_renderer(args: TokenStream, input: TokenStream) -> TokenStream { + // Parse macro arguments (renderer struct name) + let renderer_name = parse_macro_input!(args as syn::Ident); + + // Parse the input function + let input_fn = parse_macro_input!(input as ItemFn); + + // Check if the function is async + if input_fn.sig.asyncness.is_none() { + return syn::Error::new(input_fn.sig.ident.span(), "renderer function must be async") + .to_compile_error() + .into(); + } + + // Get the function name + let fn_name = &input_fn.sig.ident; + + // Get function parameters + let fn_inputs = &input_fn.sig.inputs; + + // Check the number of function parameters + if fn_inputs.len() != 1 { + return syn::Error::new( + input_fn.sig.paren_token.span.join(), + "renderer function must have exactly one parameter", + ) + .to_compile_error() + .into(); + } + + // Extract the type of the first parameter + let param_type = match &fn_inputs[0] { + syn::FnArg::Typed(pat_type) => &pat_type.ty, + syn::FnArg::Receiver(_) => { + return syn::Error::new( + fn_inputs[0].span(), + "renderer function cannot have self parameter", + ) + .to_compile_error() + .into(); + } + }; + + // Check if the parameter type is a reference type, and extract the inner type + let inner_type = match &**param_type { + Type::Reference(type_ref) => { + // Ensure it's a reference type + &type_ref.elem + } + _ => { + return syn::Error::new( + param_type.span(), + "renderer function parameter must be a reference type (&Data)", + ) + .to_compile_error() + .into(); + } + }; + + // Extract the parameter pattern (for function calls) + let param_pattern = match &fn_inputs[0] { + syn::FnArg::Typed(pat_type) => &pat_type.pat, + _ => unreachable!(), + }; + + // Extract the function's visibility modifier + let visibility = &input_fn.vis; + + // Extract generic parameters (if any) + let generics = &input_fn.sig.generics; + + // Extract where clause (if any) + let where_clause = &generics.where_clause; + + // Build the output + let expanded = quote! { + #input_fn + + #visibility struct #renderer_name; + + impl #generics crate::systems::render::renderer::JVResultRenderer<#inner_type> for #renderer_name + #where_clause + { + fn render( + #fn_inputs + ) -> impl ::std::future::Future<Output = ::std::result::Result< + crate::systems::render::renderer::JVRenderResult, + crate::systems::cmd::errors::CmdRenderError + >> + ::std::marker::Send + ::std::marker::Sync { + async move { + #fn_name(#param_pattern).await + } + } + + fn get_type_id(&self) -> std::any::TypeId { + std::any::TypeId::of::<Self>() + } + + fn get_data_type_id(&self) -> std::any::TypeId { + std::any::TypeId::of::<#inner_type>() + } + } + }; + + expanded.into() +} |
