aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/tree/command_node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-brigadier/src/tree/command_node.rs')
-rw-r--r--azalea-brigadier/src/tree/command_node.rs152
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>;
}