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/exec.rs | 69 ++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 33 deletions(-) (limited to 'mingling_core/src/program/exec.rs') diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index 853bff1..cdbb2b0 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -1,42 +1,44 @@ #![allow(clippy::borrowed_box)] +use std::fmt::Display; + use crate::{ AnyOutput, ChainProcess, Dispatcher, Next, Program, ProgramCollect, RenderResult, error::ProgramInternalExecuteError, - hint::{DispatcherNotFound, RendererNotFound}, }; pub mod error; -pub async fn exec( - program: Program, -) -> Result { +pub async fn exec(program: Program) -> Result +where + C: ProgramCollect, + G: Display, +{ + let mut current; + // Match user input - let matched: (Box, Vec) = match match_user_input(&program) { - Ok(r) => (r.0.clone(), r.1), + match match_user_input(&program) { + Ok((dispatcher, args)) => { + // Entry point + current = match dispatcher.begin(args) { + ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), + ChainProcess::Ok((any, Next::Chain)) => any, + ChainProcess::Err(e) => return Err(e.into()), + }; + } Err(ProgramInternalExecuteError::DispatcherNotFound) => { - // If no Dispatcher is found, dispatch to the DispatcherNotFound Dispatcher - // to route it to the NoDispatcherFound struct - let disp: Box = Box::new(DispatcherNotFound); - (disp, program.args) + // No matching Dispatcher is found + return Err(ProgramInternalExecuteError::DispatcherNotFound); } Err(e) => return Err(e), }; - // Entry point - let (dispatcher, args) = matched; - let mut current = match dispatcher.begin(args) { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), - }; - loop { current = { // If a chain exists, execute as a chain if C::has_chain(¤t) { match C::do_chain(current).await { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), + ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), ChainProcess::Ok((any, Next::Chain)) => any, ChainProcess::Err(e) => return Err(e.into()), } @@ -47,29 +49,28 @@ pub async fn exec( C::render(current, &mut render_result); return Ok(render_result); } - // If no renderer exists, transfer to the RendererNotFound Dispatcher for execution + // No renderer exists else { - let disp: Box = Box::new(RendererNotFound); - - match disp.begin(vec![format!("{:?}", current.type_id)]) { - ChainProcess::Ok((any, Next::Renderer)) => return Ok(render::(any)), - ChainProcess::Ok((any, Next::Chain)) => any, - ChainProcess::Err(e) => return Err(e.into()), - } + let renderer_name = current.member_id.to_string(); + return Err(ProgramInternalExecuteError::RendererNotFound(renderer_name)); } }; } } /// Match user input against registered dispatchers and return the matched dispatcher and remaining arguments. -fn match_user_input( - program: &Program, -) -> Result<(&Box, Vec), ProgramInternalExecuteError> { +fn match_user_input( + program: &Program, +) -> Result<(&Box>, Vec), ProgramInternalExecuteError> +where + C: ProgramCollect, + G: Display, +{ let nodes = get_nodes(program); let command = format!("{} ", program.args.join(" ")); // Find all nodes that match the command prefix - let matching_nodes: Vec<&(String, &Box)> = nodes + let matching_nodes: Vec<&(String, &Box>)> = nodes .iter() // Also add a space to the node string to ensure consistent matching logic .filter(|(node_str, _)| command.starts_with(&format!("{} ", node_str))) @@ -102,14 +103,16 @@ fn match_user_input( } #[inline(always)] -fn render(any: AnyOutput) -> RenderResult { +fn render, G: Display>(any: AnyOutput) -> RenderResult { let mut render_result = RenderResult::default(); C::render(any, &mut render_result); render_result } // Get all registered dispatcher names from the program -fn get_nodes(program: &Program) -> Vec<(String, &Box)> { +fn get_nodes, G: Display>( + program: &Program, +) -> Vec<(String, &Box>)> { program .dispatcher .iter() -- cgit