1use super::{
4 BrigadierRuntime, CommandRuntime, CommandSyntaxError, ContainsPrimitiveArgumentValue, NodeId,
5 PrimitiveArgumentValue, StringRange, StringReader, node::CommandRedirect,
6};
7use crate::command::{incorrectly_typed_argument, missing_argument};
8use std::sync::Arc;
9
10#[derive(Clone, Debug, PartialEq)]
11struct ParsedArgument<V> {
12 range: StringRange,
13 value: V,
14}
15
16#[derive(Clone, Debug, PartialEq)]
17struct ParsedArguments<V> {
18 values: Vec<(Box<str>, ParsedArgument<V>)>,
19}
20
21impl<V> Default for ParsedArguments<V> {
22 fn default() -> Self {
23 Self { values: Vec::new() }
24 }
25}
26
27impl<V> ParsedArguments<V> {
28 fn insert(&mut self, name: &str, range: StringRange, value: V) {
29 let argument = ParsedArgument { range, value };
30 if let Some((_, existing)) = self
31 .values
32 .iter_mut()
33 .find(|(existing_name, _)| existing_name.as_ref() == name)
34 {
35 *existing = argument;
36 } else {
37 self.values.push((name.into(), argument));
38 }
39 }
40
41 fn argument(&self, name: &str) -> Result<&V, CommandSyntaxError> {
42 self.values
43 .iter()
44 .find(|(argument_name, _)| argument_name.as_ref() == name)
45 .map(|(_, argument)| &argument.value)
46 .ok_or_else(|| missing_argument(name))
47 }
48}
49
50macro_rules! impl_get_primitive_argument_value {
51 ($name:ident, $ty:ty, $argument_value:ident) => {
52 fn $name(&self, name: &str) -> Result<$ty, CommandSyntaxError> {
53 let PrimitiveArgumentValue::$argument_value(value) =
54 self.argument(name)?.primitive_value(name)?
55 else {
56 return Err(incorrectly_typed_argument(name));
57 };
58 Ok(*value)
59 }
60 };
61}
62
63impl<V> ParsedArguments<V>
64where
65 V: ContainsPrimitiveArgumentValue,
66{
67 impl_get_primitive_argument_value!(boolean, bool, Bool);
68 impl_get_primitive_argument_value!(integer, i32, Integer);
69 impl_get_primitive_argument_value!(long, i64, Long);
70 impl_get_primitive_argument_value!(float, f32, Float);
71 impl_get_primitive_argument_value!(double, f64, Double);
72
73 fn string(&self, name: &str) -> Result<&str, CommandSyntaxError> {
74 let PrimitiveArgumentValue::String(value) = self.argument(name)?.primitive_value(name)?
75 else {
76 return Err(incorrectly_typed_argument(name));
77 };
78 Ok(value)
79 }
80}
81
82pub(crate) struct ArgumentSuggestionContext<'context, S, V> {
84 source: &'context S,
85 arguments: &'context ParsedArguments<V>,
86}
87
88impl<'context, S, V> ArgumentSuggestionContext<'context, S, V> {
89 const fn new(source: &'context S, arguments: &'context ParsedArguments<V>) -> Self {
90 Self { source, arguments }
91 }
92
93 pub(crate) const fn source(&self) -> &S {
95 self.source
96 }
97
98 pub(crate) fn argument(&self, name: &str) -> Result<&V, CommandSyntaxError> {
100 self.arguments.argument(name)
101 }
102}
103
104#[derive(Clone, Copy, Debug, PartialEq, Eq)]
106pub(crate) struct ParsedCommandNode {
107 node: NodeId,
108 range: StringRange,
109}
110
111impl ParsedCommandNode {
112 pub(crate) const fn node(self) -> NodeId {
114 self.node
115 }
116
117 pub(crate) const fn range(self) -> StringRange {
119 self.range
120 }
121}
122
123pub(crate) struct ParsedCommandContext<S, R = BrigadierRuntime>
125where
126 R: CommandRuntime<S>,
127{
128 source: Arc<S>,
129 root: NodeId,
130 arguments: ParsedArguments<R::ArgumentValue>,
131 executor: Option<Arc<R::Executor>>,
132 nodes: Vec<ParsedCommandNode>,
133 range: StringRange,
134 child: Option<Box<Self>>,
135 modifier: Option<Arc<R::Modifier>>,
136 forks: bool,
137}
138
139impl<S, R> ParsedCommandContext<S, R>
140where
141 R: CommandRuntime<S>,
142{
143 pub(super) fn new(source: Arc<S>, root: NodeId, start: usize) -> Self {
144 Self {
145 source,
146 root,
147 arguments: ParsedArguments::default(),
148 executor: None,
149 nodes: Vec::new(),
150 range: StringRange::at(start),
151 child: None,
152 modifier: None,
153 forks: false,
154 }
155 }
156
157 pub(super) fn branch(&self) -> Self {
158 Self {
159 source: Arc::clone(&self.source),
160 root: self.root,
161 arguments: self.arguments.clone(),
162 executor: self.executor.as_ref().map(Arc::clone),
163 nodes: self.nodes.clone(),
164 range: self.range,
165 child: self.child.as_ref().map(|child| Box::new(child.branch())),
166 modifier: self.modifier.as_ref().map(Arc::clone),
167 forks: self.forks,
168 }
169 }
170
171 pub(super) fn source(&self) -> &S {
172 &self.source
173 }
174
175 pub(super) fn argument_suggestion_context(
176 &self,
177 ) -> ArgumentSuggestionContext<'_, S, R::ArgumentValue> {
178 ArgumentSuggestionContext::new(&self.source, &self.arguments)
179 }
180
181 pub(super) const fn root(&self) -> NodeId {
182 self.root
183 }
184
185 pub(super) const fn source_arc(&self) -> &Arc<S> {
186 &self.source
187 }
188
189 pub(super) fn set_executor(&mut self, executor: Option<Arc<R::Executor>>) {
190 self.executor = executor;
191 }
192
193 pub(super) fn with_node(
194 &mut self,
195 node: NodeId,
196 range: StringRange,
197 redirect: Option<&CommandRedirect<S, R>>,
198 ) {
199 self.nodes.push(ParsedCommandNode { node, range });
200 self.range = StringRange::encompassing(self.range, range);
201 self.modifier = redirect
202 .and_then(|redirect| redirect.modifier.as_ref())
203 .map(Arc::clone);
204 self.forks = redirect.is_some_and(|redirect| redirect.forks);
205 }
206
207 pub(super) fn with_argument(
208 &mut self,
209 name: &str,
210 range: StringRange,
211 value: R::ArgumentValue,
212 ) {
213 self.arguments.insert(name, range, value);
214 }
215
216 pub(super) fn set_child(&mut self, child: Self) {
217 self.child = Some(Box::new(child));
218 }
219
220 pub(super) fn build(self, input: Arc<str>) -> Arc<CommandContext<S, R>> {
221 let child = self.child.map(|child| child.build(Arc::clone(&input)));
222 Arc::new(CommandContext {
223 source: self.source,
224 input,
225 root: self.root,
226 arguments: Arc::new(self.arguments),
227 executor: self.executor,
228 nodes: self.nodes.into(),
229 range: self.range,
230 child,
231 modifier: self.modifier,
232 forks: self.forks,
233 })
234 }
235
236 pub(super) fn find_suggestion_context(
237 &self,
238 cursor: usize,
239 ) -> Option<SuggestionContext<'_, S, R>> {
240 if cursor < self.range.start() {
241 return None;
242 }
243
244 if self.range.end() < cursor {
245 if let Some(child) = &self.child {
246 return child.find_suggestion_context(cursor);
247 }
248 return self.nodes.last().map_or_else(
249 || {
250 Some(SuggestionContext {
251 parent: self.root,
252 start: self.range.start(),
253 context: self,
254 })
255 },
256 |last| {
257 Some(SuggestionContext {
258 parent: last.node,
259 start: last.range.end() + 1,
260 context: self,
261 })
262 },
263 );
264 }
265
266 let mut previous = self.root;
267 for node in &self.nodes {
268 if node.range.start() <= cursor && cursor <= node.range.end() {
269 return Some(SuggestionContext {
270 parent: previous,
271 start: node.range.start(),
272 context: self,
273 });
274 }
275 previous = node.node;
276 }
277 Some(SuggestionContext {
278 parent: previous,
279 start: self.range.start(),
280 context: self,
281 })
282 }
283
284 pub(crate) fn nodes(&self) -> &[ParsedCommandNode] {
286 &self.nodes
287 }
288
289 pub(crate) const fn range(&self) -> StringRange {
291 self.range
292 }
293
294 pub(crate) const fn is_executable(&self) -> bool {
296 self.executor.is_some()
297 }
298
299 pub(crate) fn argument(&self, name: &str) -> Result<&R::ArgumentValue, CommandSyntaxError> {
301 self.arguments.argument(name)
302 }
303
304 pub(crate) fn child(&self) -> Option<&Self> {
306 self.child.as_deref()
307 }
308}
309
310impl<S, R> ParsedCommandContext<S, R>
311where
312 R: CommandRuntime<S>,
313 R::ArgumentValue: ContainsPrimitiveArgumentValue,
314{
315 pub(crate) fn boolean(&self, name: &str) -> Result<bool, CommandSyntaxError> {
317 self.arguments.boolean(name)
318 }
319
320 pub(crate) fn integer(&self, name: &str) -> Result<i32, CommandSyntaxError> {
322 self.arguments.integer(name)
323 }
324
325 pub(crate) fn long(&self, name: &str) -> Result<i64, CommandSyntaxError> {
327 self.arguments.long(name)
328 }
329
330 pub(crate) fn float(&self, name: &str) -> Result<f32, CommandSyntaxError> {
332 self.arguments.float(name)
333 }
334
335 pub(crate) fn double(&self, name: &str) -> Result<f64, CommandSyntaxError> {
337 self.arguments.double(name)
338 }
339
340 pub(crate) fn string(&self, name: &str) -> Result<&str, CommandSyntaxError> {
342 self.arguments.string(name)
343 }
344}
345
346pub(crate) struct CommandContext<S, R = BrigadierRuntime>
348where
349 R: CommandRuntime<S>,
350{
351 source: Arc<S>,
352 input: Arc<str>,
353 root: NodeId,
354 arguments: Arc<ParsedArguments<R::ArgumentValue>>,
355 executor: Option<Arc<R::Executor>>,
356 nodes: Arc<[ParsedCommandNode]>,
357 range: StringRange,
358 child: Option<Arc<Self>>,
359 modifier: Option<Arc<R::Modifier>>,
360 forks: bool,
361}
362
363impl<S, R> CommandContext<S, R>
364where
365 R: CommandRuntime<S>,
366{
367 pub(crate) fn source(&self) -> &S {
369 &self.source
370 }
371
372 pub(crate) fn input(&self) -> &str {
374 &self.input
375 }
376
377 pub(crate) const fn root(&self) -> NodeId {
379 self.root
380 }
381
382 pub(crate) fn nodes(&self) -> &[ParsedCommandNode] {
384 &self.nodes
385 }
386
387 pub(crate) const fn range(&self) -> StringRange {
389 self.range
390 }
391
392 pub(crate) fn argument(&self, name: &str) -> Result<&R::ArgumentValue, CommandSyntaxError> {
394 self.arguments.argument(name)
395 }
396
397 pub(crate) fn child(&self) -> Option<&Self> {
399 self.child.as_deref()
400 }
401
402 pub(super) const fn child_arc(&self) -> Option<&Arc<Self>> {
403 self.child.as_ref()
404 }
405
406 pub(crate) fn executor(&self) -> Option<&R::Executor> {
407 self.executor.as_deref()
408 }
409
410 pub(crate) fn modifier(&self) -> Option<&R::Modifier> {
411 self.modifier.as_deref()
412 }
413
414 pub(crate) const fn is_forked(&self) -> bool {
415 self.forks
416 }
417
418 pub(crate) fn copy_for(&self, source: Arc<S>) -> Self {
419 Self {
420 source,
421 input: Arc::clone(&self.input),
422 root: self.root,
423 arguments: Arc::clone(&self.arguments),
424 executor: self.executor.as_ref().map(Arc::clone),
425 nodes: Arc::clone(&self.nodes),
426 range: self.range,
427 child: self.child.as_ref().map(Arc::clone),
428 modifier: self.modifier.as_ref().map(Arc::clone),
429 forks: self.forks,
430 }
431 }
432
433 #[cfg(test)]
434 pub(super) fn empty(source: S, root: NodeId) -> Self {
435 Self {
436 source: Arc::new(source),
437 input: Arc::from(""),
438 root,
439 arguments: Arc::new(ParsedArguments::default()),
440 executor: None,
441 nodes: Arc::from([]),
442 range: StringRange::at(0),
443 child: None,
444 modifier: None,
445 forks: false,
446 }
447 }
448}
449
450impl<S, R> CommandContext<S, R>
451where
452 R: CommandRuntime<S>,
453 R::ArgumentValue: ContainsPrimitiveArgumentValue,
454{
455 pub(crate) fn boolean(&self, name: &str) -> Result<bool, CommandSyntaxError> {
457 self.arguments.boolean(name)
458 }
459
460 pub(crate) fn integer(&self, name: &str) -> Result<i32, CommandSyntaxError> {
462 self.arguments.integer(name)
463 }
464
465 pub(crate) fn long(&self, name: &str) -> Result<i64, CommandSyntaxError> {
467 self.arguments.long(name)
468 }
469
470 pub(crate) fn float(&self, name: &str) -> Result<f32, CommandSyntaxError> {
472 self.arguments.float(name)
473 }
474
475 pub(crate) fn double(&self, name: &str) -> Result<f64, CommandSyntaxError> {
477 self.arguments.double(name)
478 }
479
480 pub(crate) fn string(&self, name: &str) -> Result<&str, CommandSyntaxError> {
482 self.arguments.string(name)
483 }
484}
485
486pub(super) struct SuggestionContext<'context, S, R>
487where
488 R: CommandRuntime<S>,
489{
490 pub(super) parent: NodeId,
491 pub(super) start: usize,
492 pub(super) context: &'context ParsedCommandContext<S, R>,
493}
494
495#[derive(Clone, Debug, PartialEq)]
497pub(crate) struct ParseError {
498 node: NodeId,
499 error: CommandSyntaxError,
500}
501
502impl ParseError {
503 pub(super) const fn new(node: NodeId, error: CommandSyntaxError) -> Self {
504 Self { node, error }
505 }
506
507 pub(crate) const fn node(&self) -> NodeId {
509 self.node
510 }
511
512 pub(crate) const fn error(&self) -> &CommandSyntaxError {
514 &self.error
515 }
516
517 pub(super) fn into_error(self) -> CommandSyntaxError {
518 self.error
519 }
520}
521
522pub(crate) struct ParseResults<'input, S, R = BrigadierRuntime>
524where
525 R: CommandRuntime<S>,
526{
527 context: ParsedCommandContext<S, R>,
528 reader: StringReader<'input>,
529 errors: Vec<ParseError>,
530}
531
532impl<'input, S, R> ParseResults<'input, S, R>
533where
534 R: CommandRuntime<S>,
535{
536 pub(super) const fn new(
537 context: ParsedCommandContext<S, R>,
538 reader: StringReader<'input>,
539 errors: Vec<ParseError>,
540 ) -> Self {
541 Self {
542 context,
543 reader,
544 errors,
545 }
546 }
547
548 pub(crate) const fn reader(&self) -> &StringReader<'input> {
550 &self.reader
551 }
552
553 pub(crate) const fn context(&self) -> &ParsedCommandContext<S, R> {
555 &self.context
556 }
557
558 pub(crate) fn errors(&self) -> &[ParseError] {
560 &self.errors
561 }
562
563 pub(super) fn into_parts(
564 self,
565 ) -> (
566 ParsedCommandContext<S, R>,
567 StringReader<'input>,
568 Vec<ParseError>,
569 ) {
570 (self.context, self.reader, self.errors)
571 }
572}