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