diff options
Diffstat (limited to 'azalea-brigadier/src/tree/mod.rs')
| -rwxr-xr-x | azalea-brigadier/src/tree/mod.rs | 59 |
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 { |
