aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/tree/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'azalea-brigadier/src/tree/mod.rs')
-rwxr-xr-xazalea-brigadier/src/tree/mod.rs59
1 files changed, 34 insertions, 25 deletions
diff --git a/azalea-brigadier/src/tree/mod.rs b/azalea-brigadier/src/tree/mod.rs
index bb6af68d..cec972dc 100755
--- a/azalea-brigadier/src/tree/mod.rs
+++ b/azalea-brigadier/src/tree/mod.rs
@@ -1,3 +1,5 @@
+use parking_lot::RwLock;
+
use crate::{
builder::{
argument_builder::ArgumentBuilderType, literal_argument_builder::Literal,
@@ -8,24 +10,24 @@ use crate::{
modifier::RedirectModifier,
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, 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.
#[non_exhaustive]
pub struct CommandNode<S> {
pub value: ArgumentBuilderType,
- pub children: HashMap<String, Rc<RefCell<CommandNode<S>>>>,
- pub literals: HashMap<String, Rc<RefCell<CommandNode<S>>>>,
- pub arguments: HashMap<String, Rc<RefCell<CommandNode<S>>>>,
+ pub children: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
+ pub literals: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
+ pub arguments: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
pub command: Command<S>,
- pub requirement: Rc<dyn Fn(Rc<S>) -> bool>,
- pub redirect: Option<Rc<RefCell<CommandNode<S>>>>,
+ pub requirement: Arc<dyn Fn(Arc<S>) -> bool + Send + Sync>,
+ pub redirect: Option<Arc<RwLock<CommandNode<S>>>>,
pub forks: bool,
- pub modifier: Option<Rc<RedirectModifier<S>>>,
+ pub modifier: Option<Arc<RedirectModifier<S>>>,
}
impl<S> Clone for CommandNode<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;
if literals.is_empty() {
@@ -88,24 +90,24 @@ 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)
}
- pub fn add_child(&mut self, node: &Rc<RefCell<CommandNode<S>>>) {
- let child = self.children.get(node.borrow().name());
+ pub fn add_child(&mut self, node: &Arc<RwLock<CommandNode<S>>>) {
+ let child = self.children.get(node.read().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());
+ if let Some(command) = &node.read().command {
+ child.write().command = Some(command.clone());
}
- for grandchild in node.borrow().children.values() {
- child.borrow_mut().add_child(grandchild);
+ for grandchild in node.read().children.values() {
+ child.write().add_child(grandchild);
}
} else {
self.children
- .insert(node.borrow().name().to_string(), node.clone());
- match &node.borrow().value {
+ .insert(node.read().name().to_string(), node.clone());
+ match &node.read().value {
ArgumentBuilderType::Literal(literal) => {
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()
}
@@ -142,7 +144,7 @@ impl<S> CommandNode<S> {
};
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(())
}
@@ -152,7 +154,7 @@ impl<S> CommandNode<S> {
if let Some(end) = end {
context_builder.with_node(
- Rc::new(RefCell::new(self.clone())),
+ Arc::new(RwLock::new(self.clone())),
StringRange::between(start, end),
);
return Ok(());
@@ -219,7 +221,7 @@ impl<S> Default for CommandNode<S> {
arguments: HashMap::new(),
command: None,
- requirement: Rc::new(|_| true),
+ requirement: Arc::new(|_| true),
redirect: None,
forks: false,
modifier: None,
@@ -232,7 +234,7 @@ impl<S> Hash for CommandNode<S> {
// hash the children
for (k, v) in &self.children {
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
ptr::hash(&self.command, state);
@@ -241,14 +243,21 @@ impl<S> Hash for CommandNode<S> {
impl<S> PartialEq for CommandNode<S> {
fn eq(&self, other: &Self) -> bool {
- if self.children != other.children {
+ if self.children.len() != other.children.len() {
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 {
// 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) {
+ if !Arc::ptr_eq(selfexecutes, otherexecutes) {
return false;
}
} else {