diff options
Diffstat (limited to 'clap/src/app/validator.rs')
-rw-r--r-- | clap/src/app/validator.rs | 573 |
1 files changed, 0 insertions, 573 deletions
diff --git a/clap/src/app/validator.rs b/clap/src/app/validator.rs deleted file mode 100644 index 181b831..0000000 --- a/clap/src/app/validator.rs +++ /dev/null @@ -1,573 +0,0 @@ -// std -use std::fmt::Display; -#[allow(deprecated, unused_imports)] -use std::ascii::AsciiExt; - -// Internal -use INTERNAL_ERROR_MSG; -use INVALID_UTF8; -use args::{AnyArg, ArgMatcher, MatchedArg}; -use args::settings::ArgSettings; -use errors::{Error, ErrorKind}; -use errors::Result as ClapResult; -use app::settings::AppSettings as AS; -use app::parser::{ParseResult, Parser}; -use fmt::{Colorizer, ColorizerOption}; -use app::usage; - -pub struct Validator<'a, 'b, 'z>(&'z mut Parser<'a, 'b>) -where - 'a: 'b, - 'b: 'z; - -impl<'a, 'b, 'z> Validator<'a, 'b, 'z> { - pub fn new(p: &'z mut Parser<'a, 'b>) -> Self { Validator(p) } - - pub fn validate( - &mut self, - needs_val_of: ParseResult<'a>, - subcmd_name: Option<String>, - matcher: &mut ArgMatcher<'a>, - ) -> ClapResult<()> { - debugln!("Validator::validate;"); - let mut reqs_validated = false; - self.0.add_env(matcher)?; - self.0.add_defaults(matcher)?; - if let ParseResult::Opt(a) = needs_val_of { - debugln!("Validator::validate: needs_val_of={:?}", a); - let o = { - self.0 - .opts - .iter() - .find(|o| o.b.name == a) - .expect(INTERNAL_ERROR_MSG) - .clone() - }; - self.validate_required(matcher)?; - reqs_validated = true; - let should_err = if let Some(v) = matcher.0.args.get(&*o.b.name) { - v.vals.is_empty() && !(o.v.min_vals.is_some() && o.v.min_vals.unwrap() == 0) - } else { - true - }; - if should_err { - return Err(Error::empty_value( - &o, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - } - - if matcher.is_empty() && matcher.subcommand_name().is_none() - && self.0.is_set(AS::ArgRequiredElseHelp) - { - let mut out = vec![]; - self.0.write_help_err(&mut out)?; - return Err(Error { - message: String::from_utf8_lossy(&*out).into_owned(), - kind: ErrorKind::MissingArgumentOrSubcommand, - info: None, - }); - } - self.validate_blacklist(matcher)?; - if !(self.0.is_set(AS::SubcommandsNegateReqs) && subcmd_name.is_some()) && !reqs_validated { - self.validate_required(matcher)?; - } - self.validate_matched_args(matcher)?; - matcher.usage(usage::create_usage_with_title(self.0, &[])); - - Ok(()) - } - - fn validate_arg_values<A>( - &self, - arg: &A, - ma: &MatchedArg, - matcher: &ArgMatcher<'a>, - ) -> ClapResult<()> - where - A: AnyArg<'a, 'b> + Display, - { - debugln!("Validator::validate_arg_values: arg={:?}", arg.name()); - for val in &ma.vals { - if self.0.is_set(AS::StrictUtf8) && val.to_str().is_none() { - debugln!( - "Validator::validate_arg_values: invalid UTF-8 found in val {:?}", - val - ); - return Err(Error::invalid_utf8( - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - if let Some(p_vals) = arg.possible_vals() { - debugln!("Validator::validate_arg_values: possible_vals={:?}", p_vals); - let val_str = val.to_string_lossy(); - let ok = if arg.is_set(ArgSettings::CaseInsensitive) { - p_vals.iter().any(|pv| pv.eq_ignore_ascii_case(&*val_str)) - } else { - p_vals.contains(&&*val_str) - }; - if !ok { - return Err(Error::invalid_value( - val_str, - p_vals, - arg, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - } - if !arg.is_set(ArgSettings::EmptyValues) && val.is_empty() - && matcher.contains(&*arg.name()) - { - debugln!("Validator::validate_arg_values: illegal empty val found"); - return Err(Error::empty_value( - arg, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - if let Some(vtor) = arg.validator() { - debug!("Validator::validate_arg_values: checking validator..."); - if let Err(e) = vtor(val.to_string_lossy().into_owned()) { - sdebugln!("error"); - return Err(Error::value_validation(Some(arg), e, self.0.color())); - } else { - sdebugln!("good"); - } - } - if let Some(vtor) = arg.validator_os() { - debug!("Validator::validate_arg_values: checking validator_os..."); - if let Err(e) = vtor(val) { - sdebugln!("error"); - return Err(Error::value_validation( - Some(arg), - (*e).to_string_lossy().to_string(), - self.0.color(), - )); - } else { - sdebugln!("good"); - } - } - } - Ok(()) - } - - fn build_err(&self, name: &str, matcher: &ArgMatcher) -> ClapResult<()> { - debugln!("build_err!: name={}", name); - let mut c_with = find_from!(self.0, &name, blacklist, matcher); - c_with = c_with.or( - self.0.find_any_arg(name).map_or(None, |aa| aa.blacklist()) - .map_or(None, - |bl| bl.iter().find(|arg| matcher.contains(arg))) - .map_or(None, |an| self.0.find_any_arg(an)) - .map_or(None, |aa| Some(format!("{}", aa))) - ); - debugln!("build_err!: '{:?}' conflicts with '{}'", c_with, &name); -// matcher.remove(&name); - let usg = usage::create_error_usage(self.0, matcher, None); - if let Some(f) = find_by_name!(self.0, name, flags, iter) { - debugln!("build_err!: It was a flag..."); - Err(Error::argument_conflict(f, c_with, &*usg, self.0.color())) - } else if let Some(o) = find_by_name!(self.0, name, opts, iter) { - debugln!("build_err!: It was an option..."); - Err(Error::argument_conflict(o, c_with, &*usg, self.0.color())) - } else { - match find_by_name!(self.0, name, positionals, values) { - Some(p) => { - debugln!("build_err!: It was a positional..."); - Err(Error::argument_conflict(p, c_with, &*usg, self.0.color())) - }, - None => panic!(INTERNAL_ERROR_MSG) - } - } - } - - fn validate_blacklist(&self, matcher: &mut ArgMatcher) -> ClapResult<()> { - debugln!("Validator::validate_blacklist;"); - let mut conflicts: Vec<&str> = vec![]; - for (&name, _) in matcher.iter() { - debugln!("Validator::validate_blacklist:iter:{};", name); - if let Some(grps) = self.0.groups_for_arg(name) { - for grp in &grps { - if let Some(g) = self.0.groups.iter().find(|g| &g.name == grp) { - if !g.multiple { - for arg in &g.args { - if arg == &name { - continue; - } - conflicts.push(arg); - } - } - if let Some(ref gc) = g.conflicts { - conflicts.extend(&*gc); - } - } - } - } - if let Some(arg) = find_any_by_name!(self.0, name) { - if let Some(bl) = arg.blacklist() { - for conf in bl { - if matcher.get(conf).is_some() { - conflicts.push(conf); - } - } - } - } else { - debugln!("Validator::validate_blacklist:iter:{}:group;", name); - let args = self.0.arg_names_in_group(name); - for arg in &args { - debugln!("Validator::validate_blacklist:iter:{}:group:iter:{};", name, arg); - if let Some(bl) = find_any_by_name!(self.0, *arg).unwrap().blacklist() { - for conf in bl { - if matcher.get(conf).is_some() { - conflicts.push(conf); - } - } - } - } - } - } - - for name in &conflicts { - debugln!( - "Validator::validate_blacklist:iter:{}: Checking blacklisted arg", - name - ); - let mut should_err = false; - if self.0.groups.iter().any(|g| &g.name == name) { - debugln!( - "Validator::validate_blacklist:iter:{}: groups contains it...", - name - ); - for n in self.0.arg_names_in_group(name) { - debugln!( - "Validator::validate_blacklist:iter:{}:iter:{}: looking in group...", - name, - n - ); - if matcher.contains(n) { - debugln!( - "Validator::validate_blacklist:iter:{}:iter:{}: matcher contains it...", - name, - n - ); - return self.build_err(n, matcher); - } - } - } else if let Some(ma) = matcher.get(name) { - debugln!( - "Validator::validate_blacklist:iter:{}: matcher contains it...", - name - ); - should_err = ma.occurs > 0; - } - if should_err { - return self.build_err(*name, matcher); - } - } - Ok(()) - } - - fn validate_matched_args(&self, matcher: &mut ArgMatcher<'a>) -> ClapResult<()> { - debugln!("Validator::validate_matched_args;"); - for (name, ma) in matcher.iter() { - debugln!( - "Validator::validate_matched_args:iter:{}: vals={:#?}", - name, - ma.vals - ); - if let Some(opt) = find_by_name!(self.0, *name, opts, iter) { - self.validate_arg_num_vals(opt, ma, matcher)?; - self.validate_arg_values(opt, ma, matcher)?; - self.validate_arg_requires(opt, ma, matcher)?; - self.validate_arg_num_occurs(opt, ma, matcher)?; - } else if let Some(flag) = find_by_name!(self.0, *name, flags, iter) { - self.validate_arg_requires(flag, ma, matcher)?; - self.validate_arg_num_occurs(flag, ma, matcher)?; - } else if let Some(pos) = find_by_name!(self.0, *name, positionals, values) { - self.validate_arg_num_vals(pos, ma, matcher)?; - self.validate_arg_num_occurs(pos, ma, matcher)?; - self.validate_arg_values(pos, ma, matcher)?; - self.validate_arg_requires(pos, ma, matcher)?; - } else { - let grp = self.0 - .groups - .iter() - .find(|g| &g.name == name) - .expect(INTERNAL_ERROR_MSG); - if let Some(ref g_reqs) = grp.requires { - if g_reqs.iter().any(|&n| !matcher.contains(n)) { - return self.missing_required_error(matcher, None); - } - } - } - } - Ok(()) - } - - fn validate_arg_num_occurs<A>( - &self, - a: &A, - ma: &MatchedArg, - matcher: &ArgMatcher, - ) -> ClapResult<()> - where - A: AnyArg<'a, 'b> + Display, - { - debugln!("Validator::validate_arg_num_occurs: a={};", a.name()); - if ma.occurs > 1 && !a.is_set(ArgSettings::Multiple) { - // Not the first time, and we don't allow multiples - return Err(Error::unexpected_multiple_usage( - a, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - Ok(()) - } - - fn validate_arg_num_vals<A>( - &self, - a: &A, - ma: &MatchedArg, - matcher: &ArgMatcher, - ) -> ClapResult<()> - where - A: AnyArg<'a, 'b> + Display, - { - debugln!("Validator::validate_arg_num_vals:{}", a.name()); - if let Some(num) = a.num_vals() { - debugln!("Validator::validate_arg_num_vals: num_vals set...{}", num); - let should_err = if a.is_set(ArgSettings::Multiple) { - ((ma.vals.len() as u64) % num) != 0 - } else { - num != (ma.vals.len() as u64) - }; - if should_err { - debugln!("Validator::validate_arg_num_vals: Sending error WrongNumberOfValues"); - return Err(Error::wrong_number_of_values( - a, - num, - if a.is_set(ArgSettings::Multiple) { - (ma.vals.len() % num as usize) - } else { - ma.vals.len() - }, - if ma.vals.len() == 1 - || (a.is_set(ArgSettings::Multiple) && (ma.vals.len() % num as usize) == 1) - { - "as" - } else { - "ere" - }, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - } - if let Some(num) = a.max_vals() { - debugln!("Validator::validate_arg_num_vals: max_vals set...{}", num); - if (ma.vals.len() as u64) > num { - debugln!("Validator::validate_arg_num_vals: Sending error TooManyValues"); - return Err(Error::too_many_values( - ma.vals - .iter() - .last() - .expect(INTERNAL_ERROR_MSG) - .to_str() - .expect(INVALID_UTF8), - a, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - } - let min_vals_zero = if let Some(num) = a.min_vals() { - debugln!("Validator::validate_arg_num_vals: min_vals set: {}", num); - if (ma.vals.len() as u64) < num && num != 0 { - debugln!("Validator::validate_arg_num_vals: Sending error TooFewValues"); - return Err(Error::too_few_values( - a, - num, - ma.vals.len(), - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - num == 0 - } else { - false - }; - // Issue 665 (https://github.com/clap-rs/clap/issues/665) - // Issue 1105 (https://github.com/clap-rs/clap/issues/1105) - if a.takes_value() && !min_vals_zero && ma.vals.is_empty() { - return Err(Error::empty_value( - a, - &*usage::create_error_usage(self.0, matcher, None), - self.0.color(), - )); - } - Ok(()) - } - - fn validate_arg_requires<A>( - &self, - a: &A, - ma: &MatchedArg, - matcher: &ArgMatcher, - ) -> ClapResult<()> - where - A: AnyArg<'a, 'b> + Display, - { - debugln!("Validator::validate_arg_requires:{};", a.name()); - if let Some(a_reqs) = a.requires() { - for &(val, name) in a_reqs.iter().filter(|&&(val, _)| val.is_some()) { - let missing_req = - |v| v == val.expect(INTERNAL_ERROR_MSG) && !matcher.contains(name); - if ma.vals.iter().any(missing_req) { - return self.missing_required_error(matcher, None); - } - } - for &(_, name) in a_reqs.iter().filter(|&&(val, _)| val.is_none()) { - if !matcher.contains(name) { - return self.missing_required_error(matcher, Some(name)); - } - } - } - Ok(()) - } - - fn validate_required(&mut self, matcher: &ArgMatcher) -> ClapResult<()> { - debugln!( - "Validator::validate_required: required={:?};", - self.0.required - ); - - let mut should_err = false; - let mut to_rem = Vec::new(); - for name in &self.0.required { - debugln!("Validator::validate_required:iter:{}:", name); - if matcher.contains(name) { - continue; - } - if to_rem.contains(name) { - continue; - } else if let Some(a) = find_any_by_name!(self.0, *name) { - if self.is_missing_required_ok(a, matcher) { - to_rem.push(a.name()); - if let Some(reqs) = a.requires() { - for r in reqs - .iter() - .filter(|&&(val, _)| val.is_none()) - .map(|&(_, name)| name) - { - to_rem.push(r); - } - } - continue; - } - } - should_err = true; - break; - } - if should_err { - for r in &to_rem { - 'inner: for i in (0 .. self.0.required.len()).rev() { - if &self.0.required[i] == r { - self.0.required.swap_remove(i); - break 'inner; - } - } - } - return self.missing_required_error(matcher, None); - } - - // Validate the conditionally required args - for &(a, v, r) in &self.0.r_ifs { - if let Some(ma) = matcher.get(a) { - if matcher.get(r).is_none() && ma.vals.iter().any(|val| val == v) { - return self.missing_required_error(matcher, Some(r)); - } - } - } - Ok(()) - } - - fn validate_arg_conflicts(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> { - debugln!("Validator::validate_arg_conflicts: a={:?};", a.name()); - a.blacklist().map(|bl| { - bl.iter().any(|conf| { - matcher.contains(conf) - || self.0 - .groups - .iter() - .find(|g| &g.name == conf) - .map_or(false, |g| g.args.iter().any(|arg| matcher.contains(arg))) - }) - }) - } - - fn validate_required_unless(&self, a: &AnyArg, matcher: &ArgMatcher) -> Option<bool> { - debugln!("Validator::validate_required_unless: a={:?};", a.name()); - macro_rules! check { - ($how:ident, $_self:expr, $a:ident, $m:ident) => {{ - $a.required_unless().map(|ru| { - ru.iter().$how(|n| { - $m.contains(n) || { - if let Some(grp) = $_self.groups.iter().find(|g| &g.name == n) { - grp.args.iter().any(|arg| $m.contains(arg)) - } else { - false - } - } - }) - }) - }}; - } - if a.is_set(ArgSettings::RequiredUnlessAll) { - check!(all, self.0, a, matcher) - } else { - check!(any, self.0, a, matcher) - } - } - - fn missing_required_error(&self, matcher: &ArgMatcher, extra: Option<&str>) -> ClapResult<()> { - debugln!("Validator::missing_required_error: extra={:?}", extra); - let c = Colorizer::new(ColorizerOption { - use_stderr: true, - when: self.0.color(), - }); - let mut reqs = self.0.required.iter().map(|&r| &*r).collect::<Vec<_>>(); - if let Some(r) = extra { - reqs.push(r); - } - reqs.retain(|n| !matcher.contains(n)); - reqs.dedup(); - debugln!("Validator::missing_required_error: reqs={:#?}", reqs); - let req_args = - usage::get_required_usage_from(self.0, &reqs[..], Some(matcher), extra, true) - .iter() - .fold(String::new(), |acc, s| { - acc + &format!("\n {}", c.error(s))[..] - }); - debugln!( - "Validator::missing_required_error: req_args={:#?}", - req_args - ); - Err(Error::missing_required_argument( - &*req_args, - &*usage::create_error_usage(self.0, matcher, extra), - self.0.color(), - )) - } - - #[inline] - fn is_missing_required_ok(&self, a: &AnyArg, matcher: &ArgMatcher) -> bool { - debugln!("Validator::is_missing_required_ok: a={}", a.name()); - self.validate_arg_conflicts(a, matcher).unwrap_or(false) - || self.validate_required_unless(a, matcher).unwrap_or(false) - } -} |