1use std::{
2 collections::{BTreeMap, HashMap},
3 fmt::Debug,
4 hash::Hash,
5 ptr,
6 sync::Arc,
7};
8
9use parking_lot::RwLock;
10
11use crate::{
12 builder::{
13 argument_builder::ArgumentBuilderType, literal_argument_builder::Literal,
14 required_argument_builder::Argument,
15 },
16 context::{CommandContext, CommandContextBuilder, ParsedArgument, StringRange},
17 exceptions::{BuiltInExceptions, CommandSyntaxException},
18 modifier::RedirectModifier,
19 string_reader::StringReader,
20 suggestion::{Suggestions, SuggestionsBuilder},
21};
22
23pub type Command<S> = Option<Arc<dyn Fn(&CommandContext<S>) -> i32 + Send + Sync>>;
24
25#[non_exhaustive]
27pub struct CommandNode<S> {
28 pub value: ArgumentBuilderType,
29
30 pub children: BTreeMap<String, Arc<RwLock<CommandNode<S>>>>,
32 pub literals: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
33 pub arguments: HashMap<String, Arc<RwLock<CommandNode<S>>>>,
34
35 pub command: Command<S>,
36 pub requirement: Arc<dyn Fn(&S) -> bool + Send + Sync>,
37 pub redirect: Option<Arc<RwLock<CommandNode<S>>>>,
38 pub forks: bool,
39 pub modifier: Option<Arc<RedirectModifier<S>>>,
40}
41
42impl<S> Clone for CommandNode<S> {
43 fn clone(&self) -> Self {
44 Self {
45 value: self.value.clone(),
46 children: self.children.clone(),
47 literals: self.literals.clone(),
48 arguments: self.arguments.clone(),
49 command: self.command.clone(),
50 requirement: self.requirement.clone(),
51 redirect: self.redirect.clone(),
52 forks: self.forks,
53 modifier: self.modifier.clone(),
54 }
55 }
56}
57
58impl<S> CommandNode<S> {
59 pub fn literal(&self) -> &Literal {
62 match self.value {
63 ArgumentBuilderType::Literal(ref literal) => literal,
64 _ => panic!("CommandNode::literal() called on non-literal node"),
65 }
66 }
67 pub fn argument(&self) -> &Argument {
70 match self.value {
71 ArgumentBuilderType::Argument(ref argument) => argument,
72 _ => panic!("CommandNode::argument() called on non-argument node"),
73 }
74 }
75
76 pub fn get_relevant_nodes(&self, input: &mut StringReader) -> Vec<Arc<RwLock<CommandNode<S>>>> {
77 let literals = &self.literals;
78
79 if literals.is_empty() {
80 self.arguments.values().cloned().collect()
81 } else {
82 let cursor = input.cursor();
83 while input.can_read() && input.peek() != ' ' {
84 input.skip();
85 }
86 let text: String = input
87 .string()
88 .chars()
89 .skip(cursor)
90 .take(input.cursor() - cursor)
91 .collect();
92 input.cursor = cursor;
93 let literal = literals.get(&text);
94 if let Some(literal) = literal {
95 vec![literal.clone()]
96 } else {
97 self.arguments.values().cloned().collect()
98 }
99 }
100 }
101
102 pub fn can_use(&self, source: &S) -> bool {
103 (self.requirement)(source)
104 }
105
106 pub fn add_child(&mut self, node: &Arc<RwLock<CommandNode<S>>>) {
107 let child = self.children.get(node.read().name());
108 if let Some(child) = child {
109 if let Some(command) = &node.read().command {
111 child.write().command = Some(command.clone());
112 }
113 for grandchild in node.read().children.values() {
114 child.write().add_child(grandchild);
115 }
116 } else {
117 self.children
118 .insert(node.read().name().to_string(), node.clone());
119 match &node.read().value {
120 ArgumentBuilderType::Literal(literal) => {
121 self.literals.insert(literal.value.clone(), node.clone());
122 }
123 ArgumentBuilderType::Argument(argument) => {
124 self.arguments.insert(argument.name.clone(), node.clone());
125 }
126 }
127 }
128 }
129
130 pub fn name(&self) -> &str {
131 match &self.value {
132 ArgumentBuilderType::Argument(argument) => &argument.name,
133 ArgumentBuilderType::Literal(literal) => &literal.value,
134 }
135 }
136
137 pub fn usage_text(&self) -> String {
138 match &self.value {
139 ArgumentBuilderType::Argument(argument) => format!("<{}>", argument.name),
140 ArgumentBuilderType::Literal(literal) => literal.value.to_owned(),
141 }
142 }
143
144 pub fn child(&self, name: &str) -> Option<Arc<RwLock<CommandNode<S>>>> {
145 self.children.get(name).cloned()
146 }
147
148 pub fn parse_with_context(
149 &self,
150 reader: &mut StringReader,
151 context_builder: &mut CommandContextBuilder<S>,
152 ) -> Result<(), CommandSyntaxException> {
153 match self.value {
154 ArgumentBuilderType::Argument(ref argument) => {
155 let start = reader.cursor();
156 let result = argument.parse(reader)?;
157 let parsed = ParsedArgument {
158 range: StringRange::between(start, reader.cursor()),
159 result,
160 };
161
162 context_builder.with_argument(&argument.name, parsed.clone());
163 context_builder.with_node(Arc::new(RwLock::new(self.clone())), parsed.range);
164
165 Ok(())
166 }
167 ArgumentBuilderType::Literal(ref literal) => {
168 let start = reader.cursor();
169 let end = self.parse(reader);
170
171 if let Some(end) = end {
172 context_builder.with_node(
173 Arc::new(RwLock::new(self.clone())),
174 StringRange::between(start, end),
175 );
176 return Ok(());
177 }
178
179 Err(BuiltInExceptions::LiteralIncorrect {
180 expected: literal.value.clone(),
181 }
182 .create_with_context(reader))
183 }
184 }
185 }
186
187 fn parse(&self, reader: &mut StringReader) -> Option<usize> {
188 match self.value {
189 ArgumentBuilderType::Argument(_) => {
190 panic!("Can't parse argument.")
191 }
192 ArgumentBuilderType::Literal(ref literal) => {
193 let start = reader.cursor();
194 if reader.can_read_length(literal.value.len()) {
195 let end = start + literal.value.len();
196 if reader
197 .string()
198 .get(start..end)
199 .expect("Couldn't slice reader correctly?")
200 == literal.value
201 {
202 reader.cursor = end;
203 if !reader.can_read() || reader.peek() == ' ' {
204 return Some(end);
205 } else {
206 reader.cursor = start;
207 }
208 }
209 }
210 }
211 }
212 None
213 }
214
215 pub fn list_suggestions(
216 &self,
217 _context: CommandContext<S>,
220 builder: SuggestionsBuilder,
221 ) -> Suggestions {
222 match &self.value {
223 ArgumentBuilderType::Literal(literal) => {
224 if literal
225 .value
226 .to_lowercase()
227 .starts_with(builder.remaining_lowercase())
228 {
229 builder.suggest(&literal.value).build()
230 } else {
231 Suggestions::default()
232 }
233 }
234 ArgumentBuilderType::Argument(argument) => argument.list_suggestions(builder),
235 }
236 }
237}
238
239impl<S> Debug for CommandNode<S> {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 f.debug_struct("CommandNode")
242 .field("value", &self.value)
243 .field("children", &self.children)
244 .field("command", &self.command.is_some())
245 .field("redirect", &self.redirect)
247 .field("forks", &self.forks)
248 .finish()
250 }
251}
252
253impl<S> Default for CommandNode<S> {
254 fn default() -> Self {
255 Self {
256 value: ArgumentBuilderType::Literal(Literal::default()),
257
258 children: BTreeMap::new(),
259 literals: HashMap::new(),
260 arguments: HashMap::new(),
261
262 command: None,
263 requirement: Arc::new(|_| true),
264 redirect: None,
265 forks: false,
266 modifier: None,
267 }
268 }
269}
270
271impl<S> Hash for CommandNode<S> {
272 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
273 for (k, v) in &self.children {
275 k.hash(state);
276 v.read().hash(state);
277 }
278 ptr::hash(&self.command, state);
280 }
281}
282
283impl<S> PartialEq for CommandNode<S> {
284 fn eq(&self, other: &Self) -> bool {
285 if self.children.len() != other.children.len() {
286 return false;
287 }
288 for (k, v) in &self.children {
289 let other_child = other.children.get(k).unwrap();
290 if !Arc::ptr_eq(v, other_child) {
291 return false;
292 }
293 }
294
295 match &self.command {
296 Some(selfexecutes) => {
297 match &other.command {
299 Some(otherexecutes) =>
300 {
301 #[allow(ambiguous_wide_pointer_comparisons)]
302 if !Arc::ptr_eq(selfexecutes, otherexecutes) {
303 return false;
304 }
305 }
306 _ => {
307 return false;
308 }
309 }
310 }
311 _ => {
312 if other.command.is_some() {
313 return false;
314 }
315 }
316 }
317 true
318 }
319}
320impl<S> Eq for CommandNode<S> {}