aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mingling_core/src/asset/comp.rs2
-rw-r--r--mingling_core/src/asset/dispatcher.rs2
-rw-r--r--mingling_core/src/program.rs38
-rw-r--r--mingling_core/src/program/exec.rs30
4 files changed, 55 insertions, 17 deletions
diff --git a/mingling_core/src/asset/comp.rs b/mingling_core/src/asset/comp.rs
index a6299e1..cf1f48c 100644
--- a/mingling_core/src/asset/comp.rs
+++ b/mingling_core/src/asset/comp.rs
@@ -51,7 +51,7 @@ impl CompletionHelper {
let program = this::<P>();
let args = ctx.all_words.iter().skip(1).cloned().collect::<Vec<_>>();
- let suggest = if let Ok((dispatcher, args)) = match_user_input(program, args) {
+ let suggest = if let Ok((dispatcher, args)) = match_user_input(program, &args) {
trace!(
"dispatcher matched, dispatcher=\"{}\", args={:?}",
dispatcher.node().to_string(),
diff --git a/mingling_core/src/asset/dispatcher.rs b/mingling_core/src/asset/dispatcher.rs
index 761c399..cf8fcca 100644
--- a/mingling_core/src/asset/dispatcher.rs
+++ b/mingling_core/src/asset/dispatcher.rs
@@ -29,6 +29,7 @@ where
impl<C: crate::program::ProgramCollect> Program<C> {
/// Adds a dispatcher to the program.
+ #[cfg(not(feature = "dispatch_tree"))]
pub fn with_dispatcher<Disp>(&mut self, dispatcher: Disp)
where
Disp: Dispatcher<C> + Send + Sync + 'static,
@@ -37,6 +38,7 @@ impl<C: crate::program::ProgramCollect> Program<C> {
}
/// Add some dispatchers to the program.
+ #[cfg(not(feature = "dispatch_tree"))]
pub fn with_dispatchers<D>(&mut self, dispatchers: D)
where
D: Into<Dispatchers<C>>,
diff --git a/mingling_core/src/program.rs b/mingling_core/src/program.rs
index 1505480..df5b285 100644
--- a/mingling_core/src/program.rs
+++ b/mingling_core/src/program.rs
@@ -63,6 +63,8 @@ where
pub(crate) collect: std::marker::PhantomData<C>,
pub(crate) args: Vec<String>,
+
+ #[cfg(not(feature = "dispatch_tree"))]
pub(crate) dispatcher: Vec<Box<dyn Dispatcher<C> + Send + Sync>>,
pub stdout_setting: ProgramStdoutSetting,
@@ -101,12 +103,16 @@ where
Program {
collect: std::marker::PhantomData,
args: args.into().into(),
+
+ #[cfg(not(feature = "dispatch_tree"))]
dispatcher: Vec::new(),
+
stdout_setting: Default::default(),
user_context: Default::default(),
#[cfg(feature = "general_renderer")]
general_renderer_name: GeneralRendererSetting::Disable,
+
resources: Arc::new(Mutex::new(HashMap::new())),
}
}
@@ -126,16 +132,18 @@ where
}
/// Get all registered dispatcher names from the program
- pub fn get_nodes(&self) -> Vec<(String, &(dyn Dispatcher<C> + Send + Sync))> {
+ pub fn get_nodes(
+ &'static self,
+ ) -> Vec<(String, &'static (dyn Dispatcher<C> + Send + Sync + 'static))> {
get_nodes(self)
}
/// Dynamically dispatch input arguments to registered entry types
pub fn dispatch_args_dynamic(
- &self,
+ &'static self,
args: impl Into<StringVec>,
) -> Result<AnyOutput<C>, ChainProcessError> {
- match exec::dispatch_args_dynamic(self, args.into().into()) {
+ match exec::dispatch_args_dynamic(self, &args.into().into()) {
Ok(ok) => Ok(ok),
Err(e) => Err(e.into()),
}
@@ -287,6 +295,16 @@ pub trait ProgramCollect {
/// Enum type representing internal IDs for the program
type Enum: Display;
+ /// Use a prefix tree to quickly match arguments and dispatch to an Entry
+ #[cfg(feature = "dispatch_tree")]
+ fn dispatch_args_trie(
+ raw: &Vec<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
fn build_renderer_not_found(member_id: Self::Enum) -> AnyOutput<Self::Enum>;
@@ -402,9 +420,13 @@ macro_rules! __dispatch_program_chains {
/// Get all registered dispatcher names from the program
pub fn get_nodes<C: ProgramCollect<Enum = C>>(
- program: &Program<C>,
-) -> Vec<(String, &(dyn Dispatcher<C> + Send + Sync))> {
- program
+ program: &'static Program<C>,
+) -> Vec<(String, &'static (dyn Dispatcher<C> + Send + Sync + 'static))> {
+ #[cfg(feature = "dispatch_tree")]
+ let r = C::get_nodes();
+
+ #[cfg(not(feature = "dispatch_tree"))]
+ let r = program
.dispatcher
.iter()
.map(|disp| {
@@ -416,5 +438,7 @@ pub fn get_nodes<C: ProgramCollect<Enum = C>>(
.join(" ");
(node_str, &**disp)
})
- .collect()
+ .collect();
+
+ return r;
}
diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs
index 469f6d2..9cb2892 100644
--- a/mingling_core/src/program/exec.rs
+++ b/mingling_core/src/program/exec.rs
@@ -9,11 +9,18 @@ use crate::{
pub mod error;
#[cfg(feature = "async")]
-pub async fn exec<C>(program: &Program<C>) -> Result<RenderResult, ProgramInternalExecuteError>
+pub async fn exec<C>(
+ program: &'static Program<C>,
+) -> Result<RenderResult, ProgramInternalExecuteError>
where
C: ProgramCollect<Enum = C>,
{
- let mut current = dispatch_args_dynamic(program, program.args.clone())?;
+ #[cfg(not(feature = "dispatch_tree"))]
+ let mut current = dispatch_args_dynamic(program, &program.args)?;
+
+ #[cfg(feature = "dispatch_tree")]
+ let mut current = C::dispatch_args_trie(&program.args)?;
+
let mut stop_next = false;
// If the program has Help enabled, skip actual logic and jump to Help
@@ -54,11 +61,16 @@ where
}
#[cfg(not(feature = "async"))]
-pub fn exec<C>(program: &Program<C>) -> Result<RenderResult, ProgramInternalExecuteError>
+pub fn exec<C>(program: &'static Program<C>) -> Result<RenderResult, ProgramInternalExecuteError>
where
C: ProgramCollect<Enum = C>,
{
- let mut current = dispatch_args_dynamic(program, program.args.clone())?;
+ #[cfg(not(feature = "dispatch_tree"))]
+ let mut current = dispatch_args_dynamic(program, &program.args)?;
+
+ #[cfg(feature = "dispatch_tree")]
+ let mut current = C::dispatch_args_trie(&program.args)?;
+
let mut stop_next = false;
// If the program has Help enabled, skip actual logic and jump to Help
@@ -100,8 +112,8 @@ where
/// Dynamically dispatch input arguments to registered entry types
pub(crate) fn dispatch_args_dynamic<C>(
- program: &Program<C>,
- args: Vec<String>,
+ program: &'static Program<C>,
+ args: &Vec<String>,
) -> Result<AnyOutput<C>, ProgramInternalExecuteError>
where
C: ProgramCollect<Enum = C>,
@@ -126,9 +138,9 @@ where
/// 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: &Program<C>,
- args: Vec<String>,
-) -> Result<(&(dyn Dispatcher<C> + Send + Sync), Vec<String>), ProgramInternalExecuteError>
+ program: &'static Program<C>,
+ args: &Vec<String>,
+) -> Result<(&'static (dyn Dispatcher<C> + Send + Sync), Vec<String>), ProgramInternalExecuteError>
where
C: ProgramCollect<Enum = C>,
{