azalea_brigadier/context/
context_chain.rs1use std::{rc::Rc, sync::Arc};
2
3use super::CommandContext;
4use crate::{errors::CommandSyntaxError, result_consumer::ResultConsumer};
5
6pub struct ContextChain<S> {
7 modifiers: Vec<Rc<CommandContext<S>>>,
8 executable: Rc<CommandContext<S>>,
9 next_stage_cache: Option<Rc<ContextChain<S>>>,
10}
11
12impl<S> ContextChain<S> {
13 pub fn new(modifiers: Vec<Rc<CommandContext<S>>>, executable: Rc<CommandContext<S>>) -> Self {
14 if executable.command.is_none() {
15 panic!("Last command in chain must be executable");
16 }
17 Self {
18 modifiers,
19 executable,
20 next_stage_cache: None,
21 }
22 }
23
24 pub fn try_flatten(root_context: Rc<CommandContext<S>>) -> Option<Self> {
25 let mut modifiers = Vec::new();
26 let mut current = root_context;
27 loop {
28 let child = current.child.clone();
29 let Some(child) = child else {
30 current.command.as_ref()?;
32
33 return Some(ContextChain::new(modifiers, current));
34 };
35
36 modifiers.push(current);
37 current = child;
38 }
39 }
40
41 pub fn run_modifier(
42 modifier: Rc<CommandContext<S>>,
43 source: Arc<S>,
44 result_consumer: &dyn ResultConsumer<S>,
45 forked_mode: bool,
46 ) -> Result<Vec<Arc<S>>, CommandSyntaxError> {
47 let source_modifier = modifier.redirect_modifier();
48 let Some(source_modifier) = source_modifier else {
49 return Ok(vec![source]);
50 };
51
52 let context_to_use = Rc::new(modifier.copy_for(source));
53 let err = match (source_modifier)(&context_to_use) {
54 Ok(res) => return Ok(res),
55 Err(e) => e,
56 };
57
58 result_consumer.on_command_complete(context_to_use, false, 0);
59 if forked_mode {
60 return Ok(vec![]);
61 }
62 Err(err)
63 }
64
65 pub fn run_executable(
66 &self,
67 executable: Rc<CommandContext<S>>,
68 source: Arc<S>,
69 result_consumer: &dyn ResultConsumer<S>,
70 forked_mode: bool,
71 ) -> Result<i32, CommandSyntaxError> {
72 let context_to_use = Rc::new(executable.copy_for(source));
73 let Some(command) = &executable.command else {
74 unimplemented!();
75 };
76
77 let err = match (command)(&context_to_use) {
78 Ok(result) => {
79 result_consumer.on_command_complete(context_to_use, true, result);
80 return if forked_mode { Ok(1) } else { Ok(result) };
81 }
82 Err(err) => err,
83 };
84
85 result_consumer.on_command_complete(context_to_use, false, 0);
86 if forked_mode { Ok(0) } else { Err(err) }
87 }
88
89 pub fn execute_all(
90 &self,
91 source: Arc<S>,
92 result_consumer: &dyn ResultConsumer<S>,
93 ) -> Result<i32, CommandSyntaxError> {
94 if self.modifiers.is_empty() {
95 return self.run_executable(self.executable.clone(), source, result_consumer, false);
96 }
97
98 let mut forked_mode = false;
99 let mut current_sources = vec![source];
100
101 for modifier in &self.modifiers {
102 forked_mode |= modifier.is_forked();
103
104 let mut next_sources = Vec::new();
105 for source_to_run in current_sources {
106 next_sources.extend(Self::run_modifier(
107 modifier.clone(),
108 source_to_run.clone(),
109 result_consumer,
110 forked_mode,
111 )?);
112 }
113 if next_sources.is_empty() {
114 return Ok(0);
115 }
116 current_sources = next_sources;
117 }
118
119 let mut result = 0;
120 for execution_source in current_sources {
121 result += self.run_executable(
122 self.executable.clone(),
123 execution_source,
124 result_consumer,
125 forked_mode,
126 )?;
127 }
128
129 Ok(result)
130 }
131
132 pub fn stage(&self) -> Stage {
133 if self.modifiers.is_empty() {
134 Stage::Execute
135 } else {
136 Stage::Modify
137 }
138 }
139
140 pub fn top_context(&self) -> Rc<CommandContext<S>> {
141 self.modifiers
142 .first()
143 .cloned()
144 .unwrap_or_else(|| self.executable.clone())
145 }
146
147 pub fn next_stage(&mut self) -> Option<Rc<ContextChain<S>>> {
148 let modifier_count = self.modifiers.len();
149 if modifier_count == 0 {
150 return None;
151 }
152
153 if self.next_stage_cache.is_none() {
154 self.next_stage_cache = Some(Rc::new(ContextChain::new(
155 self.modifiers[1..].to_vec(),
156 self.executable.clone(),
157 )));
158 }
159
160 self.next_stage_cache.clone()
161 }
162}
163
164pub enum Stage {
165 Modify,
166 Execute,
167}