From d9e52f8d965473517ddf6f11f9ac3be9aa14e14d Mon Sep 17 00:00:00 2001 From: mat Date: Tue, 1 Feb 2022 00:12:46 -0600 Subject: b --- azalea-brigadier/src/builder/argument_builder.rs | 37 +++-- .../src/builder/literal_argument_builder.rs | 29 ++-- .../src/builder/required_argument_builder.rs | 35 +++-- azalea-brigadier/src/command_dispatcher.rs | 1 + azalea-brigadier/src/context/command_context.rs | 4 +- .../src/context/command_context_builder.rs | 21 +-- .../src/context/parsed_command_node.rs | 8 +- azalea-brigadier/src/context/suggestion_context.rs | 4 +- azalea-brigadier/src/string_reader.rs | 14 +- azalea-brigadier/src/tree/argument_command_node.rs | 67 +++++++-- azalea-brigadier/src/tree/command_node.rs | 152 ++++++++++----------- azalea-brigadier/src/tree/literal_command_node.rs | 61 +++++---- azalea-brigadier/src/tree/root_command_node.rs | 31 +++-- 13 files changed, 272 insertions(+), 192 deletions(-) diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs index ec2756ca..d0770be2 100644 --- a/azalea-brigadier/src/builder/argument_builder.rs +++ b/azalea-brigadier/src/builder/argument_builder.rs @@ -4,40 +4,35 @@ use crate::{ redirect_modifier::RedirectModifier, single_redirect_modifier::SingleRedirectModifier, tree::{ - command_node::{BaseCommandNode, CommandNode}, + command_node::{BaseCommandNode, CommandNodeTrait}, root_command_node::RootCommandNode, }, }; +use std::fmt::Debug; -pub struct BaseArgumentBuilder<'a, S> -where - S: Sized, -{ +pub struct BaseArgumentBuilder<'a, S> { arguments: RootCommandNode<'a, S>, command: Option>>, requirement: Box bool>, - target: Option>>, + target: Option>>, modifier: Option>>, forks: bool, } -pub trait ArgumentBuilder -where - T: ArgumentBuilder, -{ - fn build(self) -> Box>; +pub trait ArgumentBuilder { + fn build(self) -> Box>; } impl<'a, S> BaseArgumentBuilder<'a, S> { - pub fn then(&mut self, argument: Box>) -> Result<&mut Self, String> { + pub fn then(&mut self, argument: Box>) -> Result<&mut Self, String> { if self.target.is_some() { return Err("Cannot add children to a redirected node".to_string()); } - + self.arguments.add_child(argument.build()); Ok(self) } - pub fn arguments(&self) -> &Vec<&dyn CommandNode> { + pub fn arguments(&self) -> &Vec<&dyn CommandNodeTrait> { &self.arguments.get_children() } @@ -59,13 +54,13 @@ impl<'a, S> BaseArgumentBuilder<'a, S> { self.requirement } - pub fn redirect(&mut self, target: Box>) -> &mut Self { + pub fn redirect(&mut self, target: Box>) -> &mut Self { self.forward(target, None, false) } pub fn redirect_modifier( &mut self, - target: &dyn CommandNode, + target: &dyn CommandNodeTrait, modifier: &dyn SingleRedirectModifier, ) -> &mut Self { // forward(target, modifier == null ? null : o -> Collections.singleton(modifier.apply(o)), false); @@ -74,7 +69,7 @@ impl<'a, S> BaseArgumentBuilder<'a, S> { pub fn fork( &mut self, - target: &dyn CommandNode, + target: &dyn CommandNodeTrait, modifier: &dyn RedirectModifier, ) -> &mut Self { self.forward(target, Some(modifier), true) @@ -82,20 +77,20 @@ impl<'a, S> BaseArgumentBuilder<'a, S> { pub fn forward( &mut self, - target: Box>, - modifier: Option>>, + target: Option>>, + modifier: Option<&dyn RedirectModifier>, fork: bool, ) -> Result<&mut Self, String> { if !self.arguments.get_children().is_empty() { return Err("Cannot forward a node with children".to_string()); } - self.target = Some(target); + self.target = target; self.modifier = modifier; self.forks = fork; Ok(self) } - pub fn get_redirect(&self) -> Option<&dyn CommandNode> { + pub fn get_redirect(&self) -> Option<&dyn CommandNodeTrait> { self.target.as_ref() } diff --git a/azalea-brigadier/src/builder/literal_argument_builder.rs b/azalea-brigadier/src/builder/literal_argument_builder.rs index 5bceb6eb..8250d45d 100644 --- a/azalea-brigadier/src/builder/literal_argument_builder.rs +++ b/azalea-brigadier/src/builder/literal_argument_builder.rs @@ -4,27 +4,38 @@ use crate::{ command::Command, redirect_modifier::RedirectModifier, tree::{ - command_node::CommandNode, literal_command_node::LiteralCommandNode, + command_node::CommandNodeTrait, literal_command_node::LiteralCommandNode, root_command_node::RootCommandNode, }, }; +use std::fmt::Debug; -pub struct LiteralArgumentBuilder<'a, S> { +pub struct LiteralArgumentBuilder<'a, S> +where + , +{ arguments: RootCommandNode<'a, S>, command: Option>>, requirement: Box bool>, - target: Option>>, + target: Option>>, modifier: Option>>, forks: bool, - literal: String, } -impl<'a, S> LiteralArgumentBuilder<'a, S> { +impl<'a, S> LiteralArgumentBuilder<'a, S> +where + , +{ pub fn new(literal: String) -> Self { Self { literal, - base: BaseArgumentBuilder::default(), + arguments: RootCommandNode::new(), + command: None, + requirement: Box::new(|_| true), + target: None, + modifier: None, + forks: false, } } @@ -33,11 +44,11 @@ impl<'a, S> LiteralArgumentBuilder<'a, S> { } } -impl<'a, S, T> ArgumentBuilder for LiteralArgumentBuilder<'a, S> +impl<'a, S> ArgumentBuilder for LiteralArgumentBuilder<'a, S> where - T: ArgumentBuilder, + , { - fn build(self) -> Box> { + fn build(self) -> Box> { let result = LiteralCommandNode::new(self.literal, self.base.build()); for argument in self.base.arguments() { diff --git a/azalea-brigadier/src/builder/required_argument_builder.rs b/azalea-brigadier/src/builder/required_argument_builder.rs index b577f3ed..fe6f2ecc 100644 --- a/azalea-brigadier/src/builder/required_argument_builder.rs +++ b/azalea-brigadier/src/builder/required_argument_builder.rs @@ -1,17 +1,23 @@ +use super::argument_builder::BaseArgumentBuilder; use crate::{ arguments::argument_type::ArgumentType, + command::Command, + redirect_modifier::RedirectModifier, suggestion::suggestion_provider::SuggestionProvider, - tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode}, + tree::{ + argument_command_node::ArgumentCommandNode, + command_node::{BaseCommandNode, CommandNodeTrait}, + root_command_node::RootCommandNode, + }, }; use std::any::Any; - -use super::argument_builder::BaseArgumentBuilder; +use std::fmt::Debug; pub struct RequiredArgumentBuilder<'a, S> { arguments: RootCommandNode<'a, S>, command: Option>>, requirement: Box bool>, - target: Option>>, + target: Option>>, modifier: Option>>, forks: bool, @@ -26,7 +32,12 @@ impl<'a, S> RequiredArgumentBuilder<'a, S> { name, type_: type_, suggestions_provider: None, - base: BaseArgumentBuilder::default(), + arguments: RootCommandNode::new(), + command: None, + requirement: Box::new(|_| true), + target: None, + modifier: None, + forks: false, } } @@ -62,15 +73,13 @@ impl<'a, S> RequiredArgumentBuilder<'a, S> { let result = ArgumentCommandNode { name: self.name, type_: self.type_, - base: BaseCommandNode { - command: self.base.command(), - requirement: self.base.requirement(), - redirect: self.base.get_redirect(), - modifier: self.base.get_redirect_modifier(), - forks: self.base.forks, - ..BaseCommandNode::default() - }, + command: self.base.command(), + requirement: self.base.requirement(), + redirect: self.base.get_redirect(), + modifier: self.base.get_redirect_modifier(), + forks: self.base.forks, custom_suggestions: self.base.custom_suggestions, + ..ArgumentCommandNode::default() }; for argument in self.base.arguments() { diff --git a/azalea-brigadier/src/command_dispatcher.rs b/azalea-brigadier/src/command_dispatcher.rs index 72a353ad..98288a48 100644 --- a/azalea-brigadier/src/command_dispatcher.rs +++ b/azalea-brigadier/src/command_dispatcher.rs @@ -1,4 +1,5 @@ use crate::{arguments::argument_type::ArgumentType, tree::root_command_node::RootCommandNode}; +use std::fmt::Debug; /// The core command dispatcher, for registering, parsing, and executing commands. /// The `S` generic is a custom "source" type, such as a user or originator of a command diff --git a/azalea-brigadier/src/context/command_context.rs b/azalea-brigadier/src/context/command_context.rs index 4f0b4d49..8db1487f 100644 --- a/azalea-brigadier/src/context/command_context.rs +++ b/azalea-brigadier/src/context/command_context.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier, - tree::command_node::CommandNode, + tree::command_node::CommandNodeTrait, }; use std::{any::Any, collections::HashMap}; @@ -13,7 +13,7 @@ pub struct CommandContext<'a, S> { input: String, command: &'a dyn Command, arguments: HashMap>>, - root_node: &'a dyn CommandNode, + root_node: &'a dyn CommandNodeTrait, nodes: Vec>, range: StringRange, child: Option<&'a CommandContext<'a, S>>, diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs index 95da4064..969f9cfd 100644 --- a/azalea-brigadier/src/context/command_context_builder.rs +++ b/azalea-brigadier/src/context/command_context_builder.rs @@ -1,10 +1,10 @@ -use std::{any::Any, collections::HashMap}; - use crate::{ arguments::argument_type::ArgumentType, command::Command, command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier, - tree::command_node::CommandNode, + tree::command_node::CommandNodeTrait, }; +use std::fmt::Debug; +use std::{any::Any, collections::HashMap}; use super::{ command_context::CommandContext, parsed_argument::ParsedArgument, @@ -27,12 +27,12 @@ use super::{ #[derive(Clone)] pub struct CommandContextBuilder<'a, S> { arguments: HashMap>>, - root_node: &'a dyn CommandNode, + root_node: &'a dyn CommandNodeTrait, nodes: Vec>, dispatcher: CommandDispatcher<'a, S>, source: S, command: Box>, - child: Option>, + child: Box>>, range: StringRange, modifier: Option>>, forks: bool, @@ -45,11 +45,14 @@ pub struct CommandContextBuilder<'a, S> { // this.range = StringRange.at(start); // } -impl CommandContextBuilder<'_, S> { +impl CommandContextBuilder<'_, S> +where + , +{ pub fn new( dispatcher: CommandDispatcher, source: S, - root_node: dyn CommandNode, + root_node: dyn CommandNodeTrait, start: usize, ) -> Self { Self { @@ -70,7 +73,7 @@ impl CommandContextBuilder<'_, S> { &self.source } - pub fn root_node(&self) -> &dyn CommandNode { + pub fn root_node(&self) -> &dyn CommandNodeTrait { &self.root_node } @@ -88,7 +91,7 @@ impl CommandContextBuilder<'_, S> { self } - pub fn with_node(mut self, node: dyn CommandNode, range: StringRange) -> Self { + pub fn with_node(mut self, node: dyn CommandNodeTrait, range: StringRange) -> Self { self.nodes.push(ParsedCommandNode::new(node, range)); self.range = StringRange::encompassing(&self.range, &range); self.modifier = node.redirect_modifier(); diff --git a/azalea-brigadier/src/context/parsed_command_node.rs b/azalea-brigadier/src/context/parsed_command_node.rs index 16c6ed8b..21d1b2e9 100644 --- a/azalea-brigadier/src/context/parsed_command_node.rs +++ b/azalea-brigadier/src/context/parsed_command_node.rs @@ -1,17 +1,17 @@ use super::string_range::StringRange; -use crate::tree::command_node::CommandNode; +use crate::tree::command_node::CommandNodeTrait; pub struct ParsedCommandNode { - node: Box>, + node: Box>, range: StringRange, } impl ParsedCommandNode { - fn new(node: dyn CommandNode, range: StringRange) -> Self { + fn new(node: dyn CommandNodeTrait, range: StringRange) -> Self { Self { node, range } } - fn node(&self) -> &dyn CommandNode { + fn node(&self) -> &dyn CommandNodeTrait { &self.node } diff --git a/azalea-brigadier/src/context/suggestion_context.rs b/azalea-brigadier/src/context/suggestion_context.rs index 252cb6ed..51a053c1 100644 --- a/azalea-brigadier/src/context/suggestion_context.rs +++ b/azalea-brigadier/src/context/suggestion_context.rs @@ -1,6 +1,6 @@ -use crate::tree::command_node::CommandNode; +use crate::tree::command_node::CommandNodeTrait; pub struct SuggestionContext<'a, S> { - parent: &'a dyn CommandNode, + parent: &'a dyn CommandNodeTrait, start_pos: usize, } diff --git a/azalea-brigadier/src/string_reader.rs b/azalea-brigadier/src/string_reader.rs index f32de473..694edccb 100644 --- a/azalea-brigadier/src/string_reader.rs +++ b/azalea-brigadier/src/string_reader.rs @@ -9,7 +9,7 @@ use std::str::FromStr; #[derive(Clone)] pub struct StringReader<'a> { string: &'a str, - cursor: usize, + pub cursor: usize, } const SYNTAX_ESCAPE: char = '\\'; @@ -18,9 +18,15 @@ const SYNTAX_SINGLE_QUOTE: char = '\''; // impl<'a> From<&'a str> for &StringReader<'a> {} -impl StringReader<'_> { - fn from(string: &str) -> StringReader { - StringReader { string, cursor: 0 } +// impl StringReader<'_> { +// fn from(string: &str) -> StringReader { +// StringReader { string, cursor: 0 } +// } +// } + +impl<'a> From<&'a str> for StringReader<'a> { + fn from(string: &'a str) -> Self { + Self { string, cursor: 0 } } } diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs index e33c3d3e..0997ec17 100644 --- a/azalea-brigadier/src/tree/argument_command_node.rs +++ b/azalea-brigadier/src/tree/argument_command_node.rs @@ -1,17 +1,20 @@ use std::{ any::Any, - fmt::{Display, Formatter}, + collections::HashMap, + fmt::{Debug, Display, Formatter}, }; use crate::{ arguments::argument_type::ArgumentType, builder::required_argument_builder::RequiredArgumentBuilder, + command::Command, context::{ command_context::CommandContext, command_context_builder::CommandContextBuilder, parsed_argument::ParsedArgument, }, exceptions::command_syntax_exception::CommandSyntaxException, immutable_string_reader::ImmutableStringReader, + redirect_modifier::RedirectModifier, string_reader::StringReader, suggestion::{ suggestion_provider::SuggestionProvider, suggestions::Suggestions, @@ -19,12 +22,16 @@ use crate::{ }, }; -use super::command_node::{BaseCommandNode, CommandNode}; +use super::{ + command_node::{BaseCommandNode, CommandNodeTrait}, + literal_command_node::LiteralCommandNode, + root_command_node::RootCommandNode, +}; const USAGE_ARGUMENT_OPEN: &str = "<"; const USAGE_ARGUMENT_CLOSE: &str = ">"; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ArgumentCommandNode<'a, S> { name: String, type_: Box>, @@ -32,6 +39,15 @@ pub struct ArgumentCommandNode<'a, S> { // custom_suggestions: &'a dyn SuggestionProvider, // Since Rust doesn't have extending, we put the struct this is extending as the "base" field pub base: BaseCommandNode<'a, S>, + + children: HashMap>>, + literals: HashMap>, + arguments: HashMap>, + pub requirement: Box bool>, + redirect: Option>>, + modifier: Option>>, + forks: bool, + pub command: Option>>, } impl ArgumentCommandNode<'_, S> { @@ -44,10 +60,7 @@ impl ArgumentCommandNode<'_, S> { } } -impl<'a, S> CommandNode for ArgumentCommandNode<'a, S> -where - S: Clone, -{ +impl<'a, S> CommandNodeTrait for ArgumentCommandNode<'a, S> { fn name(&self) -> &str { &self.name } @@ -119,8 +132,44 @@ where self.type_.get_examples() } - fn base(&self) -> &BaseCommandNode { - &self.base + fn redirect_modifier(&self) -> Option<&dyn RedirectModifier> { + self.modifier.as_ref().map(|modifier| modifier.as_ref()) + } + + fn can_use(&self, source: S) -> bool { + (self.requirement)(&source) + } + + fn add_child(&self, node: &Box>) -> Result<(), String> { + let dynamic_node = node as &dyn Any; + if dynamic_node.is::>() { + return Err(String::from( + "Cannot add a RootCommandNode as a child to any other CommandNode", + )); + } + + 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.base_mut().command = Some(*command); + } + 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(dynamic_node) = dynamic_node.downcast_ref::>() { + self.literals.insert(node.name().to_string(), *dynamic_node); + } else if let Some(dynamic_node) = dynamic_node.downcast_ref::>() + { + self.arguments + .insert(node.name().to_string(), *dynamic_node); + } + Ok(()) + } } } 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>>, - literals: HashMap>, - arguments: HashMap>, - requirement: Box bool>, - redirect: Option>>, - modifier: Option>>, - forks: bool, - command: Option>>, +enum CommandNodeEnum<'a, S> { + Literal(LiteralCommandNode<'a, S>), + Argument(ArgumentCommandNode<'a, S>), + Root(RootCommandNode<'a, S>), } -impl BaseCommandNode<'_, S> { - pub fn command(&self) -> &Option>> { - &self.command +impl Deref for CommandNodeEnum<'_, S> { + type Target = dyn CommandNodeTrait; + + fn deref(&self) -> &Self::Target { + match self { + CommandNodeEnum::Literal(node) => node, + CommandNodeEnum::Argument(node) => node, + CommandNodeEnum::Root(node) => node, + } } +} - pub fn children(&self) -> &HashMap>> { - &self.children +impl From> for CommandNodeEnum<'_, S> { + fn from(node: LiteralCommandNode<'_, S>) -> Self { + CommandNodeEnum::Literal(node) } +} - pub fn child(&self, name: &str) -> Option<&dyn CommandNode> { - self.children.get(name).map(|child| child.as_ref()) +impl From> for CommandNodeEnum<'_, S> { + fn from(node: ArgumentCommandNode<'_, S>) -> Self { + CommandNodeEnum::Argument(node) } +} - pub fn redirect(&self) -> Option<&dyn CommandNode> { - self.redirect.as_ref().map(|redirect| redirect.as_ref()) +impl From> for CommandNodeEnum<'_, S> { + fn from(node: RootCommandNode<'_, S>) -> Self { + CommandNodeEnum::Root(node) } +} - pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier> { - self.modifier.as_ref().map(|modifier| modifier.as_ref()) +impl CommandNodeEnum<'_, S> { + fn redirect_modifier(&self) -> Option<&dyn RedirectModifier> { + (*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 node) { - // if (node instanceof RootCommandNode) { - // throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode"); - // } - - // final CommandNode 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 grandchild : node.getChildren()) { - // child.addChild(grandchild); - // } - // } else { - // children.put(node.getName(), node); - // if (node instanceof LiteralCommandNode) { - // literals.put(node.getName(), (LiteralCommandNode) node); - // } else if (node instanceof ArgumentCommandNode) { - // arguments.put(node.getName(), (ArgumentCommandNode) node); - // } - // } - // } - - pub fn add_child(&self, node: &dyn CommandNode) -> Result<(), String> { - if (&node as &dyn Any).is::>() { + fn add_child(&self, node: &Box>) -> Result<(), String> { + let dynamic_node = node as &dyn Any; + if dynamic_node.is::>() { 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 - { - 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 + self.children.insert(node.name().to_string(), *node); + + if let Some(dynamic_node) = dynamic_node.downcast_ref::>() { + self.literals.insert(node.name().to_string(), *dynamic_node); + } else if let Some(dynamic_node) = dynamic_node.downcast_ref::>() { self.arguments - .insert(node.name().to_string(), argument.clone_boxed()); + .insert(node.name().to_string(), *dynamic_node); } + Ok(()) } } } - -impl 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>>, + literals: HashMap>, + arguments: HashMap>, + pub requirement: Box bool>, + redirect: Option>>, + modifier: Option>>, + forks: bool, + pub command: Option>>, } +// impl 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 Debug for BaseCommandNode<'_, S> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("BaseCommandNode") @@ -153,7 +148,7 @@ impl Default for BaseCommandNode<'_, S> { } } -pub trait CommandNode { +pub trait CommandNodeTrait { fn name(&self) -> &str; fn usage_text(&self) -> &str; fn parse( @@ -167,7 +162,6 @@ pub trait CommandNode { builder: &SuggestionsBuilder, ) -> Result; fn is_valid_input(&self, input: &str) -> bool; - fn create_builder(&self) -> dyn ArgumentBuilder; + fn create_builder(&self) -> Box>; fn get_examples(&self) -> Vec; - fn base(&self) -> &BaseCommandNode; } diff --git a/azalea-brigadier/src/tree/literal_command_node.rs b/azalea-brigadier/src/tree/literal_command_node.rs index a722121f..253b6dc5 100644 --- a/azalea-brigadier/src/tree/literal_command_node.rs +++ b/azalea-brigadier/src/tree/literal_command_node.rs @@ -1,17 +1,19 @@ use crate::{ arguments::argument_type::ArgumentType, - builder::literal_argument_builder::LiteralArgumentBuilder, - command::Command, + builder::{ + argument_builder::ArgumentBuilder, literal_argument_builder::LiteralArgumentBuilder, + }, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, exceptions::{ builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, }, - redirect_modifier::RedirectModifier, + immutable_string_reader::ImmutableStringReader, string_reader::StringReader, suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, }; +use std::fmt::Debug; -use super::command_node::{BaseCommandNode, CommandNode}; +use super::command_node::{BaseCommandNode, CommandNodeTrait}; #[derive(Debug, Clone)] pub struct LiteralCommandNode<'a, S> { @@ -22,7 +24,7 @@ pub struct LiteralCommandNode<'a, S> { } impl<'a, S> LiteralCommandNode<'a, S> { - pub fn new(literal: String, base: BaseCommandNode) -> Self { + pub fn new(literal: String, base: BaseCommandNode<'a, S>) -> Self { let literal_lowercase = literal.to_lowercase(); Self { literal, @@ -35,16 +37,16 @@ impl<'a, S> LiteralCommandNode<'a, S> { &self.literal } - pub fn parse(&self, reader: StringReader) -> i32 { - let start = reader.get_cursor(); - if reader.can_read(self.literal.len()) { + pub fn parse(&self, reader: &mut StringReader) -> i32 { + let start = reader.cursor(); + if reader.can_read_length(self.literal.len()) { let end = start + self.literal.len(); - if reader.get_string()[start..end].eq(&self.literal) { - reader.set_cursor(end); + if reader.string()[start..end].eq(&self.literal) { + reader.cursor = end; if !reader.can_read() || reader.peek() == ' ' { return end as i32; } else { - reader.set_cursor(start); + reader.cursor = start; } } } @@ -52,27 +54,24 @@ impl<'a, S> LiteralCommandNode<'a, S> { } } -impl CommandNode for LiteralCommandNode<'_, S> -where - S: Clone, -{ +impl CommandNodeTrait for LiteralCommandNode<'_, S> { fn name(&self) -> &str { &self.literal } fn parse( &self, - reader: StringReader, + reader: &mut StringReader<'_>, context_builder: CommandContextBuilder, ) -> Result<(), CommandSyntaxException> { - let start = reader.get_cursor(); + let start = reader.cursor(); let end = self.parse(reader); if end > -1 { return Ok(()); } Err(BuiltInExceptions::LiteralIncorrect { - expected: self.literal(), + expected: self.literal().to_string(), } .create_with_context(reader)) } @@ -80,33 +79,41 @@ where fn list_suggestions( &self, context: CommandContext, - builder: SuggestionsBuilder, + builder: &SuggestionsBuilder, ) -> Result { if self .literal_lowercase .starts_with(&builder.remaining_lowercase()) { - builder.suggest(self.literal()) + Ok(builder.suggest(self.literal()).build()) } else { - Suggestions::empty() + Ok(Suggestions::default()) } } fn is_valid_input(&self, input: &str) -> bool { - self.parse(StringReader::from(input)) > -1 + self.parse(&mut StringReader::from(input)) > -1 } fn usage_text(&self) -> &str { - self.literal + &self.literal } - fn create_builder(&self) -> LiteralArgumentBuilder { - let builder = LiteralArgumentBuilder::literal(self.literal()); - builder.requires(self.requirement()); - builder.forward(self.redirect(), self.redirect_modifier(), self.is_fork()); + fn create_builder(&self) -> Box> { + let mut builder = LiteralArgumentBuilder::literal(self.literal().to_string()); + builder.base.requires(&self.base().requirement); + builder.base.forward( + self.base.redirect(), + self.base.redirect_modifier(), + self.base.is_fork(), + ); if self.command().is_some() { builder.executes(self.command().unwrap()); } builder } + + fn get_examples(&self) -> Vec { + todo!() + } } diff --git a/azalea-brigadier/src/tree/root_command_node.rs b/azalea-brigadier/src/tree/root_command_node.rs index c3139a05..0fcb8d97 100644 --- a/azalea-brigadier/src/tree/root_command_node.rs +++ b/azalea-brigadier/src/tree/root_command_node.rs @@ -1,44 +1,49 @@ -use std::fmt::{Display, Formatter}; - +use super::{ + argument_command_node::ArgumentCommandNode, + command_node::{BaseCommandNode, CommandNodeTrait}, + literal_command_node::LiteralCommandNode, +}; use crate::{ arguments::argument_type::ArgumentType, + builder::argument_builder::ArgumentBuilder, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, exceptions::{ builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, }, + redirect_modifier::RedirectModifier, string_reader::StringReader, suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, }; +use std::{ + any::Any, + fmt::{Debug, Display, Formatter}, +}; -use super::command_node::{BaseCommandNode, CommandNode}; - -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct RootCommandNode<'a, S> { // Since Rust doesn't have extending, we put the struct this is extending as the "base" field pub base: BaseCommandNode<'a, S>, } -impl CommandNode for RootCommandNode<'_, S> -where - S: Clone, -{ +impl CommandNodeTrait for RootCommandNode<'_, S> { fn name(&self) -> &str { "" } fn parse( &self, - reader: StringReader, + reader: &mut StringReader<'_>, context_builder: CommandContextBuilder, ) -> Result<(), CommandSyntaxException> { + Ok(()) } fn list_suggestions( &self, context: CommandContext, - builder: SuggestionsBuilder, + builder: &SuggestionsBuilder, ) -> Result { - Suggestions::empty() + Ok(Suggestions::default()) } fn is_valid_input(&self, input: &str) -> bool { @@ -49,7 +54,7 @@ where "" } - fn create_builder(&self) -> () { + fn create_builder(&self) -> Box> { panic!("Cannot convert root into a builder"); } -- cgit v1.2.3