aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/context
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-04-24 17:37:57 -0500
committermat <github@matdoes.dev>2022-04-24 17:37:57 -0500
commit3e507f0db4020eaf406ba69aae3d4dc1301d29ac (patch)
treeca6c127c9db6dfd14511e98944fc031fe5f1e43a /azalea-brigadier/src/context
parent9f576c5600ba9a244bc0d433bb7de174284066a2 (diff)
parentb7641ff308aab7840d2a2253ae50f8ee496b2a97 (diff)
downloadazalea-drasl-3e507f0db4020eaf406ba69aae3d4dc1301d29ac.tar.xz
Merge branch 'main' into auth
Diffstat (limited to 'azalea-brigadier/src/context')
-rwxr-xr-xazalea-brigadier/src/context/command_context.rs80
-rwxr-xr-xazalea-brigadier/src/context/command_context_builder.rs116
-rwxr-xr-xazalea-brigadier/src/context/mod.rs11
-rwxr-xr-xazalea-brigadier/src/context/parsed_argument.rs8
-rwxr-xr-xazalea-brigadier/src/context/parsed_command_node.rs18
-rwxr-xr-xazalea-brigadier/src/context/string_range.rs45
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
+ }
+}