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