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