diff options
| author | mat <github@matdoes.dev> | 2022-04-17 14:02:13 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-04-17 14:02:13 -0500 |
| commit | a72a47ced76065caf739898954cd18edbc39174b (patch) | |
| tree | 5526c7663f253bbd7c8318b9d98413f1f2074852 /azalea-brigadier/src/tree | |
| parent | 4ff67d4917ce333232189e86aee09f2d82451fc6 (diff) | |
| download | azalea-drasl-a72a47ced76065caf739898954cd18edbc39174b.tar.xz | |
Rewrite brigadier
Diffstat (limited to 'azalea-brigadier/src/tree')
| -rw-r--r-- | azalea-brigadier/src/tree/argument_command_node.rs | 176 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/command_node.rs | 143 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/literal_command_node.rs | 131 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/mod.rs | 4 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/root_command_node.rs | 79 |
5 files changed, 0 insertions, 533 deletions
diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs deleted file mode 100644 index 9d2af14e..00000000 --- a/azalea-brigadier/src/tree/argument_command_node.rs +++ /dev/null @@ -1,176 +0,0 @@ -use std::{ - any::Any, - 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, - suggestions_builder::SuggestionsBuilder, - }, -}; - -use super::{ - command_node::{BaseCommandNode, CommandNodeTrait}, - literal_command_node::LiteralCommandNode, - root_command_node::RootCommandNode, -}; - -const USAGE_ARGUMENT_OPEN: &str = "<"; -const USAGE_ARGUMENT_CLOSE: &str = ">"; - -pub struct ArgumentCommandNode<S> { - name: String, - type_: Box<dyn ArgumentType<Into = dyn Any>>, - custom_suggestions: Option<Box<dyn SuggestionProvider<S>>>, - - children: HashMap<String, Box<dyn CommandNodeTrait<S>>>, - literals: HashMap<String, LiteralCommandNode<S>>, - arguments: HashMap<String, ArgumentCommandNode<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> ArgumentCommandNode<S> { - fn get_type(&self) -> &dyn ArgumentType<Into = dyn Any> { - &*self.type_ - } - - fn custom_suggestions(&self) -> &Option<Box<dyn SuggestionProvider<S>>> { - &self.custom_suggestions - } -} - -impl<S> CommandNodeTrait<S> for ArgumentCommandNode<S> { - fn name(&self) -> &str { - &self.name - } - - fn parse( - &self, - reader: &mut StringReader, - context_builder: CommandContextBuilder<S>, - ) -> Result<(), CommandSyntaxException> { - // final int start = reader.getCursor(); - // final T result = type.parse(reader); - // final ParsedArgument<S> parsed = new ParsedArgument<>(start, reader.getCursor(), result); - - // contextBuilder.withArgument(name, parsed); - // contextBuilder.withNode(this, parsed.getRange()); - - let start = reader.cursor(); - let result = self.get_type().parse(reader)?; - let parsed = ParsedArgument::new(start, reader.get_cursor(), result); - - context_builder.with_argument(&self.name, parsed); - context_builder.with_node(self, parsed.get_range()); - - Ok(()) - } - - fn list_suggestions( - &self, - context: CommandContext<S>, - builder: &SuggestionsBuilder, - ) -> Result<Suggestions, CommandSyntaxException> { - if self.custom_suggestions.is_none() { - self.get_type().list_suggestions(context, builder) - } else { - self.custom_suggestions.get_suggestions(context, builder) - } - } - - fn is_valid_input(&self, input: &str) -> bool { - let reader = StringReader::new(input); - let result = self.get_type().parse(reader); - if result.is_ok() { - return !reader.can_read() || reader.peek() == ' '; - } else { - return false; - } - } - - fn usage_text(&self) -> &str { - USAGE_ARGUMENT_OPEN + self.name + USAGE_ARGUMENT_CLOSE - } - - fn create_builder(&self) -> RequiredArgumentBuilder<S> { - let builder = RequiredArgumentBuilder::argument(&self.name, &self.type_); - builder.requires(self.base.get_requirement()); - builder.forward( - self.base.get_redirect(), - self.base.get_redirect_modifier(), - self.base.is_fork(), - ); - builder.suggests(self.custom_suggestions()); - if self.base.get_command() != None { - builder.executes(self.base.get_command().unwrap()); - } - builder - } - - fn get_examples(&self) -> Vec<String> { - self.type_.get_examples() - } - - fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> { - 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<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 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::<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(), *dynamic_node); - } - Ok(()) - } - } -} - -impl<S> Display for ArgumentCommandNode<S> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "<argument {}: {}>", self.name, self.type_) - } -} diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs deleted file mode 100644 index 207e114e..00000000 --- a/azalea-brigadier/src/tree/command_node.rs +++ /dev/null @@ -1,143 +0,0 @@ -use super::{ - argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode, - root_command_node::RootCommandNode, -}; -use crate::{ - arguments::argument_type::ArgumentType, - builder::argument_builder::ArgumentBuilder, - command::Command, - context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, - exceptions::command_syntax_exception::CommandSyntaxException, - redirect_modifier::RedirectModifier, - string_reader::StringReader, - suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, -}; -use std::ops::Deref; -use std::{any::Any, collections::HashMap, fmt::Debug}; - -#[enum_dispatch(CommandNodeTrait)] -enum CommandNodeEnum<S> { - Literal(LiteralCommandNode<S>), - Argument(ArgumentCommandNode<S>), - Root(RootCommandNode<S>), -} - -impl<S> CommandNodeEnum<S> { - fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> { - (*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<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 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::<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(), *dynamic_node); - } - Ok(()) - } - } -} -pub struct BaseCommandNode<S> { - children: HashMap<String, Box<dyn CommandNodeTrait<S>>>, - literals: HashMap<String, LiteralCommandNode<S>>, - arguments: HashMap<String, ArgumentCommandNode<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") - .field("children", &self.children) - .field("literals", &self.literals) - .field("arguments", &self.arguments) - .field("requirement", &self.requirement) - .field("redirect", &self.redirect) - .field("modifier", &self.modifier) - .field("forks", &self.forks) - .field("command", &self.command) - .finish() - } -} - -impl<S> Default for BaseCommandNode<S> { - fn default() -> Self { - Self { - children: HashMap::new(), - literals: HashMap::new(), - arguments: HashMap::new(), - requirement: Box::new(|_| true), - redirect: None, - modifier: None, - forks: false, - command: None, - } - } -} - -#[enum_dispatch] -pub trait CommandNodeTrait<S> { - fn name(&self) -> &str; - fn usage_text(&self) -> &str; - fn parse( - &self, - reader: &mut StringReader, - context_builder: CommandContextBuilder<S>, - ) -> Result<(), CommandSyntaxException>; - fn list_suggestions( - &self, - context: CommandContext<S>, - builder: &SuggestionsBuilder, - ) -> Result<Suggestions, CommandSyntaxException>; - fn is_valid_input(&self, input: &str) -> bool; - fn create_builder(&self) -> Box<dyn ArgumentBuilder<S>>; - fn get_examples(&self) -> Vec<String>; - - fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>>; - fn can_use(&self, source: S) -> bool; - fn add_child(&self, node: &Box<dyn CommandNodeTrait<S>>) -> Result<(), String>; -} diff --git a/azalea-brigadier/src/tree/literal_command_node.rs b/azalea-brigadier/src/tree/literal_command_node.rs deleted file mode 100644 index 2db31d97..00000000 --- a/azalea-brigadier/src/tree/literal_command_node.rs +++ /dev/null @@ -1,131 +0,0 @@ -use crate::{ - arguments::argument_type::ArgumentType, - builder::{ - argument_builder::ArgumentBuilder, literal_argument_builder::LiteralArgumentBuilder, - }, - command::Command, - context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, - exceptions::{ - builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, - }, - immutable_string_reader::ImmutableStringReader, - redirect_modifier::RedirectModifier, - string_reader::StringReader, - suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, -}; -use std::{collections::HashMap, fmt::Debug}; - -use super::{ - argument_command_node::ArgumentCommandNode, - command_node::{BaseCommandNode, CommandNodeTrait}, -}; - -#[derive(Debug, Clone)] -pub struct LiteralCommandNode<S> { - literal: String, - literal_lowercase: String, - - children: HashMap<String, Box<dyn CommandNodeTrait<S>>>, - literals: HashMap<String, LiteralCommandNode<S>>, - arguments: HashMap<String, ArgumentCommandNode<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> LiteralCommandNode<S> { - pub fn new(literal: String) -> Self { - let literal_lowercase = literal.to_lowercase(); - Self { - literal, - literal_lowercase, - ..Default::default() - } - } - - pub fn literal(&self) -> &String { - &self.literal - } - - 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.string()[start..end].eq(&self.literal) { - reader.cursor = end; - if !reader.can_read() || reader.peek() == ' ' { - return end as i32; - } else { - reader.cursor = start; - } - } - } - -1 - } -} - -impl<S> CommandNodeTrait<S> for LiteralCommandNode<S> { - fn name(&self) -> &str { - &self.literal - } - - fn parse( - &self, - reader: &mut StringReader<'_>, - context_builder: CommandContextBuilder<S>, - ) -> Result<(), CommandSyntaxException> { - let start = reader.cursor(); - let end = self.parse(reader); - if end > -1 { - return Ok(()); - } - - Err(BuiltInExceptions::LiteralIncorrect { - expected: self.literal().to_string(), - } - .create_with_context(reader)) - } - - fn list_suggestions( - &self, - context: CommandContext<S>, - builder: &SuggestionsBuilder, - ) -> Result<Suggestions, CommandSyntaxException> { - if self - .literal_lowercase - .starts_with(&builder.remaining_lowercase()) - { - Ok(builder.suggest(self.literal()).build()) - } else { - Ok(Suggestions::default()) - } - } - - fn is_valid_input(&self, input: &str) -> bool { - self.parse(&mut StringReader::from(input)) > -1 - } - - fn usage_text(&self) -> &str { - &self.literal - } - - fn create_builder(&self) -> Box<dyn ArgumentBuilder<S>> { - 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<String> { - todo!() - } -} diff --git a/azalea-brigadier/src/tree/mod.rs b/azalea-brigadier/src/tree/mod.rs deleted file mode 100644 index 3dc22583..00000000 --- a/azalea-brigadier/src/tree/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod argument_command_node; -pub mod command_node; -pub mod literal_command_node; -pub mod root_command_node; diff --git a/azalea-brigadier/src/tree/root_command_node.rs b/azalea-brigadier/src/tree/root_command_node.rs deleted file mode 100644 index 6b8bc157..00000000 --- a/azalea-brigadier/src/tree/root_command_node.rs +++ /dev/null @@ -1,79 +0,0 @@ -use super::{ - argument_command_node::ArgumentCommandNode, - command_node::{BaseCommandNode, CommandNodeTrait}, - literal_command_node::LiteralCommandNode, -}; -use crate::{ - arguments::argument_type::ArgumentType, - builder::argument_builder::ArgumentBuilder, - command::Command, - 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, - collections::HashMap, - fmt::{Debug, Display, Formatter}, -}; - -#[derive(Default)] -pub struct RootCommandNode<S> { - // Since Rust doesn't have extending, we put the struct this is extending as the "base" field - children: HashMap<String, Box<dyn CommandNodeTrait<S>>>, - literals: HashMap<String, LiteralCommandNode<S>>, - arguments: HashMap<String, ArgumentCommandNode<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> CommandNodeTrait<S> for RootCommandNode<S> { - fn name(&self) -> &str { - "" - } - - fn parse( - &self, - reader: &mut StringReader<'_>, - context_builder: CommandContextBuilder<S>, - ) -> Result<(), CommandSyntaxException> { - Ok(()) - } - - fn list_suggestions( - &self, - context: CommandContext<S>, - builder: &SuggestionsBuilder, - ) -> Result<Suggestions, CommandSyntaxException> { - Ok(Suggestions::default()) - } - - fn is_valid_input(&self, input: &str) -> bool { - false - } - - fn usage_text(&self) -> &str { - "" - } - - fn create_builder(&self) -> Box<dyn ArgumentBuilder<S>> { - panic!("Cannot convert root into a builder"); - } - - fn get_examples(&self) -> Vec<String> { - vec![] - } -} - -impl<S> Display for RootCommandNode<S> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "<root>") - } -} |
