From 3de10ca22cca06c4d9069984d0e66e370a331dde Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 1 Apr 2026 15:48:41 +0800 Subject: Replace typeid-based dispatch with enum-based dispatch - Add `Groupped` trait and `member_id` to `AnyOutput` - Add generic parameter `G` to `Dispatcher`, `Chain`, `Program` etc - Remove `hint` module and its marker types - Update macros to support explicit group specification - Add `gen_program` macro for generating enum-based programs - Add `GroupProcess` marker type for type-level grouping --- mingling_core/src/program.rs | 57 +++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'mingling_core/src/program.rs') diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index b13a879..1c8c0b4 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -2,10 +2,9 @@ use crate::{ AnyOutput, ChainProcess, RenderResult, asset::dispatcher::Dispatcher, error::ProgramExecuteError, }; -use std::{env, pin::Pin}; +use std::{env, fmt::Display, pin::Pin}; pub mod exec; -pub mod hint; pub mod setup; mod config; @@ -16,24 +15,31 @@ pub use flag::*; use tokio::io::AsyncWriteExt; #[derive(Default)] -pub struct Program { +pub struct Program +where + C: ProgramCollect, + G: Display, +{ pub(crate) collect: std::marker::PhantomData, + pub(crate) group: std::marker::PhantomData, pub(crate) args: Vec, - pub(crate) dispatcher: Vec>, + pub(crate) dispatcher: Vec>>, pub stdout_setting: ProgramStdoutSetting, pub user_context: ProgramUserContext, } -impl Program +impl Program where - C: ProgramCollect, + C: ProgramCollect, + G: Display, { /// Creates a new Program instance, initializing args from environment. pub fn new() -> Self { Program { collect: std::marker::PhantomData, + group: std::marker::PhantomData, args: env::args().collect(), dispatcher: Vec::new(), stdout_setting: Default::default(), @@ -57,6 +63,10 @@ where eprintln!("Dispatcher not found"); return; } + ProgramExecuteError::RendererNotFound(renderer_name) => { + eprintln!("Renderer `{}` not found", renderer_name); + return; + } ProgramExecuteError::Other(e) => { eprintln!("{}", e); return; @@ -77,24 +87,27 @@ where } pub trait ProgramCollect { - fn render(any: AnyOutput, r: &mut RenderResult); - fn do_chain(any: AnyOutput) -> Pin + Send>>; - fn has_renderer(any: &AnyOutput) -> bool; - fn has_chain(any: &AnyOutput) -> bool; + type Enum: Display; + fn render(any: AnyOutput, r: &mut RenderResult); + fn do_chain( + any: AnyOutput, + ) -> Pin> + Send>>; + fn has_renderer(any: &AnyOutput) -> bool; + fn has_chain(any: &AnyOutput) -> bool; } #[macro_export] #[doc(hidden)] macro_rules! __dispatch_program_renderers { ( - $( $render_ty:ty => $prev_ty:ty, )* + $( $render_ty:ty => $prev_ty:ident, )* ) => { - fn render(any: mingling::AnyOutput, r: &mut mingling::RenderResult) { - match any.type_id { + fn render(any: mingling::AnyOutput, r: &mut mingling::RenderResult) { + match any.member_id { $( - id if id == std::any::TypeId::of::<$prev_ty>() => { - // SAFETY: The `type_id` check ensures that `any` contains a value of type `$chain_prev`, - // so downcasting to `$chain_prev` is safe. + Self::$prev_ty => { + // SAFETY: The `type_id` check ensures that `any` contains a value of type `$prev_ty`, + // so downcasting to `$prev_ty` is safe. let value = unsafe { any.downcast::<$prev_ty>().unwrap_unchecked() }; <$render_ty as mingling::Renderer>::render(value, r); } @@ -109,18 +122,18 @@ macro_rules! __dispatch_program_renderers { #[doc(hidden)] macro_rules! __dispatch_program_chains { ( - $( $chain_ty:ty => $chain_prev:ty, )* + $( $chain_ty:ty => $chain_prev:ident, )* ) => { fn do_chain( - any: mingling::AnyOutput, - ) -> std::pin::Pin + Send>> { - match any.type_id { + any: mingling::AnyOutput, + ) -> std::pin::Pin> + Send>> { + match any.member_id { $( - id if id == std::any::TypeId::of::<$chain_prev>() => { + Self::$chain_prev => { // SAFETY: The `type_id` check ensures that `any` contains a value of type `$chain_prev`, // so downcasting to `$chain_prev` is safe. let value = unsafe { any.downcast::<$chain_prev>().unwrap_unchecked() }; - let fut = async { <$chain_ty as mingling::Chain>::proc(value).await }; + let fut = async { <$chain_ty as mingling::Chain>::proc(value).await }; Box::pin(fut) } )* -- cgit