1#[allow(deprecated, unused_imports)]
3use std::{ascii::AsciiExt, fmt::Display};
4
5use crate::{
7 app::{
8 parser::{ParseResult, Parser},
9 settings::AppSettings as AS,
10 usage,
11 },
12 args::{settings::ArgSettings, AnyArg, ArgMatcher, MatchedArg},
13 errors::{Error, ErrorKind, Result as ClapResult},
14 fmt::{Colorizer, ColorizerOption},
15 INTERNAL_ERROR_MSG, INVALID_UTF8,
16};
17
18pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>)
19where
20 'a: 'b,
21 'b: 'z;
22
23impl<'a, 'b, 'z> Validator<'a, 'b, 'z> {
24 pub fn new(p: &'z mut Parser<'a, 'b>) -> Self {
25 Validator(p)
26 }
27
28 pub fn validate(
29 &mut self,
30 needs_val_of: ParseResult<'a>,
31 subcmd_name: Option<String>,
32 matcher: &mut ArgMatcher<'a>,
33 ) -> ClapResult<()> {
34 debugln!("Validator::validate;");
35 let mut reqs_validated = false;
36 self.0.add_env(matcher)?;
37 self.0.add_defaults(matcher)?;
38 if let ParseResult::Opt(a) = needs_val_of {
39 debugln!("Validator::validate: needs_val_of={:?}", a);
40 let o = {
41 self.0
42 .opts
43 .iter()
44 .find(|o| o.b.name == a)
45 .expect(INTERNAL_ERROR_MSG)
46 .clone()
47 };
48 self.validate_required(matcher)?;
49 reqs_validated = true;
50 let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) {
51 v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0)
52 } else {
53 true
54 };
55 if should_err {
56 return Err(Error::empty_value(
57 &o,
58 &*usage::create_error_usage(self.0, matcher, None),
59 self.0.color(),
60 ));
61 }
62 }
63
64 if matcher.is_empty()
65 && matcher.subcommand_name().is_none()
66 && self.0.is_set(AS::ArgRequiredElseHelp)
67 {
68 let mut out = vec![];
69 self.0.write_help_err(&mut out)?;
70 return Err(Error {
71 message: String::from_utf8_lossy(&*out).into_owned(),
72 kind: ErrorKind::MissingArgumentOrSubcommand,
73 info: None,
74 });
75 }
76 self.validate_blacklist(matcher)?;
77 if !(reqs_validated || self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) {
78 self.validate_required(matcher)?;
79 }
80 self.validate_matched_args(matcher)?;
81 matcher.usage(usage::create_usage_with_title(self.0, &[]));
82
83 Ok(())
84 }
85
86 fn validate_arg_values<A>(
87 &self,
88 arg: &A,
89 ma: &MatchedArg,
90 matcher: &ArgMatcher<'a>,
91 ) -> ClapResult<()>
92 where
93 A: AnyArg<'a, 'b> + Display,
94 {
95 debugln!("Validator::validate_arg_values: arg={:?}", arg.name());
96 for val in &ma.vals {
97 if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() {
98 debugln!(
99 "Validator::validate_arg_values: invalid UTF-8 found in val {:?}",
100 val
101 );
102 return Err(Error::invalid_utf8(
103 &*usage::create_error_usage(self.0, matcher, None),
104 self.0.color(),
105 ));
106 }
107 if let Some(p_vals) = arg.possible_vals() {
108 debugln!("Validator::validate_arg_values: possible_vals={:?}", p_vals);
109 let val_str = val.to_string_lossy();
110 let ok = if arg.is_set(ArgSettings::CaseInsensitive) {
111 p_vals.iter().any(|pv| pv.eq_ignore_ascii_case(&*val_str))
112 } else {
113 p_vals.contains(&&*val_str)
114 };
115 if !ok {
116 return Err(Error::invalid_value(
117 val_str,
118 p_vals,
119 arg,
120 &*usage::create_error_usage(self.0, matcher, None),
121 self.0.color(),
122 ));
123 }
124 }
125 if !arg.is_set(ArgSettings::EmptyValues)
126 && val.is_empty()
127 && matcher.contains(&*arg.name())
128 {
129 debugln!("Validator::validate_arg_values: illegal empty val found");
130 return Err(Error::empty_value(
131 arg,
132 &*usage::create_error_usage(self.0, matcher, None),
133 self.0.color(),
134 ));
135 }
136 if let Some(vtor) = arg.validator() {
137 debug!("Validator::validate_arg_values: checking validator...");
138 if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
139 sdebugln!("error");
140 return Err(Error::value_validation(Some(arg), e, self.0.color()));
141 } else {
142 sdebugln!("good");
143 }
144 }
145 if let Some(vtor) = arg.validator_os() {
146 debug!("Validator::validate_arg_values: checking validator_os...");
147 if let Err(e) = vtor(val) {
148 sdebugln!("error");
149 return Err(Error::value_validation(
150 Some(arg),
151 (*e).to_string_lossy().to_string(),
152 self.0.color(),
153 ));
154 } else {
155 sdebugln!("good");
156 }
157 }
158 }
159 Ok(())
160 }
161
162 fn build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()> {
163 debugln!("build_err!: name={}", name);
164 let mut c_with = find_from!(self.0, &name, blacklist, matcher);
165 c_with = c_with.or_else(|| {
166 self.0
167 .find_any_arg(name)
168 .and_then(|aa| aa.blacklist())
169 .and_then(|bl| bl.iter().find(|arg| matcher.contains(arg)))
170 .and_then(|an| self.0.find_any_arg(an))
171 .map(|aa| format!("{}", aa))
172 });
173 debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &name);
174 let usg = usage::create_error_usage(self.0, matcher, None);
176 if let Some(f) = find_by_name!(self.0, name, flags, iter) {
177 debugln!("build_err!: It was a flag...");
178 Err(Error::argument_conflict(f, c_with, &*usg, self.0.color()))
179 } else if let Some(o) = find_by_name!(self.0, name, opts, iter) {
180 debugln!("build_err!: It was an option...");
181 Err(Error::argument_conflict(o, c_with, &*usg, self.0.color()))
182 } else {
183 match find_by_name!(self.0, name, positionals, values) {
184 Some(p) => {
185 debugln!("build_err!: It was a positional...");
186 Err(Error::argument_conflict(p, c_with, &*usg, self.0.color()))
187 }
188 None => panic!("{}", INTERNAL_ERROR_MSG),
189 }
190 }
191 }
192
193 fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> {
194 debugln!("Validator::validate_blacklist;");
195 let mut conflicts: Vec<&str> = vec![];
196 for (&name, _) in matcher.iter() {
197 debugln!("Validator::validate_blacklist:iter:{};", name);
198 if let Some(grps) = self.0.groups_for_arg(name) {
199 for grp in &grps {
200 if let Some(g) = self.0.groups.iter().find(|g| &g.name == grp) {
201 if !g.multiple {
202 for arg in &g.args {
203 if arg == &name {
204 continue;
205 }
206 conflicts.push(arg);
207 }
208 }
209 if let Some(ref gc) = g.conflicts {
210 conflicts.extend(&*gc);
211 }
212 }
213 }
214 }
215 if let Some(arg) = find_any_by_name!(self.0, name) {
216 if let Some(bl) = arg.blacklist() {
217 for conf in bl {
218 if matcher.get(conf).is_some() {
219 conflicts.push(conf);
220 }
221 }
222 }
223 } else {
224 debugln!("Validator::validate_blacklist:iter:{}:group;", name);
225 let args = self.0.arg_names_in_group(name);
226 for arg in &args {
227 debugln!(
228 "Validator::validate_blacklist:iter:{}:group:iter:{};",
229 name,
230 arg
231 );
232 if let Some(bl) = find_any_by_name!(self.0, *arg).unwrap().blacklist() {
233 for conf in bl {
234 if matcher.get(conf).is_some() {
235 conflicts.push(conf);
236 }
237 }
238 }
239 }
240 }
241 }
242
243 for name in &conflicts {
244 debugln!(
245 "Validator::validate_blacklist:iter:{}: Checking blacklisted arg",
246 name
247 );
248 let mut should_err = false;
249 if self.0.groups.iter().any(|g| &g.name == name) {
250 debugln!(
251 "Validator::validate_blacklist:iter:{}: groups contains it...",
252 name
253 );
254 for n in self.0.arg_names_in_group(name) {
255 debugln!(
256 "Validator::validate_blacklist:iter:{}:iter:{}: looking in group...",
257 name,
258 n
259 );
260 if matcher.contains(n) {
261 debugln!(
262 "Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...",
263 name,
264 n
265 );
266 return self.build_err(n, matcher);
267 }
268 }
269 } else if let Some(ma) = matcher.get(name) {
270 debugln!(
271 "Validator::validate_blacklist:iter:{}: matcher contains it...",
272 name
273 );
274 should_err = ma.occurs > 0;
275 }
276 if should_err {
277 return self.build_err(*name, matcher);
278 }
279 }
280 Ok(())
281 }
282
283 fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> {
284 debugln!("Validator::validate_matched_args;");
285 for (name, ma) in matcher.iter() {
286 debugln!(
287 "Validator::validate_matched_args:iter:{}: vals={:#?}",
288 name,
289 ma.vals
290 );
291 if let Some(opt) = find_by_name!(self.0, *name, opts, iter) {
292 self.validate_arg_num_vals(opt, ma, matcher)?;
293 self.validate_arg_values(opt, ma, matcher)?;
294 self.validate_arg_requires(opt, ma, matcher)?;
295 self.validate_arg_num_occurs(opt, ma, matcher)?;
296 } else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) {
297 self.validate_arg_requires(flag, ma, matcher)?;
298 self.validate_arg_num_occurs(flag, ma, matcher)?;
299 } else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) {
300 self.validate_arg_num_vals(pos, ma, matcher)?;
301 self.validate_arg_num_occurs(pos, ma, matcher)?;
302 self.validate_arg_values(pos, ma, matcher)?;
303 self.validate_arg_requires(pos, ma, matcher)?;
304 } else {
305 let grp = self
306 .0
307 .groups
308 .iter()
309 .find(|g| &g.name == name)
310 .expect(INTERNAL_ERROR_MSG);
311 if let Some(ref g_reqs) = grp.requires {
312 if g_reqs.iter().any(|&n| !matcher.contains(n)) {
313 return self.missing_required_error(matcher, None);
314 }
315 }
316 }
317 }
318 Ok(())
319 }
320
321 fn validate_arg_num_occurs<A>(
322 &self,
323 a: &A,
324 ma: &MatchedArg,
325 matcher: &ArgMatcher,
326 ) -> ClapResult<()>
327 where
328 A: AnyArg<'a, 'b> + Display,
329 {
330 debugln!("Validator::validate_arg_num_occurs: a={};", a.name());
331 if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) {
332 return Err(Error::unexpected_multiple_usage(
334 a,
335 &*usage::create_error_usage(self.0, matcher, None),
336 self.0.color(),
337 ));
338 }
339 Ok(())
340 }
341
342 fn validate_arg_num_vals<A>(
343 &self,
344 a: &A,
345 ma: &MatchedArg,
346 matcher: &ArgMatcher,
347 ) -> ClapResult<()>
348 where
349 A: AnyArg<'a, 'b> + Display,
350 {
351 debugln!("Validator::validate_arg_num_vals:{}", a.name());
352 if let Some(num) = a.num_vals() {
353 debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num);
354 let should_err = if a.is_set(ArgSettings::Multiple) {
355 ((ma.vals.len() as u64) % num) != 0
356 } else {
357 num != (ma.vals.len() as u64)
358 };
359 if should_err {
360 debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues");
361 return Err(Error::wrong_number_of_values(
362 a,
363 num,
364 if a.is_set(ArgSettings::Multiple) {
365 ma.vals.len() % num as usize
366 } else {
367 ma.vals.len()
368 },
369 if ma.vals.len() == 1
370 || (a.is_set(ArgSettings::Multiple) && (ma.vals.len() % num as usize) == 1)
371 {
372 "as"
373 } else {
374 "ere"
375 },
376 &*usage::create_error_usage(self.0, matcher, None),
377 self.0.color(),
378 ));
379 }
380 }
381 if let Some(num) = a.max_vals() {
382 debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num);
383 if (ma.vals.len() as u64) > num {
384 debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues");
385 return Err(Error::too_many_values(
386 ma.vals
387 .iter()
388 .last()
389 .expect(INTERNAL_ERROR_MSG)
390 .to_str()
391 .expect(INVALID_UTF8),
392 a,
393 &*usage::create_error_usage(self.0, matcher, None),
394 self.0.color(),
395 ));
396 }
397 }
398 let min_vals_zero = if let Some(num) = a.min_vals() {
399 debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num);
400 if (ma.vals.len() as u64) < num && num != 0 {
401 debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues");
402 return Err(Error::too_few_values(
403 a,
404 num,
405 ma.vals.len(),
406 &*usage::create_error_usage(self.0, matcher, None),
407 self.0.color(),
408 ));
409 }
410 num == 0
411 } else {
412 false
413 };
414 if a.takes_value() && !min_vals_zero && ma.vals.is_empty() {
417 return Err(Error::empty_value(
418 a,
419 &*usage::create_error_usage(self.0, matcher, None),
420 self.0.color(),
421 ));
422 }
423 Ok(())
424 }
425
426 fn validate_arg_requires<A>(
427 &self,
428 a: &A,
429 ma: &MatchedArg,
430 matcher: &ArgMatcher,
431 ) -> ClapResult<()>
432 where
433 A: AnyArg<'a, 'b> + Display,
434 {
435 debugln!("Validator::validate_arg_requires:{};", a.name());
436 if let Some(a_reqs) = a.requires() {
437 for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) {
438 let missing_req =
439 |v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name);
440 if ma.vals.iter().any(missing_req) {
441 return self.missing_required_error(matcher, None);
442 }
443 }
444 for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) {
445 if !matcher.contains(name) {
446 return self.missing_required_error(matcher, Some(name));
447 }
448 }
449 }
450 Ok(())
451 }
452
453 fn validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()> {
454 debugln!(
455 "Validator::validate_required: required={:?};",
456 self.0.required
457 );
458
459 let mut should_err = false;
460 let mut to_rem = Vec::new();
461 for name in &self.0.required {
462 debugln!("Validator::validate_required:iter:{}:", name);
463 if matcher.contains(name) {
464 continue;
465 }
466 if to_rem.contains(name) {
467 continue;
468 } else if let Some(a) = find_any_by_name!(self.0, *name) {
469 if self.is_missing_required_ok(a, matcher) {
470 to_rem.push(a.name());
471 if let Some(reqs) = a.requires() {
472 for r in reqs
473 .iter()
474 .filter(|&&(val, _)| val.is_none())
475 .map(|&(_, name)| name)
476 {
477 to_rem.push(r);
478 }
479 }
480 continue;
481 }
482 }
483 should_err = true;
484 break;
485 }
486 if should_err {
487 for r in &to_rem {
488 'inner: for i in (0..self.0.required.len()).rev() {
489 if &self.0.required[i] == r {
490 self.0.required.swap_remove(i);
491 break 'inner;
492 }
493 }
494 }
495 return self.missing_required_error(matcher, None);
496 }
497
498 for &(a, v, r) in &self.0.r_ifs {
500 if let Some(ma) = matcher.get(a) {
501 if matcher.get(r).is_none() && ma.vals.iter().any(|val| val == v) {
502 return self.missing_required_error(matcher, Some(r));
503 }
504 }
505 }
506 Ok(())
507 }
508
509 fn validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
510 debugln!("Validator::validate_arg_conflicts: a={:?};", a.name());
511 a.blacklist().map(|bl| {
512 bl.iter().any(|conf| {
513 matcher.contains(conf)
514 || self
515 .0
516 .groups
517 .iter()
518 .find(|g| &g.name == conf)
519 .map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg)))
520 })
521 })
522 }
523
524 fn validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> {
525 debugln!("Validator::validate_required_unless: a={:?};", a.name());
526 macro_rules! check {
527 ($how:ident, $_self:expr, $a:ident, $m:ident) => {{
528 $a.required_unless().map(|ru| {
529 ru.iter().$how(|n| {
530 $m.contains(n) || {
531 if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) {
532 grp.args.iter().any(|arg| $m.contains(arg))
533 } else {
534 false
535 }
536 }
537 })
538 })
539 }};
540 }
541 if a.is_set(ArgSettings::RequiredUnlessAll) {
542 check!(all, self.0, a, matcher)
543 } else {
544 check!(any, self.0, a, matcher)
545 }
546 }
547
548 fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> {
549 debugln!("Validator::missing_required_error: extra={:?}", extra);
550 let c = Colorizer::new(ColorizerOption {
551 use_stderr: true,
552 when: self.0.color(),
553 });
554 let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>();
555 if let Some(r) = extra {
556 reqs.push(r);
557 }
558 reqs.retain(|n| !matcher.contains(n));
559 reqs.dedup();
560 debugln!("Validator::missing_required_error: reqs={:#?}", reqs);
561 let req_args =
562 usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true)
563 .iter()
564 .fold(String::new(), |acc, s| {
565 acc + &format!("\n {}", c.error(s))[..]
566 });
567 debugln!(
568 "Validator::missing_required_error: req_args={:#?}",
569 req_args
570 );
571 Err(Error::missing_required_argument(
572 &*req_args,
573 &*usage::create_error_usage(self.0, matcher, extra),
574 self.0.color(),
575 ))
576 }
577
578 #[inline]
579 fn is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool {
580 debugln!("Validator::is_missing_required_ok: a={}", a.name());
581 self.validate_arg_conflicts(a, matcher).unwrap_or(false)
582 || self.validate_required_unless(a, matcher).unwrap_or(false)
583 }
584}