1use std::sync::Arc;
4
5use super::{
6 ArgumentType, BrigadierRuntime, CommandContext, CommandRequirement, CommandRuntime,
7 CommandSyntaxError, NodeId, RegistrationError, RegistrationErrorKind,
8 node::{
9 CommandNodeData, CommandRedirect, CommandRedirectTarget, UnregisteredCommandNode,
10 merge_or_push,
11 },
12 runtime::{BrigadierExecutor, BrigadierModifier},
13};
14
15pub(crate) struct CommandNodeBuilder<S, R = BrigadierRuntime>
17where
18 R: CommandRuntime<S>,
19{
20 data: CommandNodeData<R::Argument>,
21 children: Vec<Self>,
22 executor: Option<Arc<R::Executor>>,
23 requirement: CommandRequirement<S>,
24 execution_requirement: CommandRequirement<S>,
25 redirect: Option<CommandRedirect<S, R>>,
26}
27
28pub(crate) struct CommandRequirementRoute<S> {
30 traversal: CommandRequirement<S>,
31 execution: CommandRequirement<S>,
32}
33
34impl<S> CommandRequirementRoute<S> {
35 pub(crate) const fn new(
37 traversal: CommandRequirement<S>,
38 execution: CommandRequirement<S>,
39 ) -> Self {
40 Self {
41 traversal,
42 execution,
43 }
44 }
45}
46
47impl<S> Clone for CommandRequirementRoute<S> {
48 fn clone(&self) -> Self {
49 Self {
50 traversal: self.traversal.clone(),
51 execution: self.execution.clone(),
52 }
53 }
54}
55
56#[derive(Clone, Debug, PartialEq, Eq)]
57struct RequirementRouteKey {
58 governing_scope: Option<usize>,
59 descendant_scopes: Vec<usize>,
60}
61
62#[derive(Clone, Copy)]
63struct ActiveRequirementScope<'path> {
64 index: usize,
65 remaining: &'path [Box<str>],
66}
67
68impl<S, R> Clone for CommandNodeBuilder<S, R>
69where
70 R: CommandRuntime<S>,
71 R::Argument: Clone,
72{
73 fn clone(&self) -> Self {
74 Self {
75 data: self.data.clone(),
76 children: self.children.clone(),
77 executor: self.executor.as_ref().map(Arc::clone),
78 requirement: self.requirement.clone(),
79 execution_requirement: self.execution_requirement.clone(),
80 redirect: self.redirect.clone(),
81 }
82 }
83}
84
85pub(crate) fn literal<S>(name: impl Into<Box<str>>) -> CommandNodeBuilder<S> {
87 CommandNodeBuilder::literal(name)
88}
89
90pub(crate) fn argument<S>(
92 name: impl Into<Box<str>>,
93 argument_type: ArgumentType,
94) -> CommandNodeBuilder<S> {
95 CommandNodeBuilder::argument(name, argument_type)
96}
97
98impl<S, R> CommandNodeBuilder<S, R>
99where
100 R: CommandRuntime<S>,
101{
102 pub(crate) fn literal(name: impl Into<Box<str>>) -> Self {
104 Self {
105 data: CommandNodeData::Literal(name.into()),
106 children: Vec::new(),
107 executor: None,
108 requirement: CommandRequirement::allow_all(),
109 execution_requirement: CommandRequirement::allow_all(),
110 redirect: None,
111 }
112 }
113
114 pub(crate) fn argument(name: impl Into<Box<str>>, argument_type: R::Argument) -> Self {
116 Self {
117 data: CommandNodeData::Argument {
118 name: name.into(),
119 argument_type,
120 },
121 children: Vec::new(),
122 executor: None,
123 requirement: CommandRequirement::allow_all(),
124 execution_requirement: CommandRequirement::allow_all(),
125 redirect: None,
126 }
127 }
128
129 pub(crate) fn literal_name(&self) -> Option<&str> {
131 match &self.data {
132 CommandNodeData::Literal(name) => Some(name),
133 CommandNodeData::Root | CommandNodeData::Argument { .. } => None,
134 }
135 }
136
137 pub(crate) fn with_literal_name(mut self, name: impl Into<Box<str>>) -> Option<Self> {
139 let CommandNodeData::Literal(literal) = &mut self.data else {
140 return None;
141 };
142 *literal = name.into();
143 Some(self)
144 }
145
146 #[must_use]
148 pub(crate) fn then(mut self, child: Self) -> Self {
149 self.children.push(child);
150 self
151 }
152
153 #[must_use]
155 pub(crate) fn executes_with_executor(mut self, executor: Arc<R::Executor>) -> Self {
156 self.executor = Some(executor);
157 self
158 }
159
160 #[must_use]
162 pub(crate) fn requires(mut self, requirement: CommandRequirement<S>) -> Self {
163 self.requirement = requirement;
164 self
165 }
166
167 #[must_use]
169 pub(crate) fn also_requires(mut self, requirement: CommandRequirement<S>) -> Self
170 where
171 S: 'static,
172 {
173 self.requirement = self.requirement.and(requirement);
174 self
175 }
176
177 #[must_use]
179 pub(crate) fn also_requires_execution(mut self, requirement: CommandRequirement<S>) -> Self
180 where
181 S: 'static,
182 {
183 self.execution_requirement = self.execution_requirement.and(requirement);
184 self
185 }
186
187 pub(crate) fn literal_path_match_count(&self, path: &[Box<str>]) -> usize {
191 let Some((name, remaining)) = path.split_first() else {
192 return 0;
193 };
194 let mut matches = 0;
195 for child in &self.children {
196 let Some(literal) = child.literal_name() else {
197 matches += child.literal_path_match_count(path);
198 continue;
199 };
200 if literal != name.as_ref() {
201 continue;
202 }
203 if remaining.is_empty() {
204 matches += 1;
205 } else {
206 matches += child.literal_path_match_count(remaining);
207 }
208 }
209 matches
210 }
211
212 pub(crate) fn apply_scoped_requirements(
217 &mut self,
218 scope_paths: &[Vec<Box<str>>],
219 mut requirements_for: impl FnMut(Option<usize>, &[usize]) -> CommandRequirementRoute<S>,
220 ) where
221 S: 'static,
222 {
223 let active = scope_paths
224 .iter()
225 .enumerate()
226 .map(|(index, path)| ActiveRequirementScope {
227 index,
228 remaining: path,
229 })
230 .collect::<Vec<_>>();
231 let mut cache = Vec::new();
232 self.apply_scoped_requirements_inner(
233 None,
234 &active,
235 None,
236 &mut cache,
237 &mut requirements_for,
238 );
239 }
240
241 fn apply_scoped_requirements_inner<F>(
242 &mut self,
243 inherited_scope: Option<usize>,
244 active: &[ActiveRequirementScope<'_>],
245 parent_route: Option<&RequirementRouteKey>,
246 cache: &mut Vec<(RequirementRouteKey, CommandRequirementRoute<S>)>,
247 requirements_for: &mut F,
248 ) where
249 S: 'static,
250 F: FnMut(Option<usize>, &[usize]) -> CommandRequirementRoute<S>,
251 {
252 let governing_scope = active
253 .iter()
254 .find(|scope| scope.remaining.is_empty())
255 .map_or(inherited_scope, |scope| Some(scope.index));
256 let descendant_scopes = active
257 .iter()
258 .filter(|scope| !scope.remaining.is_empty())
259 .map(|scope| scope.index)
260 .collect::<Vec<_>>();
261 let route = RequirementRouteKey {
262 governing_scope,
263 descendant_scopes,
264 };
265 let requirements = cached_route_requirements(cache, &route, requirements_for);
266
267 if parent_route != Some(&route) {
268 self.requirement = self.requirement.clone().and(requirements.traversal);
269 }
270 if !route.descendant_scopes.is_empty() && self.executor.is_some() {
271 self.execution_requirement = self
272 .execution_requirement
273 .clone()
274 .and(requirements.execution);
275 }
276
277 for child in &mut self.children {
278 let child_active = if let Some(literal) = child.literal_name() {
279 active
280 .iter()
281 .filter_map(|scope| {
282 let (name, remaining) = scope.remaining.split_first()?;
283 (name.as_ref() == literal).then_some(ActiveRequirementScope {
284 index: scope.index,
285 remaining,
286 })
287 })
288 .collect::<Vec<_>>()
289 } else {
290 active
291 .iter()
292 .filter(|scope| {
293 !scope.remaining.is_empty()
294 && child.literal_path_match_count(scope.remaining) > 0
295 })
296 .copied()
297 .collect::<Vec<_>>()
298 };
299 child.apply_scoped_requirements_inner(
300 governing_scope,
301 &child_active,
302 Some(&route),
303 cache,
304 requirements_for,
305 );
306 }
307 }
308
309 #[must_use]
311 pub(crate) fn redirects(mut self, target: impl Into<CommandRedirectTarget>) -> Self {
312 self.redirect = Some(CommandRedirect::identity(target.into()));
313 self
314 }
315
316 #[must_use]
318 pub(crate) fn redirects_with_modifier(
319 mut self,
320 target: impl Into<CommandRedirectTarget>,
321 modifier: Arc<R::Modifier>,
322 forks: bool,
323 ) -> Self {
324 self.redirect = Some(CommandRedirect::with_modifier(
325 target.into(),
326 modifier,
327 forks,
328 ));
329 self
330 }
331
332 pub(super) fn normalize(self) -> Result<UnregisteredCommandNode<S, R>, RegistrationError> {
333 let mut children = Vec::new();
334 for child in self.children {
335 merge_or_push(&mut children, child.normalize()?)?;
336 }
337 if self.redirect.is_some() && !children.is_empty() {
338 return Err(RegistrationError::new(
339 RegistrationErrorKind::RedirectWithChildren {
340 name: self.data.name().into(),
341 },
342 ));
343 }
344
345 Ok(UnregisteredCommandNode {
346 data: self.data,
347 children,
348 executor: self.executor,
349 requirement: self.requirement,
350 execution_requirement: self.execution_requirement,
351 redirect: self.redirect,
352 })
353 }
354}
355
356fn cached_route_requirements<S, F>(
357 cache: &mut Vec<(RequirementRouteKey, CommandRequirementRoute<S>)>,
358 route: &RequirementRouteKey,
359 requirements_for: &mut F,
360) -> CommandRequirementRoute<S>
361where
362 F: FnMut(Option<usize>, &[usize]) -> CommandRequirementRoute<S>,
363{
364 if let Some((_, requirements)) = cache.iter().find(|(cached, _)| cached == route) {
365 return requirements.clone();
366 }
367 let requirements = requirements_for(route.governing_scope, &route.descendant_scopes);
368 cache.push((route.clone(), requirements.clone()));
369 requirements
370}
371
372impl<S> CommandNodeBuilder<S, BrigadierRuntime> {
373 #[must_use]
375 pub(crate) fn executes(
376 self,
377 executor: impl Fn(&CommandContext<S>) -> Result<i32, CommandSyntaxError> + Send + Sync + 'static,
378 ) -> Self {
379 let executor: Arc<BrigadierExecutor<S>> = Arc::new(executor);
380 self.executes_with_executor(executor)
381 }
382
383 #[must_use]
385 pub(crate) fn redirects_with(
386 self,
387 target: NodeId,
388 modifier: impl Fn(&CommandContext<S>) -> Result<S, CommandSyntaxError> + Send + Sync + 'static,
389 ) -> Self {
390 let modifier: Arc<BrigadierModifier<S>> =
391 Arc::new(move |context| modifier(context).map(|source| vec![source]));
392 self.redirects_with_modifier(target, modifier, false)
393 }
394
395 #[must_use]
397 pub(crate) fn forks(
398 self,
399 target: NodeId,
400 modifier: impl Fn(&CommandContext<S>) -> Result<Vec<S>, CommandSyntaxError>
401 + Send
402 + Sync
403 + 'static,
404 ) -> Self {
405 let modifier: Arc<BrigadierModifier<S>> = Arc::new(modifier);
406 self.redirects_with_modifier(target, modifier, true)
407 }
408}