1 // std 2 #[allow(deprecated, unused_imports)] 3 use std::ascii::AsciiExt; 4 use std::fmt::Display; 5 6 // Internal 7 use app::parser::{ParseResult, Parser}; 8 use app::settings::AppSettings as AS; 9 use app::usage; 10 use args::settings::ArgSettings; 11 use args::{AnyArg, ArgMatcher, MatchedArg}; 12 use errors::Result as ClapResult; 13 use errors::{Error, ErrorKind}; 14 use fmt::{Colorizer, ColorizerOption}; 15 use INTERNAL_ERROR_MSG; 16 use INVALID_UTF8; 17 18 pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>) 19 where 20 'a: 'b, 21 'b: 'z; 22 23 impl<'a, 'b, 'z> Validator<'a, 'b, 'z> { new(p: &'z mut Parser<'a, 'b>) -> Self24 pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { 25 Validator(p) 26 } 27 validate( &mut self, needs_val_of: ParseResult<'a>, subcmd_name: Option<String>, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<()>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 !(self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) && !reqs_validated { 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 validate_arg_values<A>( &self, arg: &A, ma: &MatchedArg, matcher: &ArgMatcher<'a>, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,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 build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()>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(self 166 .0 167 .find_any_arg(name) 168 .map_or(None, |aa| aa.blacklist()) 169 .map_or(None, |bl| bl.iter().find(|arg| matcher.contains(arg))) 170 .map_or(None, |an| self.0.find_any_arg(an)) 171 .map_or(None, |aa| Some(format!("{}", aa)))); 172 debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &name); 173 // matcher.remove(&name); 174 let usg = usage::create_error_usage(self.0, matcher, None); 175 if let Some(f) = find_by_name!(self.0, name, flags, iter) { 176 debugln!("build_err!: It was a flag..."); 177 Err(Error::argument_conflict(f, c_with, &*usg, self.0.color())) 178 } else if let Some(o) = find_by_name!(self.0, name, opts, iter) { 179 debugln!("build_err!: It was an option..."); 180 Err(Error::argument_conflict(o, c_with, &*usg, self.0.color())) 181 } else { 182 match find_by_name!(self.0, name, positionals, values) { 183 Some(p) => { 184 debugln!("build_err!: It was a positional..."); 185 Err(Error::argument_conflict(p, c_with, &*usg, self.0.color())) 186 } 187 None => panic!(INTERNAL_ERROR_MSG), 188 } 189 } 190 } 191 validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()>192 fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { 193 debugln!("Validator::validate_blacklist;"); 194 let mut conflicts: Vec<&str> = vec![]; 195 for (&name, _) in matcher.iter() { 196 debugln!("Validator::validate_blacklist:iter:{};", name); 197 if let Some(grps) = self.0.groups_for_arg(name) { 198 for grp in &grps { 199 if let Some(g) = self.0.groups.iter().find(|g| &g.name == grp) { 200 if !g.multiple { 201 for arg in &g.args { 202 if arg == &name { 203 continue; 204 } 205 conflicts.push(arg); 206 } 207 } 208 if let Some(ref gc) = g.conflicts { 209 conflicts.extend(&*gc); 210 } 211 } 212 } 213 } 214 if let Some(arg) = find_any_by_name!(self.0, name) { 215 if let Some(bl) = arg.blacklist() { 216 for conf in bl { 217 if matcher.get(conf).is_some() { 218 conflicts.push(conf); 219 } 220 } 221 } 222 } else { 223 debugln!("Validator::validate_blacklist:iter:{}:group;", name); 224 let args = self.0.arg_names_in_group(name); 225 for arg in &args { 226 debugln!( 227 "Validator::validate_blacklist:iter:{}:group:iter:{};", 228 name, 229 arg 230 ); 231 if let Some(bl) = find_any_by_name!(self.0, *arg).unwrap().blacklist() { 232 for conf in bl { 233 if matcher.get(conf).is_some() { 234 conflicts.push(conf); 235 } 236 } 237 } 238 } 239 } 240 } 241 242 for name in &conflicts { 243 debugln!( 244 "Validator::validate_blacklist:iter:{}: Checking blacklisted arg", 245 name 246 ); 247 let mut should_err = false; 248 if self.0.groups.iter().any(|g| &g.name == name) { 249 debugln!( 250 "Validator::validate_blacklist:iter:{}: groups contains it...", 251 name 252 ); 253 for n in self.0.arg_names_in_group(name) { 254 debugln!( 255 "Validator::validate_blacklist:iter:{}:iter:{}: looking in group...", 256 name, 257 n 258 ); 259 if matcher.contains(n) { 260 debugln!( 261 "Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...", 262 name, 263 n 264 ); 265 return self.build_err(n, matcher); 266 } 267 } 268 } else if let Some(ma) = matcher.get(name) { 269 debugln!( 270 "Validator::validate_blacklist:iter:{}: matcher contains it...", 271 name 272 ); 273 should_err = ma.occurs > 0; 274 } 275 if should_err { 276 return self.build_err(*name, matcher); 277 } 278 } 279 Ok(()) 280 } 281 validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>282 fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { 283 debugln!("Validator::validate_matched_args;"); 284 for (name, ma) in matcher.iter() { 285 debugln!( 286 "Validator::validate_matched_args:iter:{}: vals={:#?}", 287 name, 288 ma.vals 289 ); 290 if let Some(opt) = find_by_name!(self.0, *name, opts, iter) { 291 self.validate_arg_num_vals(opt, ma, matcher)?; 292 self.validate_arg_values(opt, ma, matcher)?; 293 self.validate_arg_requires(opt, ma, matcher)?; 294 self.validate_arg_num_occurs(opt, ma, matcher)?; 295 } else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) { 296 self.validate_arg_requires(flag, ma, matcher)?; 297 self.validate_arg_num_occurs(flag, ma, matcher)?; 298 } else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) { 299 self.validate_arg_num_vals(pos, ma, matcher)?; 300 self.validate_arg_num_occurs(pos, ma, matcher)?; 301 self.validate_arg_values(pos, ma, matcher)?; 302 self.validate_arg_requires(pos, ma, matcher)?; 303 } else { 304 let grp = self 305 .0 306 .groups 307 .iter() 308 .find(|g| &g.name == name) 309 .expect(INTERNAL_ERROR_MSG); 310 if let Some(ref g_reqs) = grp.requires { 311 if g_reqs.iter().any(|&n| !matcher.contains(n)) { 312 return self.missing_required_error(matcher, None); 313 } 314 } 315 } 316 } 317 Ok(()) 318 } 319 validate_arg_num_occurs<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,320 fn validate_arg_num_occurs<A>( 321 &self, 322 a: &A, 323 ma: &MatchedArg, 324 matcher: &ArgMatcher, 325 ) -> ClapResult<()> 326 where 327 A: AnyArg<'a, 'b> + Display, 328 { 329 debugln!("Validator::validate_arg_num_occurs: a={};", a.name()); 330 if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) { 331 // Not the first time, and we don't allow multiples 332 return Err(Error::unexpected_multiple_usage( 333 a, 334 &*usage::create_error_usage(self.0, matcher, None), 335 self.0.color(), 336 )); 337 } 338 Ok(()) 339 } 340 validate_arg_num_vals<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,341 fn validate_arg_num_vals<A>( 342 &self, 343 a: &A, 344 ma: &MatchedArg, 345 matcher: &ArgMatcher, 346 ) -> ClapResult<()> 347 where 348 A: AnyArg<'a, 'b> + Display, 349 { 350 debugln!("Validator::validate_arg_num_vals:{}", a.name()); 351 if let Some(num) = a.num_vals() { 352 debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num); 353 let should_err = if a.is_set(ArgSettings::Multiple) { 354 ((ma.vals.len() as u64) % num) != 0 355 } else { 356 num != (ma.vals.len() as u64) 357 }; 358 if should_err { 359 debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); 360 return Err(Error::wrong_number_of_values( 361 a, 362 num, 363 if a.is_set(ArgSettings::Multiple) { 364 (ma.vals.len() % num as usize) 365 } else { 366 ma.vals.len() 367 }, 368 if ma.vals.len() == 1 369 || (a.is_set(ArgSettings::Multiple) && (ma.vals.len() % num as usize) == 1) 370 { 371 "as" 372 } else { 373 "ere" 374 }, 375 &*usage::create_error_usage(self.0, matcher, None), 376 self.0.color(), 377 )); 378 } 379 } 380 if let Some(num) = a.max_vals() { 381 debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num); 382 if (ma.vals.len() as u64) > num { 383 debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues"); 384 return Err(Error::too_many_values( 385 ma.vals 386 .iter() 387 .last() 388 .expect(INTERNAL_ERROR_MSG) 389 .to_str() 390 .expect(INVALID_UTF8), 391 a, 392 &*usage::create_error_usage(self.0, matcher, None), 393 self.0.color(), 394 )); 395 } 396 } 397 let min_vals_zero = if let Some(num) = a.min_vals() { 398 debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num); 399 if (ma.vals.len() as u64) < num && num != 0 { 400 debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues"); 401 return Err(Error::too_few_values( 402 a, 403 num, 404 ma.vals.len(), 405 &*usage::create_error_usage(self.0, matcher, None), 406 self.0.color(), 407 )); 408 } 409 num == 0 410 } else { 411 false 412 }; 413 // Issue 665 (https://github.com/clap-rs/clap/issues/665) 414 // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) 415 if a.takes_value() && !min_vals_zero && ma.vals.is_empty() { 416 return Err(Error::empty_value( 417 a, 418 &*usage::create_error_usage(self.0, matcher, None), 419 self.0.color(), 420 )); 421 } 422 Ok(()) 423 } 424 validate_arg_requires<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,425 fn validate_arg_requires<A>( 426 &self, 427 a: &A, 428 ma: &MatchedArg, 429 matcher: &ArgMatcher, 430 ) -> ClapResult<()> 431 where 432 A: AnyArg<'a, 'b> + Display, 433 { 434 debugln!("Validator::validate_arg_requires:{};", a.name()); 435 if let Some(a_reqs) = a.requires() { 436 for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) { 437 let missing_req = 438 |v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name); 439 if ma.vals.iter().any(missing_req) { 440 return self.missing_required_error(matcher, None); 441 } 442 } 443 for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) { 444 if !matcher.contains(name) { 445 return self.missing_required_error(matcher, Some(name)); 446 } 447 } 448 } 449 Ok(()) 450 } 451 validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()>452 fn validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()> { 453 debugln!( 454 "Validator::validate_required: required={:?};", 455 self.0.required 456 ); 457 458 let mut should_err = false; 459 let mut to_rem = Vec::new(); 460 for name in &self.0.required { 461 debugln!("Validator::validate_required:iter:{}:", name); 462 if matcher.contains(name) { 463 continue; 464 } 465 if to_rem.contains(name) { 466 continue; 467 } else if let Some(a) = find_any_by_name!(self.0, *name) { 468 if self.is_missing_required_ok(a, matcher) { 469 to_rem.push(a.name()); 470 if let Some(reqs) = a.requires() { 471 for r in reqs 472 .iter() 473 .filter(|&&(val, _)| val.is_none()) 474 .map(|&(_, name)| name) 475 { 476 to_rem.push(r); 477 } 478 } 479 continue; 480 } 481 } 482 should_err = true; 483 break; 484 } 485 if should_err { 486 for r in &to_rem { 487 'inner: for i in (0..self.0.required.len()).rev() { 488 if &self.0.required[i] == r { 489 self.0.required.swap_remove(i); 490 break 'inner; 491 } 492 } 493 } 494 return self.missing_required_error(matcher, None); 495 } 496 497 // Validate the conditionally required args 498 for &(a, v, r) in &self.0.r_ifs { 499 if let Some(ma) = matcher.get(a) { 500 if matcher.get(r).is_none() && ma.vals.iter().any(|val| val == v) { 501 return self.missing_required_error(matcher, Some(r)); 502 } 503 } 504 } 505 Ok(()) 506 } 507 validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool>508 fn validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> { 509 debugln!("Validator::validate_arg_conflicts: a={:?};", a.name()); 510 a.blacklist().map(|bl| { 511 bl.iter().any(|conf| { 512 matcher.contains(conf) 513 || self 514 .0 515 .groups 516 .iter() 517 .find(|g| &g.name == conf) 518 .map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg))) 519 }) 520 }) 521 } 522 validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool>523 fn validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> { 524 debugln!("Validator::validate_required_unless: a={:?};", a.name()); 525 macro_rules! check { 526 ($how:ident, $_self:expr, $a:ident, $m:ident) => {{ 527 $a.required_unless().map(|ru| { 528 ru.iter().$how(|n| { 529 $m.contains(n) || { 530 if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) { 531 grp.args.iter().any(|arg| $m.contains(arg)) 532 } else { 533 false 534 } 535 } 536 }) 537 }) 538 }}; 539 } 540 if a.is_set(ArgSettings::RequiredUnlessAll) { 541 check!(all, self.0, a, matcher) 542 } else { 543 check!(any, self.0, a, matcher) 544 } 545 } 546 missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()>547 fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> { 548 debugln!("Validator::missing_required_error: extra={:?}", extra); 549 let c = Colorizer::new(ColorizerOption { 550 use_stderr: true, 551 when: self.0.color(), 552 }); 553 let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>(); 554 if let Some(r) = extra { 555 reqs.push(r); 556 } 557 reqs.retain(|n| !matcher.contains(n)); 558 reqs.dedup(); 559 debugln!("Validator::missing_required_error: reqs={:#?}", reqs); 560 let req_args = 561 usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true) 562 .iter() 563 .fold(String::new(), |acc, s| { 564 acc + &format!("\n {}", c.error(s))[..] 565 }); 566 debugln!( 567 "Validator::missing_required_error: req_args={:#?}", 568 req_args 569 ); 570 Err(Error::missing_required_argument( 571 &*req_args, 572 &*usage::create_error_usage(self.0, matcher, extra), 573 self.0.color(), 574 )) 575 } 576 577 #[inline] is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool578 fn is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool { 579 debugln!("Validator::is_missing_required_ok: a={}", a.name()); 580 self.validate_arg_conflicts(a, matcher).unwrap_or(false) 581 || self.validate_required_unless(a, matcher).unwrap_or(false) 582 } 583 } 584