diff options
| author | mat <github@matdoes.dev> | 2022-04-24 17:37:57 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-04-24 17:37:57 -0500 |
| commit | 3e507f0db4020eaf406ba69aae3d4dc1301d29ac (patch) | |
| tree | ca6c127c9db6dfd14511e98944fc031fe5f1e43a /azalea-brigadier/src/context | |
| parent | 9f576c5600ba9a244bc0d433bb7de174284066a2 (diff) | |
| parent | b7641ff308aab7840d2a2253ae50f8ee496b2a97 (diff) | |
| download | azalea-drasl-3e507f0db4020eaf406ba69aae3d4dc1301d29ac.tar.xz | |
Merge branch 'main' into auth
Diffstat (limited to 'azalea-brigadier/src/context')
| -rwxr-xr-x | azalea-brigadier/src/context/command_context.rs | 80 | ||||
| -rwxr-xr-x | azalea-brigadier/src/context/command_context_builder.rs | 116 | ||||
| -rwxr-xr-x | azalea-brigadier/src/context/mod.rs | 11 | ||||
| -rwxr-xr-x | azalea-brigadier/src/context/parsed_argument.rs | 8 | ||||
| -rwxr-xr-x | azalea-brigadier/src/context/parsed_command_node.rs | 18 | ||||
| -rwxr-xr-x | azalea-brigadier/src/context/string_range.rs | 45 |
6 files changed, 278 insertions, 0 deletions
diff --git a/azalea-brigadier/src/context/command_context.rs b/azalea-brigadier/src/context/command_context.rs new file mode 100755 index 00000000..1834a73d --- /dev/null +++ b/azalea-brigadier/src/context/command_context.rs @@ -0,0 +1,80 @@ +use super::{parsed_command_node::ParsedCommandNode, string_range::StringRange, ParsedArgument}; +use crate::{modifier::RedirectModifier, tree::CommandNode}; +use std::{any::Any, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc}; + +/// A built `CommandContextBuilder`. +pub struct CommandContext<S> { + pub source: Rc<S>, + pub input: String, + pub arguments: HashMap<String, ParsedArgument>, + pub command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>, + pub root_node: Rc<RefCell<CommandNode<S>>>, + pub nodes: Vec<ParsedCommandNode<S>>, + pub range: StringRange, + pub child: Option<Rc<CommandContext<S>>>, + pub modifier: Option<Rc<RedirectModifier<S>>>, + pub forks: bool, +} + +impl<S> Clone for CommandContext<S> { + fn clone(&self) -> Self { + Self { + source: self.source.clone(), + input: self.input.clone(), + arguments: self.arguments.clone(), + command: self.command.clone(), + root_node: self.root_node.clone(), + nodes: self.nodes.clone(), + range: self.range.clone(), + child: self.child.clone(), + modifier: self.modifier.clone(), + forks: self.forks, + } + } +} + +impl<S> Debug for CommandContext<S> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CommandContext") + // .field("source", &self.source) + .field("input", &self.input) + // .field("arguments", &self.arguments) + // .field("command", &self.command) + // .field("root_node", &self.root_node) + // .field("nodes", &self.nodes) + .field("range", &self.range) + .field("child", &self.child) + // .field("modifier", &self.modifier) + .field("forks", &self.forks) + .finish() + } +} + +impl<S> CommandContext<S> { + pub fn copy_for(&self, source: Rc<S>) -> Self { + if Rc::ptr_eq(&source, &self.source) { + return self.clone(); + } + CommandContext { + source, + input: self.input.clone(), + arguments: self.arguments.clone(), + command: self.command.clone(), + root_node: self.root_node.clone(), + nodes: self.nodes.clone(), + range: self.range.clone(), + child: self.child.clone(), + modifier: self.modifier.clone(), + forks: self.forks, + } + } + + pub fn has_nodes(&self) -> bool { + !self.nodes.is_empty() + } + + pub fn argument(&self, name: &str) -> Option<Rc<dyn Any>> { + let argument = self.arguments.get(name); + argument.map(|a| a.result.clone()) + } +} diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs new file mode 100755 index 00000000..f192f6b7 --- /dev/null +++ b/azalea-brigadier/src/context/command_context_builder.rs @@ -0,0 +1,116 @@ +use super::{ + command_context::CommandContext, parsed_command_node::ParsedCommandNode, + string_range::StringRange, ParsedArgument, +}; +use crate::{command_dispatcher::CommandDispatcher, modifier::RedirectModifier, tree::CommandNode}; +use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc}; + +pub struct CommandContextBuilder<S> { + pub arguments: HashMap<String, ParsedArgument>, + pub root: Rc<RefCell<CommandNode<S>>>, + pub nodes: Vec<ParsedCommandNode<S>>, + pub dispatcher: Rc<CommandDispatcher<S>>, + pub source: Rc<S>, + pub command: Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>, + pub child: Option<Rc<CommandContextBuilder<S>>>, + pub range: StringRange, + pub modifier: Option<Rc<RedirectModifier<S>>>, + pub forks: bool, +} + +impl<S> Clone for CommandContextBuilder<S> { + fn clone(&self) -> Self { + Self { + arguments: self.arguments.clone(), + root: self.root.clone(), + nodes: self.nodes.clone(), + dispatcher: self.dispatcher.clone(), + source: self.source.clone(), + command: self.command.clone(), + child: self.child.clone(), + range: self.range.clone(), + modifier: self.modifier.clone(), + forks: self.forks, + } + } +} + +impl<S> CommandContextBuilder<S> { + pub fn new( + dispatcher: Rc<CommandDispatcher<S>>, + source: Rc<S>, + root_node: Rc<RefCell<CommandNode<S>>>, + start: usize, + ) -> Self { + Self { + arguments: HashMap::new(), + root: root_node, + source, + range: StringRange::at(start), + command: None, + dispatcher, + nodes: vec![], + child: None, + modifier: None, + forks: false, + } + } + + pub fn with_command( + &mut self, + command: &Option<Rc<dyn Fn(&CommandContext<S>) -> i32>>, + ) -> &Self { + self.command = command.clone(); + self + } + pub fn with_child(&mut self, child: Rc<CommandContextBuilder<S>>) -> &Self { + self.child = Some(child); + self + } + pub fn with_argument(&mut self, name: &str, argument: ParsedArgument) -> &Self { + self.arguments.insert(name.to_string(), argument); + self + } + pub fn with_node(&mut self, node: Rc<RefCell<CommandNode<S>>>, range: StringRange) -> &Self { + self.nodes.push(ParsedCommandNode { + node: node.clone(), + range: range.clone(), + }); + self.range = StringRange::encompassing(&self.range, &range); + self.modifier = node.borrow().modifier.clone(); + self.forks = node.borrow().forks; + self + } + + pub fn build(&self, input: &str) -> CommandContext<S> { + CommandContext { + arguments: self.arguments.clone(), + root_node: self.root.clone(), + nodes: self.nodes.clone(), + source: self.source.clone(), + command: self.command.clone(), + child: self.child.clone().map(|c| Rc::new(c.build(input))), + range: self.range.clone(), + forks: self.forks, + modifier: self.modifier.clone(), + input: input.to_string(), + } + } +} + +impl<S> Debug for CommandContextBuilder<S> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CommandContextBuilder") + // .field("arguments", &self.arguments) + .field("root", &self.root) + // .field("nodes", &self.nodes) + // .field("dispatcher", &self.dispatcher) + // .field("source", &self.source) + // .field("command", &self.command) + .field("child", &self.child) + .field("range", &self.range) + // .field("modifier", &self.modifier) + .field("forks", &self.forks) + .finish() + } +} diff --git a/azalea-brigadier/src/context/mod.rs b/azalea-brigadier/src/context/mod.rs new file mode 100755 index 00000000..d535602a --- /dev/null +++ b/azalea-brigadier/src/context/mod.rs @@ -0,0 +1,11 @@ +mod command_context; +mod command_context_builder; +mod parsed_argument; +mod parsed_command_node; +mod string_range; + +pub use command_context::CommandContext; +pub use command_context_builder::CommandContextBuilder; +pub use parsed_argument::ParsedArgument; +pub use parsed_command_node::ParsedCommandNode; +pub use string_range::StringRange; diff --git a/azalea-brigadier/src/context/parsed_argument.rs b/azalea-brigadier/src/context/parsed_argument.rs new file mode 100755 index 00000000..3302b1be --- /dev/null +++ b/azalea-brigadier/src/context/parsed_argument.rs @@ -0,0 +1,8 @@ +use super::string_range::StringRange; +use std::{any::Any, rc::Rc}; + +#[derive(Clone)] +pub struct ParsedArgument { + pub range: StringRange, + pub result: Rc<dyn Any>, +} diff --git a/azalea-brigadier/src/context/parsed_command_node.rs b/azalea-brigadier/src/context/parsed_command_node.rs new file mode 100755 index 00000000..ed49928d --- /dev/null +++ b/azalea-brigadier/src/context/parsed_command_node.rs @@ -0,0 +1,18 @@ +use super::string_range::StringRange; +use crate::tree::CommandNode; +use std::{cell::RefCell, rc::Rc}; + +#[derive(Debug)] +pub struct ParsedCommandNode<S> { + pub node: Rc<RefCell<CommandNode<S>>>, + pub range: StringRange, +} + +impl<S> Clone for ParsedCommandNode<S> { + fn clone(&self) -> Self { + Self { + node: self.node.clone(), + range: self.range.clone(), + } + } +} diff --git a/azalea-brigadier/src/context/string_range.rs b/azalea-brigadier/src/context/string_range.rs new file mode 100755 index 00000000..8ca88624 --- /dev/null +++ b/azalea-brigadier/src/context/string_range.rs @@ -0,0 +1,45 @@ +use std::cmp; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +pub struct StringRange { + start: usize, + end: usize, +} + +impl StringRange { + pub fn new(start: usize, end: usize) -> Self { + Self { start, end } + } + + pub fn at(pos: usize) -> Self { + Self::new(pos, pos) + } + + pub fn between(start: usize, end: usize) -> Self { + Self::new(start, end) + } + + pub fn encompassing(a: &Self, b: &Self) -> Self { + Self::new(cmp::min(a.start, b.start), cmp::max(a.end, b.end)) + } + + pub fn start(&self) -> usize { + self.start + } + + pub fn end(&self) -> usize { + self.end + } + + pub fn get<'a>(&self, reader: &'a str) -> &'a str { + &reader[self.start..self.end] + } + + pub fn is_empty(&self) -> bool { + self.start == self.end + } + + pub fn length(&self) -> usize { + self.end - self.start + } +} |
