aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--azalea-brigadier/README.md3
-rw-r--r--azalea-brigadier/src/dispatcher.rs2
-rw-r--r--azalea-brigadier/src/lib.rs19
-rw-r--r--azalea-brigadier/src/string_reader.rs2
-rw-r--r--azalea-brigadier/src/tree.rs279
5 files changed, 16 insertions, 289 deletions
diff --git a/azalea-brigadier/README.md b/azalea-brigadier/README.md
index df69b5c0..a7318566 100644
--- a/azalea-brigadier/README.md
+++ b/azalea-brigadier/README.md
@@ -1,4 +1,3 @@
# Azalea Brigadier
-A Rustier port of Mojang's [Brigadier](https://github.com/Mojang/brigadier) command parsing and dispatching library.
-
+A Rust port of Mojang's [Brigadier](https://github.com/Mojang/brigadier) command parsing and dispatching library.
diff --git a/azalea-brigadier/src/dispatcher.rs b/azalea-brigadier/src/dispatcher.rs
index 9f8edce4..ce89b81d 100644
--- a/azalea-brigadier/src/dispatcher.rs
+++ b/azalea-brigadier/src/dispatcher.rs
@@ -589,7 +589,7 @@ mod tests {
let source1 = Rc::new(CommandSource {});
let source2 = Rc::new(CommandSource {});
- let modifier = move |source: &CommandContext<CommandSource>| -> Result<Vec<Rc<CommandSource>>, CommandSyntaxException> {
+ let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Rc<CommandSource>>, CommandSyntaxException> {
Ok(vec![source1.clone(), source2.clone()])
};
diff --git a/azalea-brigadier/src/lib.rs b/azalea-brigadier/src/lib.rs
index d3db8dcf..e359e274 100644
--- a/azalea-brigadier/src/lib.rs
+++ b/azalea-brigadier/src/lib.rs
@@ -17,6 +17,7 @@ mod tests {
use crate::{
builder::{literal_argument_builder::literal, required_argument_builder::argument},
+ context::CommandContext,
dispatcher::CommandDispatcher,
parsers::{get_integer, integer},
};
@@ -27,7 +28,7 @@ mod tests {
#[test]
fn it_works() {
- let mut dispatcher = CommandDispatcher::<CommandSourceStack>::new();
+ let mut dispatcher = CommandDispatcher::new();
let source = Rc::new(CommandSourceStack {
player: "player".to_string(),
@@ -35,11 +36,17 @@ mod tests {
dispatcher.register(
literal("foo")
- .then(argument("bar", integer()).executes(|c| {
- println!("Bar is {:?}", get_integer(c, "bar"));
- 2
- }))
- .executes(|c| {
+ .then(argument("bar", integer()).executes(
+ |c: &CommandContext<CommandSourceStack>| {
+ println!(
+ "Bar is {:?} and player is {}",
+ get_integer(c, "bar"),
+ c.source.player
+ );
+ 2
+ },
+ ))
+ .executes(|_| {
println!("Called foo with no arguments");
1
}),
diff --git a/azalea-brigadier/src/string_reader.rs b/azalea-brigadier/src/string_reader.rs
index 5825871f..f220267a 100644
--- a/azalea-brigadier/src/string_reader.rs
+++ b/azalea-brigadier/src/string_reader.rs
@@ -824,7 +824,7 @@ mod test {
#[test]
fn expect_correct() {
let mut reader = StringReader::from("abc".to_string());
- reader.expect('a');
+ reader.expect('a').unwrap();
assert_eq!(reader.cursor(), 1);
}
diff --git a/azalea-brigadier/src/tree.rs b/azalea-brigadier/src/tree.rs
deleted file mode 100644
index 5ca199fa..00000000
--- a/azalea-brigadier/src/tree.rs
+++ /dev/null
@@ -1,279 +0,0 @@
-use crate::{
- builder::{
- argument_builder::ArgumentBuilderType, literal_argument_builder::Literal,
- required_argument_builder::Argument,
- },
- context::{CommandContext, CommandContextBuilder, ParsedArgument},
- exceptions::{
- builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
- },
- modifier::RedirectModifier,
- string_range::StringRange,
- string_reader::StringReader,
-};
-use std::{cell::RefCell, collections::BTreeMap, fmt::Debug, hash::Hash, ptr, rc::Rc};
-
-/// An ArgumentBuilder that has been built.
-#[non_exhaustive]
-pub struct CommandNode<S> {
- pub value: ArgumentBuilderType,
-
- // we use BTreeMap instead of HashMap because it can be hashed
- pub children: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
- pub literals: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
- pub arguments: BTreeMap<String, Rc<RefCell<CommandNode<S>>>>,
-
- pub command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>,
- pub requirement: Rc<dyn Fn(Rc<S>) -> bool>,
- pub redirect: Option<Rc<RefCell<CommandNode<S>>>>,
- pub forks: bool,
- pub modifier: Option<Rc<RedirectModifier<S>>>,
-}
-
-impl<S> Clone for CommandNode<S> {
- fn clone(&self) -> Self {
- Self {
- value: self.value.clone(),
- children: self.children.clone(),
- literals: self.literals.clone(),
- arguments: self.arguments.clone(),
- command: self.command.clone(),
- requirement: self.requirement.clone(),
- redirect: self.redirect.clone(),
- forks: self.forks,
- modifier: self.modifier.clone(),
- }
- }
-}
-
-#[derive(Debug)]
-pub struct ParsedCommandNode<S> {
- pub node: Rc<RefCell<CommandNode<S>>>,
- pub range: StringRange,
-}
-
-impl<S> Clone for ParsedCommandNode<S> {
- fn clone(&self) -> Self {
- Self {
- node: self.node.clone(),
- range: self.range.clone(),
- }
- }
-}
-
-impl<S> CommandNode<S> {
- /// Gets the literal, or panics. You should use match if you're not certain about the type.
- pub fn literal(&self) -> &Literal {
- match self.value {
- ArgumentBuilderType::Literal(ref literal) => literal,
- _ => panic!("CommandNode::literal() called on non-literal node"),
- }
- }
- /// Gets the argument, or panics. You should use match if you're not certain about the type.
- pub fn argument(&self) -> &Argument {
- match self.value {
- ArgumentBuilderType::Argument(ref argument) => argument,
- _ => panic!("CommandNode::argument() called on non-argument node"),
- }
- }
-
- pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
- let literals = &self.literals;
-
- if !literals.is_empty() {
- let cursor = input.cursor();
- while input.can_read() && input.peek() != ' ' {
- input.skip();
- }
- let text: String = input
- .string()
- .chars()
- .skip(cursor)
- .take(input.cursor() - cursor)
- .collect();
- input.cursor = cursor;
- let literal = literals.get(&text);
- if let Some(literal) = literal {
- return vec![literal.clone()];
- } else {
- return self.arguments.values().cloned().collect();
- }
- } else {
- self.arguments.values().cloned().collect()
- }
- }
-
- pub fn can_use(&self, source: Rc<S>) -> bool {
- (self.requirement)(source)
- }
-
- pub fn add_child(&mut self, node: &Rc<RefCell<CommandNode<S>>>) {
- let child = self.children.get(node.borrow().name());
- if let Some(child) = child {
- // We've found something to merge onto
- if let Some(command) = &node.borrow().command {
- child.borrow_mut().command = Some(command.clone());
- }
- for grandchild in node.borrow().children.values() {
- child.borrow_mut().add_child(grandchild);
- }
- } else {
- self.children
- .insert(node.borrow().name().to_string(), node.clone());
- match &node.borrow().value {
- ArgumentBuilderType::Literal(literal) => {
- self.literals.insert(literal.value.clone(), node.clone());
- }
- ArgumentBuilderType::Argument(argument) => {
- self.arguments.insert(argument.name.clone(), node.clone());
- }
- }
- }
- }
-
- pub fn name(&self) -> &str {
- match &self.value {
- ArgumentBuilderType::Argument(argument) => &argument.name,
- ArgumentBuilderType::Literal(literal) => &literal.value,
- }
- }
-
- pub fn child(&self, name: &str) -> Option<Rc<RefCell<CommandNode<S>>>> {
- self.children.get(name).cloned()
- }
-
- pub fn parse_with_context(
- &self,
- reader: &mut StringReader,
- context_builder: &mut CommandContextBuilder<S>,
- ) -> Result<(), CommandSyntaxException> {
- match self.value {
- ArgumentBuilderType::Argument(ref argument) => {
- let start = reader.cursor();
- // TODO: handle this better
- let result = argument.parse(reader)?;
- let parsed = ParsedArgument {
- range: StringRange::between(start, reader.cursor()),
- result,
- };
-
- context_builder.with_argument(&argument.name, parsed.clone());
- context_builder.with_node(Rc::new(RefCell::new(self.clone())), parsed.range);
-
- Ok(())
- }
- ArgumentBuilderType::Literal(ref literal) => {
- let start = reader.cursor();
- let end = self.parse(reader);
-
- if let Some(end) = end {
- context_builder.with_node(
- Rc::new(RefCell::new(self.clone())),
- StringRange::between(start, end),
- );
- return Ok(());
- }
-
- Err(BuiltInExceptions::LiteralIncorrect {
- expected: literal.value.clone(),
- }
- .create_with_context(reader))
- }
- }
- }
-
- fn parse(&self, reader: &mut StringReader) -> Option<usize> {
- match self.value {
- ArgumentBuilderType::Argument(_) => {
- panic!("Can't parse argument.")
- }
- ArgumentBuilderType::Literal(ref literal) => {
- let start = reader.cursor();
- if reader.can_read_length(literal.value.len()) {
- let end = start + literal.value.len();
- if reader
- .string()
- .get(start..end)
- .expect("Couldn't slice reader correctly?")
- == literal.value
- {
- reader.cursor = end;
- if !reader.can_read() || reader.peek() == ' ' {
- return Some(end);
- } else {
- reader.cursor = start;
- }
- }
- }
- }
- }
- None
- }
-}
-
-impl<S> Debug for CommandNode<S> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("CommandNode")
- .field("value", &self.value)
- .field("children", &self.children)
- .field("command", &self.command.is_some())
- // .field("requirement", &self.requirement)
- .field("redirect", &self.redirect)
- .field("forks", &self.forks)
- // .field("modifier", &self.modifier)
- .finish()
- }
-}
-
-impl<S> Default for CommandNode<S> {
- fn default() -> Self {
- Self {
- value: ArgumentBuilderType::Literal(Literal::default()),
-
- children: BTreeMap::new(),
- literals: BTreeMap::new(),
- arguments: BTreeMap::new(),
-
- command: None,
- requirement: Rc::new(|_| true),
- redirect: None,
- forks: false,
- modifier: None,
- }
- }
-}
-
-impl<S> Hash for CommandNode<S> {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- // hash the children
- for (k, v) in &self.children {
- k.hash(state);
- v.borrow().hash(state);
- }
- // i hope this works because if doesn't then that'll be a problem
- ptr::hash(&self.command, state);
- }
-}
-
-impl<S> PartialEq for CommandNode<S> {
- fn eq(&self, other: &Self) -> bool {
- if self.children != other.children {
- return false;
- }
- if let Some(selfexecutes) = &self.command {
- // idk how to do this better since we can't compare `dyn Fn`s
- if let Some(otherexecutes) = &other.command {
- #[allow(clippy::vtable_address_comparisons)]
- if !Rc::ptr_eq(selfexecutes, otherexecutes) {
- return false;
- }
- } else {
- return false;
- }
- } else if other.command.is_some() {
- return false;
- }
- true
- }
-}
-impl<S> Eq for CommandNode<S> {}