1 // std 2 use std::fmt::Display; 3 #[allow(deprecated, unused_imports)] 4 use std::ascii::AsciiExt; 5 6 // Internal 7 use INTERNAL_ERROR_MSG; 8 use INVALID_UTF8; 9 use args::{AnyArg, ArgMatcher, MatchedArg}; 10 use args::settings::ArgSettings; 11 use errors::{Error, ErrorKind}; 12 use errors::Result as ClapResult; 13 use app::settings::AppSettings as AS; 14 use app::parser::{ParseResult, Parser}; 15 use fmt::{Colorizer, ColorizerOption}; 16 use app::usage; 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 { Validator(p) } 25 validate( &mut self, needs_val_of: ParseResult<'a>, subcmd_name: Option<String>, matcher: &mut ArgMatcher<'a>, ) -> ClapResult<()>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 validate_arg_values<A>( &self, arg: &A, ma: &MatchedArg, matcher: &ArgMatcher<'a>, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,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 build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()>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); 169 // matcher.remove(&name); 170 let 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 validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()>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 validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()>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 validate_arg_num_occurs<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,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 // Not the first time, and we don't allow multiples 323 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 validate_arg_num_vals<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,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 // Issue 665 (https://github.com/kbknapp/clap-rs/issues/665) 405 // Issue 1105 (https://github.com/kbknapp/clap-rs/issues/1105) 406 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 validate_arg_requires<A>( &self, a: &A, ma: &MatchedArg, matcher: &ArgMatcher, ) -> ClapResult<()> where A: AnyArg<'a, 'b> + Display,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 validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()>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 // Validate the conditionally required args 489 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 validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool>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 validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool>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 missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()>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] is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool568 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 } 574