mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
CommandDispatcher is now Send+Sync
This commit is contained in:
parent
12370ab076
commit
f825544e27
8 changed files with 71 additions and 68 deletions
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{literal_argument_builder::Literal, required_argument_builder::Argument};
|
use super::{literal_argument_builder::Literal, required_argument_builder::Argument};
|
||||||
use std::{fmt::Debug, rc::Rc, sync::Arc};
|
use std::{fmt::Debug, sync::Arc};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ArgumentBuilderType {
|
pub enum ArgumentBuilderType {
|
||||||
|
@ -20,11 +20,11 @@ pub struct ArgumentBuilder<S> {
|
||||||
arguments: CommandNode<S>,
|
arguments: CommandNode<S>,
|
||||||
|
|
||||||
command: Command<S>,
|
command: Command<S>,
|
||||||
requirement: Rc<dyn Fn(Rc<S>) -> bool>,
|
requirement: Arc<dyn Fn(Arc<S>) -> bool + Send + Sync>,
|
||||||
target: Option<Arc<RwLock<CommandNode<S>>>>,
|
target: Option<Arc<RwLock<CommandNode<S>>>>,
|
||||||
|
|
||||||
forks: bool,
|
forks: bool,
|
||||||
modifier: Option<Rc<RedirectModifier<S>>>,
|
modifier: Option<Arc<RedirectModifier<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A node that isn't yet built.
|
/// A node that isn't yet built.
|
||||||
|
@ -36,7 +36,7 @@ impl<S> ArgumentBuilder<S> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
command: None,
|
command: None,
|
||||||
requirement: Rc::new(|_| true),
|
requirement: Arc::new(|_| true),
|
||||||
forks: false,
|
forks: false,
|
||||||
modifier: None,
|
modifier: None,
|
||||||
target: None,
|
target: None,
|
||||||
|
@ -54,17 +54,17 @@ impl<S> ArgumentBuilder<S> {
|
||||||
|
|
||||||
pub fn executes<F>(mut self, f: F) -> Self
|
pub fn executes<F>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(&CommandContext<S>) -> i32 + 'static,
|
F: Fn(&CommandContext<S>) -> i32 + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.command = Some(Rc::new(f));
|
self.command = Some(Arc::new(f));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requires<F>(mut self, requirement: F) -> Self
|
pub fn requires<F>(mut self, requirement: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(Rc<S>) -> bool + 'static,
|
F: Fn(Arc<S>) -> bool + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.requirement = Rc::new(requirement);
|
self.requirement = Arc::new(requirement);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl<S> ArgumentBuilder<S> {
|
||||||
pub fn fork(
|
pub fn fork(
|
||||||
self,
|
self,
|
||||||
target: Arc<RwLock<CommandNode<S>>>,
|
target: Arc<RwLock<CommandNode<S>>>,
|
||||||
modifier: Rc<RedirectModifier<S>>,
|
modifier: Arc<RedirectModifier<S>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.forward(target, Some(modifier), true)
|
self.forward(target, Some(modifier), true)
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl<S> ArgumentBuilder<S> {
|
||||||
pub fn forward(
|
pub fn forward(
|
||||||
mut self,
|
mut self,
|
||||||
target: Arc<RwLock<CommandNode<S>>>,
|
target: Arc<RwLock<CommandNode<S>>>,
|
||||||
modifier: Option<Rc<RedirectModifier<S>>>,
|
modifier: Option<Arc<RedirectModifier<S>>>,
|
||||||
fork: bool,
|
fork: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if !self.arguments.children.is_empty() {
|
if !self.arguments.children.is_empty() {
|
||||||
|
|
|
@ -2,17 +2,17 @@ use super::argument_builder::{ArgumentBuilder, ArgumentBuilderType};
|
||||||
use crate::{
|
use crate::{
|
||||||
arguments::ArgumentType, exceptions::CommandSyntaxException, string_reader::StringReader,
|
arguments::ArgumentType, exceptions::CommandSyntaxException, string_reader::StringReader,
|
||||||
};
|
};
|
||||||
use std::{any::Any, fmt::Debug, rc::Rc};
|
use std::{any::Any, fmt::Debug, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
/// An argument node type. The `T` type parameter is the type of the argument,
|
/// An argument node type. The `T` type parameter is the type of the argument,
|
||||||
/// which can be anything.
|
/// which can be anything.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Argument {
|
pub struct Argument {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
parser: Rc<dyn ArgumentType>,
|
parser: Arc<dyn ArgumentType + Send + Sync>,
|
||||||
}
|
}
|
||||||
impl Argument {
|
impl Argument {
|
||||||
pub fn new(name: &str, parser: Rc<dyn ArgumentType>) -> Self {
|
pub fn new(name: &str, parser: Arc<dyn ArgumentType + Send + Sync>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
parser,
|
parser,
|
||||||
|
@ -40,6 +40,9 @@ impl Debug for Argument {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shortcut for creating a new argument builder node.
|
/// Shortcut for creating a new argument builder node.
|
||||||
pub fn argument<S>(name: &str, parser: impl ArgumentType + 'static) -> ArgumentBuilder<S> {
|
pub fn argument<S>(
|
||||||
ArgumentBuilder::new(Argument::new(name, Rc::new(parser)).into())
|
name: &str,
|
||||||
|
parser: impl ArgumentType + Send + Sync + 'static,
|
||||||
|
) -> ArgumentBuilder<S> {
|
||||||
|
ArgumentBuilder::new(Argument::new(name, Arc::new(parser)).into())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ use std::{cmp::Ordering, collections::HashMap, mem, rc::Rc, sync::Arc};
|
||||||
/// The root of the command tree. You need to make this to register commands.
|
/// The root of the command tree. You need to make this to register commands.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CommandDispatcher<S>
|
pub struct CommandDispatcher<S>
|
||||||
// where
|
where
|
||||||
// Self: Sync + Send,
|
Self: Sync + Send,
|
||||||
{
|
{
|
||||||
pub root: Arc<RwLock<CommandNode<S>>>,
|
pub root: Arc<RwLock<CommandNode<S>>>,
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
build
|
build
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&self, command: StringReader, source: Rc<S>) -> ParseResults<S> {
|
pub fn parse(&self, command: StringReader, source: Arc<S>) -> ParseResults<S> {
|
||||||
let context = CommandContextBuilder::new(self, source, self.root.clone(), command.cursor());
|
let context = CommandContextBuilder::new(self, source, self.root.clone(), command.cursor());
|
||||||
self.parse_nodes(&self.root, &command, context).unwrap()
|
self.parse_nodes(&self.root, &command, context).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
let parse = self
|
let parse = self
|
||||||
.parse_nodes(redirect, &reader, child_context)
|
.parse_nodes(redirect, &reader, child_context)
|
||||||
.expect("Parsing nodes failed");
|
.expect("Parsing nodes failed");
|
||||||
context.with_child(Rc::new(parse.context));
|
context.with_child(Arc::new(parse.context));
|
||||||
return Ok(ParseResults {
|
return Ok(ParseResults {
|
||||||
context,
|
context,
|
||||||
reader: parse.reader,
|
reader: parse.reader,
|
||||||
|
@ -144,7 +144,7 @@ impl<S> CommandDispatcher<S> {
|
||||||
pub fn execute(
|
pub fn execute(
|
||||||
&self,
|
&self,
|
||||||
input: StringReader,
|
input: StringReader,
|
||||||
source: Rc<S>,
|
source: Arc<S>,
|
||||||
) -> Result<i32, CommandSyntaxException> {
|
) -> Result<i32, CommandSyntaxException> {
|
||||||
let parse = self.parse(input, source);
|
let parse = self.parse(input, source);
|
||||||
Self::execute_parsed(parse)
|
Self::execute_parsed(parse)
|
||||||
|
|
|
@ -9,15 +9,15 @@ use std::{any::Any, collections::HashMap, fmt::Debug, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
/// A built `CommandContextBuilder`.
|
/// A built `CommandContextBuilder`.
|
||||||
pub struct CommandContext<S> {
|
pub struct CommandContext<S> {
|
||||||
pub source: Rc<S>,
|
pub source: Arc<S>,
|
||||||
pub input: String,
|
pub input: String,
|
||||||
pub arguments: HashMap<String, ParsedArgument>,
|
pub arguments: HashMap<String, ParsedArgument>,
|
||||||
pub command: Command<S>,
|
pub command: Command<S>,
|
||||||
pub root_node: Arc<RwLock<CommandNode<S>>>,
|
pub root_node: Arc<RwLock<CommandNode<S>>>,
|
||||||
pub nodes: Vec<ParsedCommandNode<S>>,
|
pub nodes: Vec<ParsedCommandNode<S>>,
|
||||||
pub range: StringRange,
|
pub range: StringRange,
|
||||||
pub child: Option<Rc<CommandContext<S>>>,
|
pub child: Option<Arc<CommandContext<S>>>,
|
||||||
pub modifier: Option<Rc<RedirectModifier<S>>>,
|
pub modifier: Option<Arc<RedirectModifier<S>>>,
|
||||||
pub forks: bool,
|
pub forks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ impl<S> Debug for CommandContext<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> CommandContext<S> {
|
impl<S> CommandContext<S> {
|
||||||
pub fn copy_for(&self, source: Rc<S>) -> Self {
|
pub fn copy_for(&self, source: Arc<S>) -> Self {
|
||||||
if Rc::ptr_eq(&source, &self.source) {
|
if Arc::ptr_eq(&source, &self.source) {
|
||||||
return self.clone();
|
return self.clone();
|
||||||
}
|
}
|
||||||
CommandContext {
|
CommandContext {
|
||||||
|
|
|
@ -9,18 +9,18 @@ use crate::{
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
tree::{Command, CommandNode},
|
tree::{Command, CommandNode},
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, fmt::Debug, rc::Rc, sync::Arc};
|
use std::{collections::HashMap, fmt::Debug, sync::Arc};
|
||||||
|
|
||||||
pub struct CommandContextBuilder<'a, S> {
|
pub struct CommandContextBuilder<'a, S> {
|
||||||
pub arguments: HashMap<String, ParsedArgument>,
|
pub arguments: HashMap<String, ParsedArgument>,
|
||||||
pub root: Arc<RwLock<CommandNode<S>>>,
|
pub root: Arc<RwLock<CommandNode<S>>>,
|
||||||
pub nodes: Vec<ParsedCommandNode<S>>,
|
pub nodes: Vec<ParsedCommandNode<S>>,
|
||||||
pub dispatcher: &'a CommandDispatcher<S>,
|
pub dispatcher: &'a CommandDispatcher<S>,
|
||||||
pub source: Rc<S>,
|
pub source: Arc<S>,
|
||||||
pub command: Command<S>,
|
pub command: Command<S>,
|
||||||
pub child: Option<Rc<CommandContextBuilder<'a, S>>>,
|
pub child: Option<Arc<CommandContextBuilder<'a, S>>>,
|
||||||
pub range: StringRange,
|
pub range: StringRange,
|
||||||
pub modifier: Option<Rc<RedirectModifier<S>>>,
|
pub modifier: Option<Arc<RedirectModifier<S>>>,
|
||||||
pub forks: bool,
|
pub forks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ impl<S> Clone for CommandContextBuilder<'_, S> {
|
||||||
impl<'a, S> CommandContextBuilder<'a, S> {
|
impl<'a, S> CommandContextBuilder<'a, S> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
dispatcher: &'a CommandDispatcher<S>,
|
dispatcher: &'a CommandDispatcher<S>,
|
||||||
source: Rc<S>,
|
source: Arc<S>,
|
||||||
root_node: Arc<RwLock<CommandNode<S>>>,
|
root_node: Arc<RwLock<CommandNode<S>>>,
|
||||||
start: usize,
|
start: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -66,7 +66,7 @@ impl<'a, S> CommandContextBuilder<'a, S> {
|
||||||
self.command = command.clone();
|
self.command = command.clone();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn with_child(&mut self, child: Rc<CommandContextBuilder<'a, S>>) -> &Self {
|
pub fn with_child(&mut self, child: Arc<CommandContextBuilder<'a, S>>) -> &Self {
|
||||||
self.child = Some(child);
|
self.child = Some(child);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ impl<'a, S> CommandContextBuilder<'a, S> {
|
||||||
nodes: self.nodes.clone(),
|
nodes: self.nodes.clone(),
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
command: self.command.clone(),
|
command: self.command.clone(),
|
||||||
child: self.child.clone().map(|c| Rc::new(c.build(input))),
|
child: self.child.clone().map(|c| Arc::new(c.build(input))),
|
||||||
range: self.range.clone(),
|
range: self.range.clone(),
|
||||||
forks: self.forks,
|
forks: self.forks,
|
||||||
modifier: self.modifier.clone(),
|
modifier: self.modifier.clone(),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{context::CommandContext, exceptions::CommandSyntaxException};
|
use crate::{context::CommandContext, exceptions::CommandSyntaxException};
|
||||||
|
|
||||||
pub type RedirectModifier<S> =
|
pub type RedirectModifier<S> =
|
||||||
dyn Fn(&CommandContext<S>) -> Result<Vec<Rc<S>>, CommandSyntaxException>;
|
dyn Fn(&CommandContext<S>) -> Result<Vec<Arc<S>>, CommandSyntaxException> + Send + Sync;
|
||||||
|
|
|
@ -10,9 +10,9 @@ use crate::{
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
string_reader::StringReader,
|
string_reader::StringReader,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, fmt::Debug, hash::Hash, ptr, rc::Rc, sync::Arc};
|
use std::{collections::HashMap, fmt::Debug, hash::Hash, ptr, sync::Arc};
|
||||||
|
|
||||||
pub type Command<S> = Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>;
|
pub type Command<S> = Option<Arc<dyn Fn(&CommandContext<S>) -> i32 + Send + Sync>>;
|
||||||
|
|
||||||
/// An ArgumentBuilder that has been built.
|
/// An ArgumentBuilder that has been built.
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -24,10 +24,10 @@ pub struct CommandNode<S> {
|
||||||
pub arguments: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
|
pub arguments: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
|
||||||
|
|
||||||
pub command: Command<S>,
|
pub command: Command<S>,
|
||||||
pub requirement: Rc<dyn Fn(Rc<S>) -> bool>,
|
pub requirement: Arc<dyn Fn(Arc<S>) -> bool + Send + Sync>,
|
||||||
pub redirect: Option<Arc<RwLock<CommandNode<S>>>>,
|
pub redirect: Option<Arc<RwLock<CommandNode<S>>>>,
|
||||||
pub forks: bool,
|
pub forks: bool,
|
||||||
pub modifier: Option<Rc<RedirectModifier<S>>>,
|
pub modifier: Option<Arc<RedirectModifier<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Clone for CommandNode<S> {
|
impl<S> Clone for CommandNode<S> {
|
||||||
|
@ -90,7 +90,7 @@ impl<S> CommandNode<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_use(&self, source: Rc<S>) -> bool {
|
pub fn can_use(&self, source: Arc<S>) -> bool {
|
||||||
(self.requirement)(source)
|
(self.requirement)(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ impl<S> Default for CommandNode<S> {
|
||||||
arguments: HashMap::new(),
|
arguments: HashMap::new(),
|
||||||
|
|
||||||
command: None,
|
command: None,
|
||||||
requirement: Rc::new(|_| true),
|
requirement: Arc::new(|_| true),
|
||||||
redirect: None,
|
redirect: None,
|
||||||
forks: false,
|
forks: false,
|
||||||
modifier: None,
|
modifier: None,
|
||||||
|
@ -257,7 +257,7 @@ impl<S> PartialEq for CommandNode<S> {
|
||||||
// idk how to do this better since we can't compare `dyn Fn`s
|
// idk how to do this better since we can't compare `dyn Fn`s
|
||||||
if let Some(otherexecutes) = &other.command {
|
if let Some(otherexecutes) = &other.command {
|
||||||
#[allow(clippy::vtable_address_comparisons)]
|
#[allow(clippy::vtable_address_comparisons)]
|
||||||
if !Rc::ptr_eq(selfexecutes, otherexecutes) {
|
if !Arc::ptr_eq(selfexecutes, otherexecutes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use azalea_brigadier::{
|
use azalea_brigadier::{
|
||||||
arguments::integer_argument_type::integer,
|
arguments::integer_argument_type::integer,
|
||||||
|
@ -25,7 +25,7 @@ fn create_and_execute_command() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("foo".into(), Rc::new(CommandSource {}))
|
.execute("foo".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
@ -38,7 +38,7 @@ fn create_and_execute_offset_command() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute(input_with_offset("/foo", 1), Rc::new(CommandSource {}))
|
.execute(input_with_offset("/foo", 1), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
@ -52,13 +52,13 @@ fn create_and_merge_commands() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("base foo".into(), Rc::new(CommandSource {}))
|
.execute("base foo".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("base bar".into(), Rc::new(CommandSource {}))
|
.execute("base bar".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
@ -70,7 +70,7 @@ fn execute_unknown_command() {
|
||||||
subject.register(literal("bar"));
|
subject.register(literal("bar"));
|
||||||
subject.register(literal("baz"));
|
subject.register(literal("baz"));
|
||||||
|
|
||||||
let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("foo".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -85,7 +85,7 @@ fn execute_impermissible_command() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal("foo").requires(|_| false));
|
subject.register(literal("foo").requires(|_| false));
|
||||||
|
|
||||||
let execute_result = subject.execute("foo".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("foo".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -100,7 +100,7 @@ fn execute_empty_command() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal(""));
|
subject.register(literal(""));
|
||||||
|
|
||||||
let execute_result = subject.execute("".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -115,7 +115,7 @@ fn execute_unknown_subcommand() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal("foo").executes(|_| 42));
|
subject.register(literal("foo").executes(|_| 42));
|
||||||
|
|
||||||
let execute_result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("foo bar".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -130,7 +130,7 @@ fn execute_incorrect_literal() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal("foo").executes(|_| 42).then(literal("bar")));
|
subject.register(literal("foo").executes(|_| 42).then(literal("bar")));
|
||||||
|
|
||||||
let execute_result = subject.execute("foo baz".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("foo baz".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -150,7 +150,7 @@ fn execute_ambiguous_incorrect_argument() {
|
||||||
.then(literal("baz")),
|
.then(literal("baz")),
|
||||||
);
|
);
|
||||||
|
|
||||||
let execute_result = subject.execute("foo unknown".into(), Rc::new(CommandSource {}));
|
let execute_result = subject.execute("foo unknown".into(), Arc::new(CommandSource {}));
|
||||||
|
|
||||||
let err = execute_result.err().unwrap();
|
let err = execute_result.err().unwrap();
|
||||||
match err.type_ {
|
match err.type_ {
|
||||||
|
@ -174,7 +174,7 @@ fn execute_subcommand() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("foo =".into(), Rc::new(CommandSource {}))
|
.execute("foo =".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ fn parse_incomplete_literal() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal("foo").then(literal("bar").executes(|_| 42)));
|
subject.register(literal("foo").then(literal("bar").executes(|_| 42)));
|
||||||
|
|
||||||
let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
|
let parse = subject.parse("foo ".into(), Arc::new(CommandSource {}));
|
||||||
assert_eq!(parse.reader.remaining(), " ");
|
assert_eq!(parse.reader.remaining(), " ");
|
||||||
assert_eq!(parse.context.nodes.len(), 1);
|
assert_eq!(parse.context.nodes.len(), 1);
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ fn parse_incomplete_argument() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42)));
|
subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42)));
|
||||||
|
|
||||||
let parse = subject.parse("foo ".into(), Rc::new(CommandSource {}));
|
let parse = subject.parse("foo ".into(), Arc::new(CommandSource {}));
|
||||||
assert_eq!(parse.reader.remaining(), " ");
|
assert_eq!(parse.reader.remaining(), " ");
|
||||||
assert_eq!(parse.context.nodes.len(), 1);
|
assert_eq!(parse.context.nodes.len(), 1);
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ fn execute_ambiguious_parent_subcommand() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("test 1 2".into(), Rc::new(CommandSource {}))
|
.execute("test 1 2".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
|
@ -232,7 +232,7 @@ fn execute_ambiguious_parent_subcommand_via_redirect() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("redirect 1 2".into(), Rc::new(CommandSource {}))
|
.execute("redirect 1 2".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
|
@ -248,7 +248,7 @@ fn execute_redirected_multiple_times() {
|
||||||
|
|
||||||
let input = "redirected redirected actual";
|
let input = "redirected redirected actual";
|
||||||
|
|
||||||
let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
|
let parse = subject.parse(input.into(), Arc::new(CommandSource {}));
|
||||||
assert_eq!(parse.context.range.get(input), "redirected");
|
assert_eq!(parse.context.range.get(input), "redirected");
|
||||||
assert_eq!(parse.context.nodes.len(), 1);
|
assert_eq!(parse.context.nodes.len(), 1);
|
||||||
assert_eq!(*parse.context.root.read(), *root.read());
|
assert_eq!(*parse.context.root.read(), *root.read());
|
||||||
|
@ -287,19 +287,19 @@ fn execute_redirected_multiple_times() {
|
||||||
fn execute_redirected() {
|
fn execute_redirected() {
|
||||||
let mut subject = CommandDispatcher::new();
|
let mut subject = CommandDispatcher::new();
|
||||||
|
|
||||||
let source1 = Rc::new(CommandSource {});
|
let source1 = Arc::new(CommandSource {});
|
||||||
let source2 = Rc::new(CommandSource {});
|
let source2 = Arc::new(CommandSource {});
|
||||||
|
|
||||||
let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Rc<CommandSource>>, CommandSyntaxException> {
|
let modifier = move |_: &CommandContext<CommandSource>| -> Result<Vec<Arc<CommandSource>>, CommandSyntaxException> {
|
||||||
Ok(vec![source1.clone(), source2.clone()])
|
Ok(vec![source1.clone(), source2.clone()])
|
||||||
};
|
};
|
||||||
|
|
||||||
let concrete_node = subject.register(literal("actual").executes(|_| 42));
|
let concrete_node = subject.register(literal("actual").executes(|_| 42));
|
||||||
let redirect_node =
|
let redirect_node =
|
||||||
subject.register(literal("redirected").fork(subject.root.clone(), Rc::new(modifier)));
|
subject.register(literal("redirected").fork(subject.root.clone(), Arc::new(modifier)));
|
||||||
|
|
||||||
let input = "redirected actual";
|
let input = "redirected actual";
|
||||||
let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
|
let parse = subject.parse(input.into(), Arc::new(CommandSource {}));
|
||||||
assert_eq!(parse.context.range.get(input), "redirected");
|
assert_eq!(parse.context.range.get(input), "redirected");
|
||||||
assert_eq!(parse.context.nodes.len(), 1);
|
assert_eq!(parse.context.nodes.len(), 1);
|
||||||
assert_eq!(*parse.context.root.read(), *subject.root.read());
|
assert_eq!(*parse.context.root.read(), *subject.root.read());
|
||||||
|
@ -314,7 +314,7 @@ fn execute_redirected() {
|
||||||
assert_eq!(*parse.context.root.read(), *subject.root.read());
|
assert_eq!(*parse.context.root.read(), *subject.root.read());
|
||||||
assert_eq!(parent.nodes[0].range, parent.range);
|
assert_eq!(parent.nodes[0].range, parent.range);
|
||||||
assert_eq!(*parent.nodes[0].node.read(), *concrete_node.read());
|
assert_eq!(*parent.nodes[0].node.read(), *concrete_node.read());
|
||||||
assert_eq!(parent.source, Rc::new(CommandSource {}));
|
assert_eq!(parent.source, Arc::new(CommandSource {}));
|
||||||
|
|
||||||
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
|
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ fn execute_orphaned_subcommand() {
|
||||||
.executes(|_| 42),
|
.executes(|_| 42),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = subject.execute("foo 5".into(), Rc::new(CommandSource {}));
|
let result = subject.execute("foo 5".into(), Arc::new(CommandSource {}));
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let result = result.unwrap_err();
|
let result = result.unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -348,7 +348,7 @@ fn execute_invalid_other() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
subject
|
subject
|
||||||
.execute("world".into(), Rc::new(CommandSource {}))
|
.execute("world".into(), Arc::new(CommandSource {}))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
42
|
42
|
||||||
);
|
);
|
||||||
|
@ -364,7 +364,7 @@ fn parse_no_space_separator() {
|
||||||
.executes(|_| 42),
|
.executes(|_| 42),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = subject.execute("foo$".into(), Rc::new(CommandSource {}));
|
let result = subject.execute("foo$".into(), Arc::new(CommandSource {}));
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let result = result.unwrap_err();
|
let result = result.unwrap_err();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -384,7 +384,7 @@ fn execute_invalid_subcommand() {
|
||||||
.executes(|_| 42),
|
.executes(|_| 42),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = subject.execute("foo bar".into(), Rc::new(CommandSource {}));
|
let result = subject.execute("foo bar".into(), Arc::new(CommandSource {}));
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let result = result.unwrap_err();
|
let result = result.unwrap_err();
|
||||||
// this fails for some reason, i blame mojang
|
// this fails for some reason, i blame mojang
|
||||||
|
|
Loading…
Add table
Reference in a new issue