diff options
Diffstat (limited to 'mingling_core')
| -rw-r--r-- | mingling_core/Cargo.toml | 1 | ||||
| -rw-r--r-- | mingling_core/src/asset/dispatcher.rs | 415 | ||||
| -rw-r--r-- | mingling_core/src/build/pathf.rs | 11 | ||||
| -rw-r--r-- | mingling_core/src/comp.rs | 40 | ||||
| -rw-r--r-- | mingling_core/src/program.rs | 55 | ||||
| -rw-r--r-- | mingling_core/src/program/collection.rs | 20 | ||||
| -rw-r--r-- | mingling_core/src/program/collection/mock.rs | 3 | ||||
| -rw-r--r-- | mingling_core/src/program/exec.rs | 80 | ||||
| -rw-r--r-- | mingling_core/src/program/hook.rs | 10 |
9 files changed, 26 insertions, 609 deletions
diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml index 0b7e1aa..aecf476 100644 --- a/mingling_core/Cargo.toml +++ b/mingling_core/Cargo.toml @@ -17,7 +17,6 @@ async = [] build = [] picker = [] -dispatch_tree = [] structural_renderer = ["dep:serde"] ron_serde_fmt = ["dep:ron"] json_serde_fmt = ["dep:serde_json"] diff --git a/mingling_core/src/asset/dispatcher.rs b/mingling_core/src/asset/dispatcher.rs index d700405..1ab7bf6 100644 --- a/mingling_core/src/asset/dispatcher.rs +++ b/mingling_core/src/asset/dispatcher.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::{ChainProcess, Program, ProgramCollect, asset::node::Node}; +use crate::{ChainProcess, asset::node::Node}; /// The entry logic of the Mingling program /// @@ -148,307 +148,6 @@ where } } -impl<C> Program<C> -where - C: ProgramCollect<Enum = C>, -{ - /// Add a Dispatcher to the program - /// - /// This dynamically registers a Dispatcher into the program, used for command matching at program startup - /// - /// ``` - /// # use mingling_core::Program; - /// # use mingling_core::ChainProcess; - /// # use mingling_core::Dispatcher; - /// # use mingling_core::Grouped; - /// # use mingling_core::Routable; - /// # use mingling_core::Node; - /// # use mingling_core::MockProgramCollect as ThisProgram; - /// # unsafe impl Grouped<ThisProgram> for Foo { - /// # fn member_id() -> ThisProgram { ThisProgram::Foo } - /// # } - /// # struct CMDGreet; - /// # struct Foo { - /// # args: Vec<String> - /// # } - /// # impl Dispatcher<ThisProgram> for CMDGreet { - /// # fn node(&self) -> Node { - /// # Node::default().join("greet") - /// # } - /// # fn begin(&self, args: Vec<String>) -> ChainProcess<ThisProgram> { - /// # Routable::to_chain(Foo { args }) - /// # } - /// # fn clone_dispatcher(&self) -> Box<dyn Dispatcher<ThisProgram>> { - /// # Box::new(CMDGreet) - /// # } - /// # } - /// let mut program = Program::<ThisProgram>::new(); - /// program.with_dispatcher(CMDGreet); - /// ``` - #[cfg_attr( - feature = "dispatch_tree", - deprecated( - note = "When the `dispatch_tree` feature is enabled, the `dispatcher` field no longer exists inside Program. All types are collected at compile time by the `gen_program!()` macro, so the `with_dispatcher` function is no longer needed" - ) - )] - pub fn with_dispatcher<Disp>(&mut self, dispatcher: Disp) -> &mut Self - where - Disp: Dispatcher<C> + Send + Sync + 'static, - { - #[cfg(not(feature = "dispatch_tree"))] - { - self.dispatcher.push(Box::new(dispatcher)); - } - #[cfg(feature = "dispatch_tree")] - { - let _ = dispatcher; - } - self - } - - /// Add a group of Dispatchers to the program - /// - /// This dynamically registers a group of Dispatchers into the program, used for command matching at program startup - /// - /// ``` - /// # use mingling_core::Program; - /// # use mingling_core::ChainProcess; - /// # use mingling_core::Dispatcher; - /// # use mingling_core::Grouped; - /// # use mingling_core::Routable; - /// # use mingling_core::Node; - /// # use mingling_core::MockProgramCollect as ThisProgram; - /// # unsafe impl Grouped<ThisProgram> for Foo { - /// # fn member_id() -> ThisProgram { ThisProgram::Foo } - /// # } - /// # struct CMDGreet; - /// # struct Foo { - /// # args: Vec<String> - /// # } - /// # impl Dispatcher<ThisProgram> for CMDGreet { - /// # fn node(&self) -> Node { - /// # Node::default().join("greet") - /// # } - /// # fn begin(&self, args: Vec<String>) -> ChainProcess<ThisProgram> { - /// # Routable::to_chain(Foo { args }) - /// # } - /// # fn clone_dispatcher(&self) -> Box<dyn Dispatcher<ThisProgram>> { - /// # Box::new(CMDGreet) - /// # } - /// # } - /// let mut program = Program::<ThisProgram>::new(); - /// program.with_dispatchers((CMDGreet, /* Other Dispatchers */)); - /// ``` - #[deprecated( - note = "with_dispatchers is no longer the recommended way to register Dispatchers, please split into multiple with_dispatcher calls" - )] - #[allow(deprecated)] - pub fn with_dispatchers<D>(&mut self, dispatchers: D) -> &mut Self - where - D: Into<Dispatchers<C>>, - { - #[cfg(not(feature = "dispatch_tree"))] - { - let dispatchers = dispatchers.into(); - self.dispatcher.extend(dispatchers.dispatcher); - } - #[cfg(feature = "dispatch_tree")] - { - let _ = dispatchers; - } - self - } -} - -/// Represents a group of Dispatchers -/// -/// It records a group of Dispatchers and implements conversion from tuples `(Disp, ..)` for this type, -/// allowing for simpler construction syntax when using `with_dispatchers` -/// -/// # Limits -/// -/// Dispatchers supports conversion from tuples of up to 7 Dispatchers -#[deprecated( - note = "with_dispatchers is no longer the recommended way to register Dispatchers, please split into multiple with_dispatcher calls" -)] -pub struct Dispatchers<G> { - dispatcher: Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>>, -} - -#[allow(deprecated)] -impl<G> From<Vec<Box<dyn Dispatcher<G> + Send + Sync>>> for Dispatchers<G> { - fn from(dispatcher: Vec<Box<dyn Dispatcher<G> + Send + Sync>>) -> Self { - Self { dispatcher } - } -} - -#[allow(deprecated)] -impl<G> From<Box<dyn Dispatcher<G> + Send + Sync>> for Dispatchers<G> { - fn from(dispatcher: Box<dyn Dispatcher<G> + Send + Sync>) -> Self { - Self { - dispatcher: vec![dispatcher], - } - } -} - -#[allow(deprecated)] -impl<D, G> From<(D,)> for Dispatchers<G> -where - D: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatcher: (D,)) -> Self { - Self { - dispatcher: vec![Box::new(dispatcher.0)], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, G> From<(D1, D2)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2)) -> Self { - Self { - dispatcher: vec![Box::new(dispatchers.0), Box::new(dispatchers.1)], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, D3, G> From<(D1, D2, D3)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - D3: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2, D3)) -> Self { - Self { - dispatcher: vec![ - Box::new(dispatchers.0), - Box::new(dispatchers.1), - Box::new(dispatchers.2), - ], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, D3, D4, G> From<(D1, D2, D3, D4)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - D3: Dispatcher<G> + Send + Sync + 'static, - D4: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2, D3, D4)) -> Self { - Self { - dispatcher: vec![ - Box::new(dispatchers.0), - Box::new(dispatchers.1), - Box::new(dispatchers.2), - Box::new(dispatchers.3), - ], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, D3, D4, D5, G> From<(D1, D2, D3, D4, D5)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - D3: Dispatcher<G> + Send + Sync + 'static, - D4: Dispatcher<G> + Send + Sync + 'static, - D5: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2, D3, D4, D5)) -> Self { - Self { - dispatcher: vec![ - Box::new(dispatchers.0), - Box::new(dispatchers.1), - Box::new(dispatchers.2), - Box::new(dispatchers.3), - Box::new(dispatchers.4), - ], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, D3, D4, D5, D6, G> From<(D1, D2, D3, D4, D5, D6)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - D3: Dispatcher<G> + Send + Sync + 'static, - D4: Dispatcher<G> + Send + Sync + 'static, - D5: Dispatcher<G> + Send + Sync + 'static, - D6: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2, D3, D4, D5, D6)) -> Self { - Self { - dispatcher: vec![ - Box::new(dispatchers.0), - Box::new(dispatchers.1), - Box::new(dispatchers.2), - Box::new(dispatchers.3), - Box::new(dispatchers.4), - Box::new(dispatchers.5), - ], - } - } -} - -#[allow(deprecated)] -impl<D1, D2, D3, D4, D5, D6, D7, G> From<(D1, D2, D3, D4, D5, D6, D7)> for Dispatchers<G> -where - D1: Dispatcher<G> + Send + Sync + 'static, - D2: Dispatcher<G> + Send + Sync + 'static, - D3: Dispatcher<G> + Send + Sync + 'static, - D4: Dispatcher<G> + Send + Sync + 'static, - D5: Dispatcher<G> + Send + Sync + 'static, - D6: Dispatcher<G> + Send + Sync + 'static, - D7: Dispatcher<G> + Send + Sync + 'static, - G: Display, -{ - fn from(dispatchers: (D1, D2, D3, D4, D5, D6, D7)) -> Self { - Self { - dispatcher: vec![ - Box::new(dispatchers.0), - Box::new(dispatchers.1), - Box::new(dispatchers.2), - Box::new(dispatchers.3), - Box::new(dispatchers.4), - Box::new(dispatchers.5), - Box::new(dispatchers.6), - ], - } - } -} - -#[allow(deprecated)] -impl<G> std::ops::Deref for Dispatchers<G> { - type Target = Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>>; - - fn deref(&self) -> &Self::Target { - &self.dispatcher - } -} - -#[allow(deprecated)] -impl<G> From<Dispatchers<G>> for Vec<Box<dyn Dispatcher<G> + Send + Sync + 'static>> { - fn from(val: Dispatchers<G>) -> Self { - val.dispatcher - } -} - #[cfg(test)] mod tests { use super::*; @@ -485,118 +184,6 @@ mod tests { } #[test] - #[allow(deprecated)] - fn test_dispatchers_from_single_tuple() { - let disp = MockDispatcher { name: "foo" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((disp,)); - assert_eq!(dispatchers.dispatcher.len(), 1); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_two_tuple() { - let d1 = MockDispatcher { name: "a" }; - let d2 = MockDispatcher { name: "b" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2)); - assert_eq!(dispatchers.dispatcher.len(), 2); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_three_tuple() { - let d1 = MockDispatcher { name: "x" }; - let d2 = MockDispatcher { name: "y" }; - let d3 = MockDispatcher { name: "z" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2, d3)); - assert_eq!(dispatchers.dispatcher.len(), 3); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_four_tuple() { - let d1 = MockDispatcher { name: "1" }; - let d2 = MockDispatcher { name: "2" }; - let d3 = MockDispatcher { name: "3" }; - let d4 = MockDispatcher { name: "4" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2, d3, d4)); - assert_eq!(dispatchers.dispatcher.len(), 4); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_five_tuple() { - let d1 = MockDispatcher { name: "a" }; - let d2 = MockDispatcher { name: "b" }; - let d3 = MockDispatcher { name: "c" }; - let d4 = MockDispatcher { name: "d" }; - let d5 = MockDispatcher { name: "e" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2, d3, d4, d5)); - assert_eq!(dispatchers.dispatcher.len(), 5); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_six_tuple() { - let d1 = MockDispatcher { name: "a" }; - let d2 = MockDispatcher { name: "b" }; - let d3 = MockDispatcher { name: "c" }; - let d4 = MockDispatcher { name: "d" }; - let d5 = MockDispatcher { name: "e" }; - let d6 = MockDispatcher { name: "f" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2, d3, d4, d5, d6)); - assert_eq!(dispatchers.dispatcher.len(), 6); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_seven_tuple() { - let d1 = MockDispatcher { name: "a" }; - let d2 = MockDispatcher { name: "b" }; - let d3 = MockDispatcher { name: "c" }; - let d4 = MockDispatcher { name: "d" }; - let d5 = MockDispatcher { name: "e" }; - let d6 = MockDispatcher { name: "f" }; - let d7 = MockDispatcher { name: "g" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((d1, d2, d3, d4, d5, d6, d7)); - assert_eq!(dispatchers.dispatcher.len(), 7); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_vec_of_boxed() { - let d1: Box<dyn Dispatcher<MockG> + Send + Sync> = Box::new(MockDispatcher { name: "a" }); - let d2: Box<dyn Dispatcher<MockG> + Send + Sync> = Box::new(MockDispatcher { name: "b" }); - let dispatchers: Dispatchers<MockG> = vec![d1, d2].into(); - assert_eq!(dispatchers.dispatcher.len(), 2); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_from_single_boxed() { - let d: Box<dyn Dispatcher<MockG> + Send + Sync> = Box::new(MockDispatcher { name: "x" }); - let dispatchers: Dispatchers<MockG> = d.into(); - assert_eq!(dispatchers.dispatcher.len(), 1); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_deref() { - let disp = MockDispatcher { name: "test" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((disp,)); - let inner: &Vec<Box<dyn Dispatcher<MockG> + Send + Sync + 'static>> = &dispatchers; - assert_eq!(inner.len(), 1); - } - - #[test] - #[allow(deprecated)] - fn test_dispatchers_into_vec() { - let disp = MockDispatcher { name: "foo" }; - let dispatchers: Dispatchers<MockG> = Dispatchers::from((disp,)); - let vec: Vec<Box<dyn Dispatcher<MockG> + Send + Sync + 'static>> = dispatchers.into(); - assert_eq!(vec.len(), 1); - } - - #[test] fn test_box_clone_dispatcher() { let disp: Box<dyn Dispatcher<MockG>> = Box::new(MockDispatcher { name: "clonable" }); let cloned = disp.clone_dispatcher(); diff --git a/mingling_core/src/build/pathf.rs b/mingling_core/src/build/pathf.rs index 23d3910..4b8af1b 100644 --- a/mingling_core/src/build/pathf.rs +++ b/mingling_core/src/build/pathf.rs @@ -1,6 +1,5 @@ #![allow(unused_imports)] -pub use mingling_pathf::config::*; pub use mingling_pathf::module_pathf::*; pub use mingling_pathf::pattern_analyzer::*; pub use mingling_pathf::patterns::*; @@ -37,10 +36,7 @@ pub fn analyze_and_build_type_mapping_for( crate_dir: &Path, output_dir: &Path, ) -> Result<(), crate::error::MinglingPathfinderError> { - let config = mingling_pathf::config::PathfinderConfig { - use_dispatch_tree: cfg!(feature = "dispatch_tree"), - }; - mingling_pathf::analyze_and_build_type_mapping_for(crate_dir, output_dir, &config) + mingling_pathf::analyze_and_build_type_mapping_for(crate_dir, output_dir) } /// # Analyzes and builds a type mapping @@ -81,9 +77,6 @@ pub fn analyze_and_build_type_mapping_for( /// ``` pub fn analyze_and_build_type_mapping() -> Result<(), crate::error::MinglingPathfinderError> { - let config = mingling_pathf::config::PathfinderConfig { - use_dispatch_tree: cfg!(feature = "dispatch_tree"), - }; let crate_dir = std::env::current_dir().map_err(crate::error::MinglingPathfinderError::IoError)?; let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| { @@ -99,7 +92,7 @@ pub fn analyze_and_build_type_mapping() -> Result<(), crate::error::MinglingPath )) })?; let output_dir = Path::new(&out_dir).join(&crate_name); - mingling_pathf::analyze_and_build_type_mapping_for(&crate_dir, &output_dir, &config)?; + mingling_pathf::analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?; println!("cargo:rerun-if-changed=src/"); Ok(()) } diff --git a/mingling_core/src/comp.rs b/mingling_core/src/comp.rs index aea46e1..399c9bf 100644 --- a/mingling_core/src/comp.rs +++ b/mingling_core/src/comp.rs @@ -37,12 +37,6 @@ pub const COMPLETION_SUBCOMMAND: &str = "__comp"; #[cfg(feature = "debug")] use crate::debug::init_env_logger; -#[cfg(not(feature = "dispatch_tree"))] -use crate::ChainProcess; - -#[cfg(not(feature = "dispatch_tree"))] -use crate::exec::match_user_input; - /// Mingling Completion Entry Point /// /// Defines the custom completion logic entry point for the program's shell @@ -174,30 +168,6 @@ impl CompletionHelper { let args = first_cmd_match.map_or_else(Vec::new, |start| all_args[start..].to_vec()); trace!("arguments=\"{}\"", args.join(", ")); - #[cfg(not(feature = "dispatch_tree"))] - let program = this::<P>(); - - #[cfg(not(feature = "dispatch_tree"))] - let suggest = if let Ok((dispatcher, args)) = match_user_input(program, &args) { - trace!( - "dispatcher matched, dispatcher=\"{}\"", - dispatcher.node().to_string(), - ); - let begin = dispatcher.begin(args); - if let crate::ChainProcess::Ok((any, _)) = begin { - trace!("entry type: {}", any.member_id); - let result = P::do_comp(&any, ctx); - trace!("do_comp result: {:?}", result); - Some(result) - } else { - trace!("begin not Ok"); - None - } - } else { - trace!("no dispatcher matched"); - None - }; - #[cfg(feature = "dispatch_tree")] let suggest = if let Ok(any) = P::dispatch_args(&args) { debug!("dispatch_args OK, member_id = {:?}", any.member_id); trace!("entry type: {}", any.member_id); @@ -354,18 +324,8 @@ where { let words: Vec<String> = node.split(' ').map(str::to_string).collect(); - #[cfg(feature = "dispatch_tree")] let lazy_member = P::dispatch_args(&words).ok().map(|any| any.member_id); - #[cfg(not(feature = "dispatch_tree"))] - let lazy_member = match match_user_input(this::<P>(), &words) { - Ok((dispatcher, args)) => match dispatcher.begin(args) { - ChainProcess::Ok((any, _)) => Some(any.member_id), - ChainProcess::Err(_) => None, - }, - Err(_) => None, - }; - let member_id = lazy_member?; P::get_metadata::<Description>(member_id).map(String::from) } diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs index 7bafe72..1c8fb07 100644 --- a/mingling_core/src/program.rs +++ b/mingling_core/src/program.rs @@ -53,9 +53,6 @@ where pub(crate) args: Vec<String>, - #[cfg(not(feature = "dispatch_tree"))] - pub(crate) dispatcher: Vec<Box<dyn Dispatcher<C> + Send + Sync>>, - /// Program stdout settings. /// /// This struct controls the program's output behavior, including whether @@ -116,9 +113,6 @@ where collect: std::marker::PhantomData, args: args.into().into(), - #[cfg(not(feature = "dispatch_tree"))] - dispatcher: Vec::new(), - stdout_setting: ProgramStdoutSetting::default(), user_context: ProgramUserContext::default(), @@ -188,25 +182,12 @@ where get_nodes(self) } - /// Dynamically dispatch input arguments to registered entry types + /// Dispatch input arguments to an entry /// /// # Errors /// /// Returns `Err(ChainProcessError)` if the dispatch fails, /// e.g., if no dispatcher is found for the given arguments. - pub fn dispatch_args_dynamic( - &'static self, - args: impl Into<StringVec>, - ) -> Result<AnyOutput<C>, ChainProcessError> { - let sv: Vec<String> = args.into().into(); - match exec::dispatch_args_dynamic(self, &sv) { - Ok(ok) => Ok(ok), - Err(e) => Err(e.into()), - } - } - - /// Use a prefix tree to quickly match arguments and dispatch to an Entry - #[cfg(feature = "dispatch_tree")] pub fn dispatch_args( &'static self, args: impl Into<StringVec>, @@ -225,40 +206,12 @@ where pub fn get_nodes<C: ProgramCollect<Enum = C>>( program: &'static Program<C>, ) -> Vec<(String, &'static (dyn Dispatcher<C> + Send + Sync + 'static))> { - #[cfg(feature = "dispatch_tree")] let r = C::get_nodes(); - #[cfg(feature = "dispatch_tree")] - { - #[cfg(feature = "debug")] - { - let node_strs: Vec<String> = r.iter().map(|v| v.0.clone()).collect(); - crate::info!("All Nodes: [{}]", node_strs.join(", ")); - } - } - - #[cfg(not(feature = "dispatch_tree"))] - let r: Vec<_> = program - .dispatcher - .iter() - .map(|disp| { - let node_str = disp - .node() - .to_string() - .split('.') - .collect::<Vec<_>>() - .join(" "); - (node_str, &**disp) - }) - .collect(); - - #[cfg(not(feature = "dispatch_tree"))] + #[cfg(feature = "debug")] { - #[cfg(feature = "debug")] - { - let node_strs: Vec<String> = r.iter().map(|v| v.0.clone()).collect(); - crate::info!("All Nodes: [{}]", node_strs.join(", ")); - } + let node_strs: Vec<String> = r.iter().map(|v| v.0.clone()).collect(); + crate::info!("All Nodes: [{}]", node_strs.join(", ")); } r diff --git a/mingling_core/src/program/collection.rs b/mingling_core/src/program/collection.rs index 438b800..c571887 100644 --- a/mingling_core/src/program/collection.rs +++ b/mingling_core/src/program/collection.rs @@ -2,7 +2,6 @@ #[cfg(feature = "async")] use std::pin::Pin; -#[cfg(feature = "dispatch_tree")] use crate::Dispatcher; use crate::{AnyOutput, ChainProcess, Grouped, RenderResult}; @@ -34,26 +33,19 @@ pub trait ProgramCollect { /// you can use the `empty_result!()` macro to create this type ResultEmpty: Grouped<Self::Enum>; - /// Use a prefix tree to quickly match arguments and dispatch to an Entry - #[cfg(feature = "dispatch_tree")] - fn dispatch_args( - raw: &[String], - ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError>; - - #[cfg(not(feature = "dispatch_tree"))] - /// Use a prefix tree to quickly match arguments and dispatch to an Entry + /// Dispatch the raw user arguments to an Entry. + /// + /// The concrete matching strategy (trie or linear list) is generated by + /// `gen_program!` and selected by the `dispatch_tree` feature. /// /// # Errors /// /// Returns an error if the program fails to execute the given arguments. fn dispatch_args( - _raw: &[String], - ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError> { - unreachable!() - } + raw: &[String], + ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError>; /// Get all registered dispatcher names from the program - #[cfg(feature = "dispatch_tree")] fn get_nodes() -> Vec<(String, &'static (dyn Dispatcher<Self::Enum> + Send + Sync))>; /// Build an [`AnyOutput`](./struct.AnyOutput.html) to indicate that a renderer was not found diff --git a/mingling_core/src/program/collection/mock.rs b/mingling_core/src/program/collection/mock.rs index 662d8f2..d256cc1 100644 --- a/mingling_core/src/program/collection/mock.rs +++ b/mingling_core/src/program/collection/mock.rs @@ -3,7 +3,6 @@ use crate::{AnyOutput, ChainProcess, Grouped, ProgramCollect, RenderResult}; #[cfg(feature = "async")] use std::pin::Pin; -#[cfg(feature = "dispatch_tree")] use crate::Dispatcher; #[cfg(feature = "comp")] @@ -74,14 +73,12 @@ impl ProgramCollect for MockProgramCollect { type ErrorRendererNotFound = Self; type ResultEmpty = Self; - #[cfg(feature = "dispatch_tree")] fn dispatch_args( _raw: &[String], ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError> { unreachable!() } - #[cfg(feature = "dispatch_tree")] fn get_nodes() -> Vec<(String, &'static (dyn Dispatcher<Self::Enum> + Send + Sync))> { unreachable!() } diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index 3ad5ba8..4980d40 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -3,7 +3,7 @@ #![allow(clippy::too_many_lines)] use crate::{ - AnyOutput, ChainProcess, Dispatcher, NextProcess, Program, ProgramCollect, RenderResult, + AnyOutput, ChainProcess, NextProcess, Program, ProgramCollect, RenderResult, error::ProgramInternalExecuteError, hook::ProgramControls, }; @@ -58,12 +58,8 @@ where current ); - // Dispatch args - either via dynamic dispatch or trie dispatch based on feature flag - let mut current = if cfg!(not(feature = "dispatch_tree")) { - dispatch_args_dynamic(program, args)? - } else { - C::dispatch_args(args)? - }; + // Dispatch args + let mut current = C::dispatch_args(args)?; // Run hook control!( @@ -180,76 +176,6 @@ where Ok(render_result) } -/// Dynamically dispatch input arguments to registered entry types -pub(crate) fn dispatch_args_dynamic<C>( - program: &'static Program<C>, - args: &[String], -) -> Result<AnyOutput<C>, ProgramInternalExecuteError> -where - C: ProgramCollect<Enum = C>, -{ - let next = match match_user_input(program, args) { - Ok((dispatcher, args)) => { - // Entry point - match dispatcher.begin(args) { - ChainProcess::Ok((any, _)) => any, - ChainProcess::Err(e) => return Err(e.into()), - } - } - Err(ProgramInternalExecuteError::DispatcherNotFound) => { - // No matching Dispatcher is found - C::build_entry_fallback(args.to_vec()) - } - Err(e) => return Err(e), - }; - Ok(next) -} - -/// Match user input against registered dispatchers and return the matched dispatcher and remaining arguments. -#[allow(clippy::type_complexity)] -pub(crate) fn match_user_input<C>( - program: &'static Program<C>, - args: &[String], -) -> Result<(&'static (dyn Dispatcher<C> + Send + Sync), Vec<String>), ProgramInternalExecuteError> -where - C: ProgramCollect<Enum = C>, -{ - let nodes = program.get_nodes(); - let command = format!("{} ", args.join(" ")); - - // Find all nodes that match the command prefix - let matching_nodes: Vec<&(String, &(dyn Dispatcher<C> + Send + Sync))> = nodes - .iter() - // Also add a space to the node string to ensure consistent matching logic - .filter(|(node_str, _)| command.starts_with(&format!("{node_str} "))) - .collect(); - - match matching_nodes.len() { - 0 => { - // No matching node found - Err(ProgramInternalExecuteError::DispatcherNotFound) - } - 1 => { - let matched_prefix = matching_nodes[0]; - let prefix_len = matched_prefix.0.split_whitespace().count(); - let trimmed_args: Vec<String> = args.iter().skip(prefix_len).cloned().collect(); - Ok((matched_prefix.1, trimmed_args)) - } - _ => { - // Multiple matching nodes found - // Find the node with the longest length (most specific match) - let matched_prefix = matching_nodes - .iter() - .max_by_key(|node| node.0.len()) - .unwrap(); - - let prefix_len = matched_prefix.0.split_whitespace().count(); - let trimmed_args: Vec<String> = args.iter().skip(prefix_len).cloned().collect(); - Ok((matched_prefix.1, trimmed_args)) - } - } -} - #[inline] pub(crate) fn handle_program_control<C: ProgramCollect<Enum = C>>( program: &Program<C>, diff --git a/mingling_core/src/program/hook.rs b/mingling_core/src/program/hook.rs index 92106f9..a5cd3a7 100644 --- a/mingling_core/src/program/hook.rs +++ b/mingling_core/src/program/hook.rs @@ -722,6 +722,16 @@ mod tests { type ErrorRendererNotFound = Self; type ResultEmpty = Self; + fn dispatch_args( + _raw: &[String], + ) -> Result<crate::AnyOutput<Self>, crate::error::ProgramInternalExecuteError> { + unreachable!() + } + + fn get_nodes() -> Vec<(String, &'static (dyn crate::Dispatcher<Self> + Send + Sync))> { + unreachable!() + } + fn build_renderer_not_found(_member_id: Self) -> crate::AnyOutput<Self> { unreachable!() } |
