diff --git a/crates/command_parser/src/lib.rs b/crates/command_parser/src/lib.rs index 239b9531..8a3695b2 100644 --- a/crates/command_parser/src/lib.rs +++ b/crates/command_parser/src/lib.rs @@ -2,6 +2,8 @@ #![feature(round_char_boundary)] #![feature(iter_intersperse)] +use std::sync::Arc; + pub mod command; pub mod flag; pub mod parameter; @@ -28,14 +30,14 @@ pub type Tree = tree::TreeBranch; #[derive(Debug)] pub struct ParsedCommand { - pub command_def: Command, + pub command_def: Arc, pub parameters: HashMap, pub flags: HashMap>, } #[derive(Clone, Debug)] struct MatchedTokenState { - tree: Tree, + tree: Arc, token: Token, match_result: TokenMatchResult, start_pos: usize, @@ -43,12 +45,12 @@ struct MatchedTokenState { } pub fn parse_command( - command_tree: Tree, + command_tree: impl Into>, prefix: String, input: String, ) -> Result { let input: SmolStr = input.into(); - let mut local_tree: Tree = command_tree.clone(); + let mut local_tree = command_tree.into(); // end position of all currently matched tokens let mut current_pos: usize = 0; @@ -62,7 +64,7 @@ pub fn parse_command( // track the best attempt at parsing (deepest matched tokens) // so we can use it for error messages/suggestions even if we backtrack later - let mut best_attempt: Option<(Tree, Vec, usize)> = None; + let mut best_attempt: Option<(Arc, Vec, usize)> = None; loop { let mut possible_tokens = local_tree diff --git a/crates/command_parser/src/tree.rs b/crates/command_parser/src/tree.rs index 84fcca7f..022ef981 100644 --- a/crates/command_parser/src/tree.rs +++ b/crates/command_parser/src/tree.rs @@ -6,8 +6,8 @@ use crate::{command::Command, token::Token}; #[derive(Debug, Clone)] pub struct TreeBranch { - current_command: Option, - branches: OrderMap, + current_command: Option>, + branches: OrderMap>, } impl Default for TreeBranch { @@ -45,16 +45,18 @@ impl TreeBranch { current_branch.register_command(new_command); } // recursively get or create a sub-branch for each token - current_branch = current_branch - .branches - .entry(token) - .or_insert_with(TreeBranch::default); + current_branch = Arc::make_mut( + current_branch + .branches + .entry(token) + .or_insert_with(|| Arc::new(TreeBranch::default())), + ); } // when we're out of tokens add the command to the last branch - current_branch.current_command = Some(command); + current_branch.current_command = Some(Arc::new(command)); } - pub fn command(&self) -> Option { + pub fn command(&self) -> Option> { self.current_command.clone() } @@ -76,7 +78,7 @@ impl TreeBranch { let mut commands = box_iter(std::iter::empty()); for branch in self.branches.values() { if let Some(command) = branch.current_command.as_ref() { - commands = box_iter(commands.chain(std::iter::once(command))); + commands = box_iter(commands.chain(std::iter::once(command.as_ref()))); // we dont need to look further if we found a command continue; } @@ -85,11 +87,11 @@ impl TreeBranch { commands } - pub fn get_branch(&self, token: &Token) -> Option<&Self> { + pub fn get_branch(&self, token: &Token) -> Option<&Arc> { self.branches.get(token) } - pub fn branches(&self) -> impl Iterator { + pub fn branches(&self) -> impl Iterator)> { self.branches.iter() } } diff --git a/crates/commands/src/lib.rs b/crates/commands/src/lib.rs index 08a094f2..32869cab 100644 --- a/crates/commands/src/lib.rs +++ b/crates/commands/src/lib.rs @@ -1,16 +1,16 @@ -use std::{collections::HashMap, fmt::Write}; +use std::{collections::HashMap, fmt::Write, sync::Arc}; use command_parser::{parameter::ParameterValue, token::TokenMatchResult, Tree}; uniffi::include_scaffolding!("commands"); lazy_static::lazy_static! { - pub static ref COMMAND_TREE: Tree = { + pub static ref COMMAND_TREE: Arc = { let mut tree = Tree::default(); command_definitions::all().into_iter().for_each(|x| tree.register_command(x)); - tree + Arc::new(tree) }; } @@ -125,7 +125,7 @@ pub fn parse_command(prefix: String, input: String) -> CommandResult { |error| CommandResult::Err { error }, |parsed| CommandResult::Ok { command: { - let command_ref = parsed.command_def.cb.into(); + let command_ref = parsed.command_def.cb.clone().into(); let mut flags = HashMap::with_capacity(parsed.flags.capacity()); for (name, value) in parsed.flags { flags.insert(name, value.map(Parameter::from));