mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
change some things to be Arc+RwLock in brigadier
This commit is contained in:
parent
e4176937f0
commit
12370ab076
10 changed files with 111 additions and 88 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -233,6 +233,7 @@ version = "0.6.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"azalea-buf",
|
"azalea-buf",
|
||||||
"azalea-chat",
|
"azalea-chat",
|
||||||
|
"parking_lot",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -11,6 +11,7 @@ version = "0.6.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-buf = {path = "../azalea-buf", version = "^0.6.0", optional = true}
|
azalea-buf = {path = "../azalea-buf", version = "^0.6.0", optional = true}
|
||||||
azalea-chat = {path = "../azalea-chat", version = "^0.6.0", optional = true}
|
azalea-chat = {path = "../azalea-chat", version = "^0.6.0", optional = true}
|
||||||
|
parking_lot = "0.12.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
azalea-buf = ["dep:azalea-buf", "dep:azalea-chat"]
|
azalea-buf = ["dep:azalea-buf", "dep:azalea-chat"]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::CommandContext,
|
context::CommandContext,
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
|
@ -5,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::{cell::RefCell, fmt::Debug, rc::Rc};
|
use std::{fmt::Debug, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ArgumentBuilderType {
|
pub enum ArgumentBuilderType {
|
||||||
|
@ -19,7 +21,7 @@ pub struct ArgumentBuilder<S> {
|
||||||
|
|
||||||
command: Command<S>,
|
command: Command<S>,
|
||||||
requirement: Rc<dyn Fn(Rc<S>) -> bool>,
|
requirement: Rc<dyn Fn(Rc<S>) -> bool>,
|
||||||
target: Option<Rc<RefCell<CommandNode<S>>>>,
|
target: Option<Arc<RwLock<CommandNode<S>>>>,
|
||||||
|
|
||||||
forks: bool,
|
forks: bool,
|
||||||
modifier: Option<Rc<RedirectModifier<S>>>,
|
modifier: Option<Rc<RedirectModifier<S>>>,
|
||||||
|
@ -46,7 +48,7 @@ impl<S> ArgumentBuilder<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn then_built(mut self, argument: CommandNode<S>) -> Self {
|
pub fn then_built(mut self, argument: CommandNode<S>) -> Self {
|
||||||
self.arguments.add_child(&Rc::new(RefCell::new(argument)));
|
self.arguments.add_child(&Arc::new(RwLock::new(argument)));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,13 +68,13 @@ impl<S> ArgumentBuilder<S> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redirect(self, target: Rc<RefCell<CommandNode<S>>>) -> Self {
|
pub fn redirect(self, target: Arc<RwLock<CommandNode<S>>>) -> Self {
|
||||||
self.forward(target, None, false)
|
self.forward(target, None, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fork(
|
pub fn fork(
|
||||||
self,
|
self,
|
||||||
target: Rc<RefCell<CommandNode<S>>>,
|
target: Arc<RwLock<CommandNode<S>>>,
|
||||||
modifier: Rc<RedirectModifier<S>>,
|
modifier: Rc<RedirectModifier<S>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.forward(target, Some(modifier), true)
|
self.forward(target, Some(modifier), true)
|
||||||
|
@ -80,7 +82,7 @@ impl<S> ArgumentBuilder<S> {
|
||||||
|
|
||||||
pub fn forward(
|
pub fn forward(
|
||||||
mut self,
|
mut self,
|
||||||
target: Rc<RefCell<CommandNode<S>>>,
|
target: Arc<RwLock<CommandNode<S>>>,
|
||||||
modifier: Option<Rc<RedirectModifier<S>>>,
|
modifier: Option<Rc<RedirectModifier<S>>>,
|
||||||
fork: bool,
|
fork: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::argument_builder::ArgumentBuilder,
|
builder::argument_builder::ArgumentBuilder,
|
||||||
context::{CommandContext, CommandContextBuilder},
|
context::{CommandContext, CommandContextBuilder},
|
||||||
|
@ -6,26 +8,27 @@ use crate::{
|
||||||
string_reader::StringReader,
|
string_reader::StringReader,
|
||||||
tree::CommandNode,
|
tree::CommandNode,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, cmp::Ordering, collections::HashMap, marker::PhantomData, mem, rc::Rc};
|
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<'a, S> {
|
pub struct CommandDispatcher<S>
|
||||||
pub root: Rc<RefCell<CommandNode<S>>>,
|
// where
|
||||||
_marker: PhantomData<(S, &'a ())>,
|
// Self: Sync + Send,
|
||||||
|
{
|
||||||
|
pub root: Arc<RwLock<CommandNode<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> CommandDispatcher<'a, S> {
|
impl<S> CommandDispatcher<S> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
root: Rc::new(RefCell::new(CommandNode::default())),
|
root: Arc::new(RwLock::new(CommandNode::default())),
|
||||||
_marker: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register(&mut self, node: ArgumentBuilder<S>) -> Rc<RefCell<CommandNode<S>>> {
|
pub fn register(&mut self, node: ArgumentBuilder<S>) -> Arc<RwLock<CommandNode<S>>> {
|
||||||
let build = Rc::new(RefCell::new(node.build()));
|
let build = Arc::new(RwLock::new(node.build()));
|
||||||
self.root.borrow_mut().add_child(&build);
|
self.root.write().add_child(&build);
|
||||||
build
|
build
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,9 +37,9 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
self.parse_nodes(&self.root, &command, context).unwrap()
|
self.parse_nodes(&self.root, &command, context).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_nodes(
|
fn parse_nodes<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
node: &Rc<RefCell<CommandNode<S>>>,
|
node: &Arc<RwLock<CommandNode<S>>>,
|
||||||
original_reader: &StringReader,
|
original_reader: &StringReader,
|
||||||
context_so_far: CommandContextBuilder<'a, S>,
|
context_so_far: CommandContextBuilder<'a, S>,
|
||||||
) -> Result<ParseResults<'a, S>, CommandSyntaxException> {
|
) -> Result<ParseResults<'a, S>, CommandSyntaxException> {
|
||||||
|
@ -45,21 +48,18 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
let mut potentials: Vec<ParseResults<S>> = vec![];
|
let mut potentials: Vec<ParseResults<S>> = vec![];
|
||||||
let cursor = original_reader.cursor();
|
let cursor = original_reader.cursor();
|
||||||
|
|
||||||
for child in node
|
for child in node.read().get_relevant_nodes(&mut original_reader.clone()) {
|
||||||
.borrow()
|
if !child.read().can_use(source.clone()) {
|
||||||
.get_relevant_nodes(&mut original_reader.clone())
|
|
||||||
{
|
|
||||||
if !child.borrow().can_use(source.clone()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut context = context_so_far.clone();
|
let mut context = context_so_far.clone();
|
||||||
let mut reader = original_reader.clone();
|
let mut reader = original_reader.clone();
|
||||||
|
|
||||||
let parse_with_context_result =
|
let parse_with_context_result =
|
||||||
child.borrow().parse_with_context(&mut reader, &mut context);
|
child.read().parse_with_context(&mut reader, &mut context);
|
||||||
if let Err(ex) = parse_with_context_result {
|
if let Err(ex) = parse_with_context_result {
|
||||||
errors.insert(
|
errors.insert(
|
||||||
Rc::new((*child.borrow()).clone()),
|
Rc::new((*child.read()).clone()),
|
||||||
BuiltInExceptions::DispatcherParseException {
|
BuiltInExceptions::DispatcherParseException {
|
||||||
message: ex.message(),
|
message: ex.message(),
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
}
|
}
|
||||||
if reader.can_read() && reader.peek() != ' ' {
|
if reader.can_read() && reader.peek() != ' ' {
|
||||||
errors.insert(
|
errors.insert(
|
||||||
Rc::new((*child.borrow()).clone()),
|
Rc::new((*child.read()).clone()),
|
||||||
BuiltInExceptions::DispatcherExpectedArgumentSeparator
|
BuiltInExceptions::DispatcherExpectedArgumentSeparator
|
||||||
.create_with_context(&reader),
|
.create_with_context(&reader),
|
||||||
);
|
);
|
||||||
|
@ -78,14 +78,14 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.with_command(&child.borrow().command);
|
context.with_command(&child.read().command);
|
||||||
if reader.can_read_length(if child.borrow().redirect.is_none() {
|
if reader.can_read_length(if child.read().redirect.is_none() {
|
||||||
2
|
2
|
||||||
} else {
|
} else {
|
||||||
1
|
1
|
||||||
}) {
|
}) {
|
||||||
reader.skip();
|
reader.skip();
|
||||||
if let Some(redirect) = &child.borrow().redirect {
|
if let Some(redirect) = &child.read().redirect {
|
||||||
let child_context =
|
let child_context =
|
||||||
CommandContextBuilder::new(self, source, redirect.clone(), reader.cursor);
|
CommandContextBuilder::new(self, source, redirect.clone(), reader.cursor);
|
||||||
let parse = self
|
let parse = self
|
||||||
|
@ -151,30 +151,30 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_paths(
|
pub fn add_paths(
|
||||||
node: Rc<RefCell<CommandNode<S>>>,
|
node: Arc<RwLock<CommandNode<S>>>,
|
||||||
result: &mut Vec<Vec<Rc<RefCell<CommandNode<S>>>>>,
|
result: &mut Vec<Vec<Arc<RwLock<CommandNode<S>>>>>,
|
||||||
parents: Vec<Rc<RefCell<CommandNode<S>>>>,
|
parents: Vec<Arc<RwLock<CommandNode<S>>>>,
|
||||||
) {
|
) {
|
||||||
let mut current = parents;
|
let mut current = parents;
|
||||||
current.push(node.clone());
|
current.push(node.clone());
|
||||||
result.push(current.clone());
|
result.push(current.clone());
|
||||||
|
|
||||||
for child in node.borrow().children.values() {
|
for child in node.read().children.values() {
|
||||||
Self::add_paths(child.clone(), result, current.clone());
|
Self::add_paths(child.clone(), result, current.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_path(&self, target: CommandNode<S>) -> Vec<String> {
|
pub fn get_path(&self, target: CommandNode<S>) -> Vec<String> {
|
||||||
let rc_target = Rc::new(RefCell::new(target));
|
let rc_target = Arc::new(RwLock::new(target));
|
||||||
let mut nodes: Vec<Vec<Rc<RefCell<CommandNode<S>>>>> = Vec::new();
|
let mut nodes: Vec<Vec<Arc<RwLock<CommandNode<S>>>>> = Vec::new();
|
||||||
Self::add_paths(self.root.clone(), &mut nodes, vec![]);
|
Self::add_paths(self.root.clone(), &mut nodes, vec![]);
|
||||||
|
|
||||||
for list in nodes {
|
for list in nodes {
|
||||||
if *list.last().expect("Nothing in list").borrow() == *rc_target.borrow() {
|
if *list.last().expect("Nothing in list").read() == *rc_target.read() {
|
||||||
let mut result: Vec<String> = Vec::with_capacity(list.len());
|
let mut result: Vec<String> = Vec::with_capacity(list.len());
|
||||||
for node in list {
|
for node in list {
|
||||||
if node != self.root {
|
if !Arc::ptr_eq(&node, &self.root) {
|
||||||
result.push(node.borrow().name().to_string());
|
result.push(node.read().name().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -183,10 +183,10 @@ impl<'a, S> CommandDispatcher<'a, S> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_node(&self, path: &[&str]) -> Option<Rc<RefCell<CommandNode<S>>>> {
|
pub fn find_node(&self, path: &[&str]) -> Option<Arc<RwLock<CommandNode<S>>>> {
|
||||||
let mut node = self.root.clone();
|
let mut node = self.root.clone();
|
||||||
for name in path {
|
for name in path {
|
||||||
if let Some(child) = node.clone().borrow().child(name) {
|
if let Some(child) = node.clone().read().child(name) {
|
||||||
node = child;
|
node = child;
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use super::{parsed_command_node::ParsedCommandNode, string_range::StringRange, ParsedArgument};
|
use super::{parsed_command_node::ParsedCommandNode, string_range::StringRange, ParsedArgument};
|
||||||
use crate::{
|
use crate::{
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
tree::{Command, CommandNode},
|
tree::{Command, CommandNode},
|
||||||
};
|
};
|
||||||
use std::{any::Any, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
|
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> {
|
||||||
|
@ -11,7 +13,7 @@ pub struct CommandContext<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: Rc<RefCell<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<Rc<CommandContext<S>>>,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
command_context::CommandContext, parsed_command_node::ParsedCommandNode,
|
command_context::CommandContext, parsed_command_node::ParsedCommandNode,
|
||||||
string_range::StringRange, ParsedArgument,
|
string_range::StringRange, ParsedArgument,
|
||||||
|
@ -7,13 +9,13 @@ use crate::{
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
tree::{Command, CommandNode},
|
tree::{Command, CommandNode},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
|
use std::{collections::HashMap, fmt::Debug, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
pub struct CommandContextBuilder<'a, S> {
|
pub struct CommandContextBuilder<'a, S> {
|
||||||
pub arguments: HashMap<String, ParsedArgument>,
|
pub arguments: HashMap<String, ParsedArgument>,
|
||||||
pub root: Rc<RefCell<CommandNode<S>>>,
|
pub root: Arc<RwLock<CommandNode<S>>>,
|
||||||
pub nodes: Vec<ParsedCommandNode<S>>,
|
pub nodes: Vec<ParsedCommandNode<S>>,
|
||||||
pub dispatcher: &'a CommandDispatcher<'a, S>,
|
pub dispatcher: &'a CommandDispatcher<S>,
|
||||||
pub source: Rc<S>,
|
pub source: Rc<S>,
|
||||||
pub command: Command<S>,
|
pub command: Command<S>,
|
||||||
pub child: Option<Rc<CommandContextBuilder<'a, S>>>,
|
pub child: Option<Rc<CommandContextBuilder<'a, S>>>,
|
||||||
|
@ -28,7 +30,7 @@ impl<S> Clone for CommandContextBuilder<'_, S> {
|
||||||
arguments: self.arguments.clone(),
|
arguments: self.arguments.clone(),
|
||||||
root: self.root.clone(),
|
root: self.root.clone(),
|
||||||
nodes: self.nodes.clone(),
|
nodes: self.nodes.clone(),
|
||||||
dispatcher: self.dispatcher.clone(),
|
dispatcher: self.dispatcher,
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
command: self.command.clone(),
|
command: self.command.clone(),
|
||||||
child: self.child.clone(),
|
child: self.child.clone(),
|
||||||
|
@ -43,7 +45,7 @@ impl<'a, S> CommandContextBuilder<'a, S> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
dispatcher: &'a CommandDispatcher<S>,
|
dispatcher: &'a CommandDispatcher<S>,
|
||||||
source: Rc<S>,
|
source: Rc<S>,
|
||||||
root_node: Rc<RefCell<CommandNode<S>>>,
|
root_node: Arc<RwLock<CommandNode<S>>>,
|
||||||
start: usize,
|
start: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -72,14 +74,14 @@ impl<'a, S> CommandContextBuilder<'a, S> {
|
||||||
self.arguments.insert(name.to_string(), argument);
|
self.arguments.insert(name.to_string(), argument);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn with_node(&mut self, node: Rc<RefCell<CommandNode<S>>>, range: StringRange) -> &Self {
|
pub fn with_node(&mut self, node: Arc<RwLock<CommandNode<S>>>, range: StringRange) -> &Self {
|
||||||
self.nodes.push(ParsedCommandNode {
|
self.nodes.push(ParsedCommandNode {
|
||||||
node: node.clone(),
|
node: node.clone(),
|
||||||
range: range.clone(),
|
range: range.clone(),
|
||||||
});
|
});
|
||||||
self.range = StringRange::encompassing(&self.range, &range);
|
self.range = StringRange::encompassing(&self.range, &range);
|
||||||
self.modifier = node.borrow().modifier.clone();
|
self.modifier = node.read().modifier.clone();
|
||||||
self.forks = node.borrow().forks;
|
self.forks = node.read().forks;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use super::string_range::StringRange;
|
use super::string_range::StringRange;
|
||||||
use crate::tree::CommandNode;
|
use crate::tree::CommandNode;
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParsedCommandNode<S> {
|
pub struct ParsedCommandNode<S> {
|
||||||
pub node: Rc<RefCell<CommandNode<S>>>,
|
pub node: Arc<RwLock<CommandNode<S>>>,
|
||||||
pub range: StringRange,
|
pub range: StringRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::{
|
builder::{
|
||||||
argument_builder::ArgumentBuilderType, literal_argument_builder::Literal,
|
argument_builder::ArgumentBuilderType, literal_argument_builder::Literal,
|
||||||
|
@ -8,7 +10,7 @@ use crate::{
|
||||||
modifier::RedirectModifier,
|
modifier::RedirectModifier,
|
||||||
string_reader::StringReader,
|
string_reader::StringReader,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, hash::Hash, ptr, rc::Rc};
|
use std::{collections::HashMap, fmt::Debug, hash::Hash, ptr, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
pub type Command<S> = Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>;
|
pub type Command<S> = Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>;
|
||||||
|
|
||||||
|
@ -17,13 +19,13 @@ pub type Command<S> = Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>;
|
||||||
pub struct CommandNode<S> {
|
pub struct CommandNode<S> {
|
||||||
pub value: ArgumentBuilderType,
|
pub value: ArgumentBuilderType,
|
||||||
|
|
||||||
pub children: HashMap<String, Rc<RefCell<CommandNode<S>>>>,
|
pub children: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
|
||||||
pub literals: HashMap<String, Rc<RefCell<CommandNode<S>>>>,
|
pub literals: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
|
||||||
pub arguments: HashMap<String, Rc<RefCell<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: Rc<dyn Fn(Rc<S>) -> bool>,
|
||||||
pub redirect: Option<Rc<RefCell<CommandNode<S>>>>,
|
pub redirect: Option<Arc<RwLock<CommandNode<S>>>>,
|
||||||
pub forks: bool,
|
pub forks: bool,
|
||||||
pub modifier: Option<Rc<RedirectModifier<S>>>,
|
pub modifier: Option<Rc<RedirectModifier<S>>>,
|
||||||
}
|
}
|
||||||
|
@ -62,7 +64,7 @@ impl<S> CommandNode<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Rc<RefCell<CommandNode<S>>>> {
|
pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Arc<RwLock<CommandNode<S>>>> {
|
||||||
let literals = &self.literals;
|
let literals = &self.literals;
|
||||||
|
|
||||||
if literals.is_empty() {
|
if literals.is_empty() {
|
||||||
|
@ -92,20 +94,20 @@ impl<S> CommandNode<S> {
|
||||||
(self.requirement)(source)
|
(self.requirement)(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_child(&mut self, node: &Rc<RefCell<CommandNode<S>>>) {
|
pub fn add_child(&mut self, node: &Arc<RwLock<CommandNode<S>>>) {
|
||||||
let child = self.children.get(node.borrow().name());
|
let child = self.children.get(node.read().name());
|
||||||
if let Some(child) = child {
|
if let Some(child) = child {
|
||||||
// We've found something to merge onto
|
// We've found something to merge onto
|
||||||
if let Some(command) = &node.borrow().command {
|
if let Some(command) = &node.read().command {
|
||||||
child.borrow_mut().command = Some(command.clone());
|
child.write().command = Some(command.clone());
|
||||||
}
|
}
|
||||||
for grandchild in node.borrow().children.values() {
|
for grandchild in node.read().children.values() {
|
||||||
child.borrow_mut().add_child(grandchild);
|
child.write().add_child(grandchild);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.children
|
self.children
|
||||||
.insert(node.borrow().name().to_string(), node.clone());
|
.insert(node.read().name().to_string(), node.clone());
|
||||||
match &node.borrow().value {
|
match &node.read().value {
|
||||||
ArgumentBuilderType::Literal(literal) => {
|
ArgumentBuilderType::Literal(literal) => {
|
||||||
self.literals.insert(literal.value.clone(), node.clone());
|
self.literals.insert(literal.value.clone(), node.clone());
|
||||||
}
|
}
|
||||||
|
@ -123,7 +125,7 @@ impl<S> CommandNode<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn child(&self, name: &str) -> Option<Rc<RefCell<CommandNode<S>>>> {
|
pub fn child(&self, name: &str) -> Option<Arc<RwLock<CommandNode<S>>>> {
|
||||||
self.children.get(name).cloned()
|
self.children.get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +144,7 @@ impl<S> CommandNode<S> {
|
||||||
};
|
};
|
||||||
|
|
||||||
context_builder.with_argument(&argument.name, parsed.clone());
|
context_builder.with_argument(&argument.name, parsed.clone());
|
||||||
context_builder.with_node(Rc::new(RefCell::new(self.clone())), parsed.range);
|
context_builder.with_node(Arc::new(RwLock::new(self.clone())), parsed.range);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -152,7 +154,7 @@ impl<S> CommandNode<S> {
|
||||||
|
|
||||||
if let Some(end) = end {
|
if let Some(end) = end {
|
||||||
context_builder.with_node(
|
context_builder.with_node(
|
||||||
Rc::new(RefCell::new(self.clone())),
|
Arc::new(RwLock::new(self.clone())),
|
||||||
StringRange::between(start, end),
|
StringRange::between(start, end),
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -232,7 +234,7 @@ impl<S> Hash for CommandNode<S> {
|
||||||
// hash the children
|
// hash the children
|
||||||
for (k, v) in &self.children {
|
for (k, v) in &self.children {
|
||||||
k.hash(state);
|
k.hash(state);
|
||||||
v.borrow().hash(state);
|
v.read().hash(state);
|
||||||
}
|
}
|
||||||
// i hope this works because if doesn't then that'll be a problem
|
// i hope this works because if doesn't then that'll be a problem
|
||||||
ptr::hash(&self.command, state);
|
ptr::hash(&self.command, state);
|
||||||
|
@ -241,9 +243,16 @@ impl<S> Hash for CommandNode<S> {
|
||||||
|
|
||||||
impl<S> PartialEq for CommandNode<S> {
|
impl<S> PartialEq for CommandNode<S> {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
if self.children != other.children {
|
if self.children.len() != other.children.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for (k, v) in &self.children {
|
||||||
|
let other_child = other.children.get(k).unwrap();
|
||||||
|
if !Arc::ptr_eq(v, other_child) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(selfexecutes) = &self.command {
|
if let Some(selfexecutes) = &self.command {
|
||||||
// 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 {
|
||||||
|
|
|
@ -17,13 +17,14 @@ use super::ArgumentBuilder;
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
// public void testArguments() throws Exception {
|
// public void testArguments() throws Exception {
|
||||||
// final RequiredArgumentBuilder<Object, ?> argument = argument("bar", integer());
|
// final RequiredArgumentBuilder<Object, ?> argument = argument("bar",
|
||||||
|
// integer());
|
||||||
|
|
||||||
// builder.then(argument);
|
// builder.then(argument);
|
||||||
|
|
||||||
// assertThat(builder.getArguments(), hasSize(1));
|
// assertThat(builder.getArguments(), hasSize(1));
|
||||||
// assertThat(builder.getArguments(), hasItem((CommandNode<Object>) argument.build()));
|
// assertThat(builder.getArguments(), hasItem((CommandNode<Object>)
|
||||||
// }
|
// argument.build())); }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arguments() {
|
fn test_arguments() {
|
||||||
|
@ -37,7 +38,7 @@ fn test_arguments() {
|
||||||
.arguments
|
.arguments
|
||||||
.children
|
.children
|
||||||
.values()
|
.values()
|
||||||
.any(|e| *e.borrow() == *built_argument));
|
.any(|e| *e.read() == *built_argument));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
@ -61,8 +62,8 @@ fn test_arguments() {
|
||||||
// builder.then(literal("foo"));
|
// builder.then(literal("foo"));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// private static class TestableArgumentBuilder<S> extends ArgumentBuilder<S, TestableArgumentBuilder<S>> {
|
// private static class TestableArgumentBuilder<S> extends
|
||||||
// @Override
|
// ArgumentBuilder<S, TestableArgumentBuilder<S>> { @Override
|
||||||
// protected TestableArgumentBuilder<S> getThis() {
|
// protected TestableArgumentBuilder<S> getThis() {
|
||||||
// return this;
|
// return this;
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -251,31 +251,34 @@ fn execute_redirected_multiple_times() {
|
||||||
let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
|
let parse = subject.parse(input.into(), Rc::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, root);
|
assert_eq!(*parse.context.root.read(), *root.read());
|
||||||
assert_eq!(parse.context.nodes[0].range, parse.context.range);
|
assert_eq!(parse.context.nodes[0].range, parse.context.range);
|
||||||
assert_eq!(parse.context.nodes[0].node, redirect_node);
|
assert_eq!(*parse.context.nodes[0].node.read(), *redirect_node.read());
|
||||||
|
|
||||||
let child1 = parse.context.child.clone();
|
let child1 = parse.context.child.clone();
|
||||||
assert!(child1.is_some());
|
assert!(child1.is_some());
|
||||||
assert_eq!(child1.clone().unwrap().range.get(input), "redirected");
|
assert_eq!(child1.clone().unwrap().range.get(input), "redirected");
|
||||||
assert_eq!(child1.clone().unwrap().nodes.len(), 1);
|
assert_eq!(child1.clone().unwrap().nodes.len(), 1);
|
||||||
assert_eq!(child1.clone().unwrap().root, root);
|
assert_eq!(*child1.clone().unwrap().root.read(), *root.read());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
child1.clone().unwrap().nodes[0].range,
|
child1.clone().unwrap().nodes[0].range,
|
||||||
child1.clone().unwrap().range
|
child1.clone().unwrap().range
|
||||||
);
|
);
|
||||||
assert_eq!(child1.clone().unwrap().nodes[0].node, redirect_node);
|
assert_eq!(
|
||||||
|
*child1.clone().unwrap().nodes[0].node.read(),
|
||||||
|
*redirect_node.read()
|
||||||
|
);
|
||||||
|
|
||||||
let child2 = child1.unwrap().child.clone();
|
let child2 = child1.unwrap().child.clone();
|
||||||
assert!(child2.is_some());
|
assert!(child2.is_some());
|
||||||
assert_eq!(child2.clone().unwrap().range.get(input), "actual");
|
assert_eq!(child2.clone().unwrap().range.get(input), "actual");
|
||||||
assert_eq!(child2.clone().unwrap().nodes.len(), 1);
|
assert_eq!(child2.clone().unwrap().nodes.len(), 1);
|
||||||
assert_eq!(child2.clone().unwrap().root, root);
|
assert_eq!(*child2.clone().unwrap().root.read(), *root.read());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
child2.clone().unwrap().nodes[0].range,
|
child2.clone().unwrap().nodes[0].range,
|
||||||
child2.clone().unwrap().range
|
child2.clone().unwrap().range
|
||||||
);
|
);
|
||||||
assert_eq!(child2.unwrap().nodes[0].node, concrete_node);
|
assert_eq!(*child2.unwrap().nodes[0].node.read(), *concrete_node.read());
|
||||||
|
|
||||||
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
|
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 42);
|
||||||
}
|
}
|
||||||
|
@ -299,18 +302,18 @@ fn execute_redirected() {
|
||||||
let parse = subject.parse(input.into(), Rc::new(CommandSource {}));
|
let parse = subject.parse(input.into(), Rc::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, subject.root);
|
assert_eq!(*parse.context.root.read(), *subject.root.read());
|
||||||
assert_eq!(parse.context.nodes[0].range, parse.context.range);
|
assert_eq!(parse.context.nodes[0].range, parse.context.range);
|
||||||
assert_eq!(parse.context.nodes[0].node, redirect_node);
|
assert_eq!(*parse.context.nodes[0].node.read(), *redirect_node.read());
|
||||||
|
|
||||||
let parent = parse.context.child.clone();
|
let parent = parse.context.child.clone();
|
||||||
assert!(parent.is_some());
|
assert!(parent.is_some());
|
||||||
let parent = parent.unwrap();
|
let parent = parent.unwrap();
|
||||||
assert_eq!(parent.range.get(input), "actual");
|
assert_eq!(parent.range.get(input), "actual");
|
||||||
assert_eq!(parent.nodes.len(), 1);
|
assert_eq!(parent.nodes.len(), 1);
|
||||||
assert_eq!(parse.context.root, subject.root);
|
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, concrete_node);
|
assert_eq!(*parent.nodes[0].node.read(), *concrete_node.read());
|
||||||
assert_eq!(parent.source, Rc::new(CommandSource {}));
|
assert_eq!(parent.source, Rc::new(CommandSource {}));
|
||||||
|
|
||||||
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
|
assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2);
|
||||||
|
@ -406,5 +409,5 @@ fn get_path() {
|
||||||
fn find_node_doesnt_exist() {
|
fn find_node_doesnt_exist() {
|
||||||
let subject = CommandDispatcher::<()>::new();
|
let subject = CommandDispatcher::<()>::new();
|
||||||
|
|
||||||
assert_eq!(subject.find_node(&["foo", "bar"]), None)
|
assert!(subject.find_node(&["foo", "bar"]).is_none())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue