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