diff options
Diffstat (limited to 'azalea-brigadier/src/tree/command_node.rs')
| -rw-r--r-- | azalea-brigadier/src/tree/command_node.rs | 152 |
1 files changed, 73 insertions, 79 deletions
diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs index f59b1cef..b7801363 100644 --- a/azalea-brigadier/src/tree/command_node.rs +++ b/azalea-brigadier/src/tree/command_node.rs @@ -12,117 +12,112 @@ use crate::{ string_reader::StringReader, suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, }; -use dyn_clonable::*; +use std::ops::Deref; use std::{any::Any, collections::HashMap, fmt::Debug}; -pub struct BaseCommandNode<'a, S> { - children: HashMap<String, Box<dyn CommandNode<S>>>, - literals: HashMap<String, LiteralCommandNode<'a, S>>, - arguments: HashMap<String, ArgumentCommandNode<'a, S>>, - requirement: Box<dyn Fn(&S) -> bool>, - redirect: Option<Box<dyn CommandNode<S>>>, - modifier: Option<Box<dyn RedirectModifier<S>>>, - forks: bool, - command: Option<Box<dyn Command<S>>>, +enum CommandNodeEnum<'a, S> { + Literal(LiteralCommandNode<'a, S>), + Argument(ArgumentCommandNode<'a, S>), + Root(RootCommandNode<'a, S>), } -impl<S> BaseCommandNode<'_, S> { - pub fn command(&self) -> &Option<Box<dyn Command<S>>> { - &self.command +impl<S> Deref for CommandNodeEnum<'_, S> { + type Target = dyn CommandNodeTrait<S>; + + fn deref(&self) -> &Self::Target { + match self { + CommandNodeEnum::Literal(node) => node, + CommandNodeEnum::Argument(node) => node, + CommandNodeEnum::Root(node) => node, + } } +} - pub fn children(&self) -> &HashMap<String, Box<dyn CommandNode<S>>> { - &self.children +impl<S> From<LiteralCommandNode<'_, S>> for CommandNodeEnum<'_, S> { + fn from(node: LiteralCommandNode<'_, S>) -> Self { + CommandNodeEnum::Literal(node) } +} - pub fn child(&self, name: &str) -> Option<&dyn CommandNode<S>> { - self.children.get(name).map(|child| child.as_ref()) +impl<S> From<ArgumentCommandNode<'_, S>> for CommandNodeEnum<'_, S> { + fn from(node: ArgumentCommandNode<'_, S>) -> Self { + CommandNodeEnum::Argument(node) } +} - pub fn redirect(&self) -> Option<&dyn CommandNode<S>> { - self.redirect.as_ref().map(|redirect| redirect.as_ref()) +impl<S> From<RootCommandNode<'_, S>> for CommandNodeEnum<'_, S> { + fn from(node: RootCommandNode<'_, S>) -> Self { + CommandNodeEnum::Root(node) } +} - pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> { - self.modifier.as_ref().map(|modifier| modifier.as_ref()) +impl<S> CommandNodeEnum<'_, S> { + fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> { + (*self).modifier.as_ref().map(|modifier| modifier.as_ref()) } - pub fn can_use(&self, source: S) -> bool { + fn can_use(&self, source: S) -> bool { (self.requirement)(&source) } - // public void addChild(final CommandNode<S> node) { - // if (node instanceof RootCommandNode) { - // throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode"); - // } - - // final CommandNode<S> child = children.get(node.getName()); - // if (child != null) { - // // We've found something to merge onto - // if (node.getCommand() != null) { - // child.command = node.getCommand(); - // } - // for (final CommandNode<S> grandchild : node.getChildren()) { - // child.addChild(grandchild); - // } - // } else { - // children.put(node.getName(), node); - // if (node instanceof LiteralCommandNode) { - // literals.put(node.getName(), (LiteralCommandNode<S>) node); - // } else if (node instanceof ArgumentCommandNode) { - // arguments.put(node.getName(), (ArgumentCommandNode<S, ?>) node); - // } - // } - // } - - pub fn add_child(&self, node: &dyn CommandNode<S>) -> Result<(), String> { - if (&node as &dyn Any).is::<RootCommandNode<S>>() { + fn add_child(&self, node: &Box<dyn CommandNodeTrait<S>>) -> Result<(), String> { + let dynamic_node = node as &dyn Any; + if dynamic_node.is::<RootCommandNode<S>>() { return Err(String::from( "Cannot add a RootCommandNode as a child to any other CommandNode", )); } - let child = self.children.get(node.name()); + let mut child = self.children.get(node.name()); if let Some(child) = child { // We've found something to merge onto - if let Some(command) = node.base.command() { - child.command = Some(command); + if let Some(command) = node.base().command() { + child.base_mut().command = Some(*command); } - for grandchild in node.children() { - child.add_child(grandchild)?; + for grandchild in node.base().children().values() { + child.base_mut().add_child(&*grandchild)?; } + Ok(()) } else { - self.children.insert(node.name().to_string(), node); - if let Some(literal) = - &node.clone_boxed() as &dyn Any as &dyn Any as &LiteralCommandNode<S> - { - self.literals - .insert(node.name().to_string(), literal.clone_boxed()); - } else if let Some(argument) = - &node.clone_boxed() as &dyn Any as &dyn Any as &ArgumentCommandNode<S> + self.children.insert(node.name().to_string(), *node); + + if let Some(dynamic_node) = dynamic_node.downcast_ref::<LiteralCommandNode<S>>() { + self.literals.insert(node.name().to_string(), *dynamic_node); + } else if let Some(dynamic_node) = dynamic_node.downcast_ref::<ArgumentCommandNode<S>>() { self.arguments - .insert(node.name().to_string(), argument.clone_boxed()); + .insert(node.name().to_string(), *dynamic_node); } + Ok(()) } } } - -impl<S> Clone for BaseCommandNode<'_, S> { - fn clone(&self) -> Self { - Self { - children: self.children.clone(), - literals: self.literals.clone(), - arguments: self.arguments.clone(), - requirement: self.requirement.clone(), - redirect: self.redirect.clone(), - modifier: self.modifier.clone(), - forks: self.forks.clone(), - command: self.command.clone(), - } - } +pub struct BaseCommandNode<'a, S> { + children: HashMap<String, Box<dyn CommandNodeTrait<S>>>, + literals: HashMap<String, LiteralCommandNode<'a, S>>, + arguments: HashMap<String, ArgumentCommandNode<'a, S>>, + pub requirement: Box<dyn Fn(&S) -> bool>, + redirect: Option<Box<dyn CommandNodeTrait<S>>>, + modifier: Option<Box<dyn RedirectModifier<S>>>, + forks: bool, + pub command: Option<Box<dyn Command<S>>>, } +// impl<S> Clone for BaseCommandNode<'_, S> { +// fn clone(&self) -> Self { +// Self { +// children: self.children.clone(), +// literals: self.literals.clone(), +// arguments: self.arguments.clone(), +// requirement: self.requirement.clone(), +// redirect: self.redirect.clone(), +// modifier: self.modifier.clone(), +// forks: self.forks.clone(), +// command: self.command.clone(), +// } +// } +// } + impl<S> Debug for BaseCommandNode<'_, S> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("BaseCommandNode") @@ -153,7 +148,7 @@ impl<S> Default for BaseCommandNode<'_, S> { } } -pub trait CommandNode<S> { +pub trait CommandNodeTrait<S> { fn name(&self) -> &str; fn usage_text(&self) -> &str; fn parse( @@ -167,7 +162,6 @@ pub trait CommandNode<S> { builder: &SuggestionsBuilder, ) -> Result<Suggestions, CommandSyntaxException>; fn is_valid_input(&self, input: &str) -> bool; - fn create_builder(&self) -> dyn ArgumentBuilder<S, dyn Any>; + fn create_builder(&self) -> Box<dyn ArgumentBuilder<S>>; fn get_examples(&self) -> Vec<String>; - fn base(&self) -> &BaseCommandNode<S>; } |
