1
2
Fork 0
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:
mat 2023-05-05 23:09:57 -05:00
parent e4176937f0
commit 12370ab076
10 changed files with 111 additions and 88 deletions

1
Cargo.lock generated
View file

@ -233,6 +233,7 @@ version = "0.6.0"
dependencies = [ dependencies = [
"azalea-buf", "azalea-buf",
"azalea-chat", "azalea-chat",
"parking_lot",
] ]
[[package]] [[package]]

View file

@ -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"]

View file

@ -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 {

View file

@ -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;

View file

@ -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>>>,

View file

@ -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
} }

View file

@ -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,
} }

View file

@ -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 {

View file

@ -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;
// } // }

View file

@ -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())
} }