use Arc throught the parser

This commit is contained in:
dawn 2026-01-19 17:57:50 +03:00
parent f9367ea041
commit c18e72450b
No known key found for this signature in database
3 changed files with 24 additions and 20 deletions

View file

@ -2,6 +2,8 @@
#![feature(round_char_boundary)] #![feature(round_char_boundary)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
use std::sync::Arc;
pub mod command; pub mod command;
pub mod flag; pub mod flag;
pub mod parameter; pub mod parameter;
@ -28,14 +30,14 @@ pub type Tree = tree::TreeBranch;
#[derive(Debug)] #[derive(Debug)]
pub struct ParsedCommand { pub struct ParsedCommand {
pub command_def: Command, pub command_def: Arc<Command>,
pub parameters: HashMap<String, ParameterValue>, pub parameters: HashMap<String, ParameterValue>,
pub flags: HashMap<String, Option<ParameterValue>>, pub flags: HashMap<String, Option<ParameterValue>>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct MatchedTokenState { struct MatchedTokenState {
tree: Tree, tree: Arc<Tree>,
token: Token, token: Token,
match_result: TokenMatchResult, match_result: TokenMatchResult,
start_pos: usize, start_pos: usize,
@ -43,12 +45,12 @@ struct MatchedTokenState {
} }
pub fn parse_command( pub fn parse_command(
command_tree: Tree, command_tree: impl Into<Arc<Tree>>,
prefix: String, prefix: String,
input: String, input: String,
) -> Result<ParsedCommand, String> { ) -> Result<ParsedCommand, String> {
let input: SmolStr = input.into(); 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 // end position of all currently matched tokens
let mut current_pos: usize = 0; let mut current_pos: usize = 0;
@ -62,7 +64,7 @@ pub fn parse_command(
// track the best attempt at parsing (deepest matched tokens) // track the best attempt at parsing (deepest matched tokens)
// so we can use it for error messages/suggestions even if we backtrack later // so we can use it for error messages/suggestions even if we backtrack later
let mut best_attempt: Option<(Tree, Vec<MatchedTokenState>, usize)> = None; let mut best_attempt: Option<(Arc<Tree>, Vec<MatchedTokenState>, usize)> = None;
loop { loop {
let mut possible_tokens = local_tree let mut possible_tokens = local_tree

View file

@ -6,8 +6,8 @@ use crate::{command::Command, token::Token};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TreeBranch { pub struct TreeBranch {
current_command: Option<Command>, current_command: Option<Arc<Command>>,
branches: OrderMap<Token, TreeBranch>, branches: OrderMap<Token, Arc<TreeBranch>>,
} }
impl Default for TreeBranch { impl Default for TreeBranch {
@ -45,16 +45,18 @@ impl TreeBranch {
current_branch.register_command(new_command); current_branch.register_command(new_command);
} }
// recursively get or create a sub-branch for each token // recursively get or create a sub-branch for each token
current_branch = current_branch current_branch = Arc::make_mut(
.branches current_branch
.entry(token) .branches
.or_insert_with(TreeBranch::default); .entry(token)
.or_insert_with(|| Arc::new(TreeBranch::default())),
);
} }
// when we're out of tokens add the command to the last branch // 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<Command> { pub fn command(&self) -> Option<Arc<Command>> {
self.current_command.clone() self.current_command.clone()
} }
@ -76,7 +78,7 @@ impl TreeBranch {
let mut commands = box_iter(std::iter::empty()); let mut commands = box_iter(std::iter::empty());
for branch in self.branches.values() { for branch in self.branches.values() {
if let Some(command) = branch.current_command.as_ref() { 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 // we dont need to look further if we found a command
continue; continue;
} }
@ -85,11 +87,11 @@ impl TreeBranch {
commands commands
} }
pub fn get_branch(&self, token: &Token) -> Option<&Self> { pub fn get_branch(&self, token: &Token) -> Option<&Arc<Self>> {
self.branches.get(token) self.branches.get(token)
} }
pub fn branches(&self) -> impl Iterator<Item = (&Token, &Self)> { pub fn branches(&self) -> impl Iterator<Item = (&Token, &Arc<Self>)> {
self.branches.iter() self.branches.iter()
} }
} }

View file

@ -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}; use command_parser::{parameter::ParameterValue, token::TokenMatchResult, Tree};
uniffi::include_scaffolding!("commands"); uniffi::include_scaffolding!("commands");
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref COMMAND_TREE: Tree = { pub static ref COMMAND_TREE: Arc<Tree> = {
let mut tree = Tree::default(); let mut tree = Tree::default();
command_definitions::all().into_iter().for_each(|x| tree.register_command(x)); 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 }, |error| CommandResult::Err { error },
|parsed| CommandResult::Ok { |parsed| CommandResult::Ok {
command: { 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()); let mut flags = HashMap::with_capacity(parsed.flags.capacity());
for (name, value) in parsed.flags { for (name, value) in parsed.flags {
flags.insert(name, value.map(Parameter::from)); flags.insert(name, value.map(Parameter::from));