From a990de90fe41456a23e58bd087d2f107d321f3a1 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Fri, 19 Jul 2024 16:37:58 +0400 Subject: Deleted vendor folder --- vendor/clap_builder/src/builder/value_parser.rs | 2712 ----------------------- 1 file changed, 2712 deletions(-) delete mode 100644 vendor/clap_builder/src/builder/value_parser.rs (limited to 'vendor/clap_builder/src/builder/value_parser.rs') diff --git a/vendor/clap_builder/src/builder/value_parser.rs b/vendor/clap_builder/src/builder/value_parser.rs deleted file mode 100644 index 1f0ef92..0000000 --- a/vendor/clap_builder/src/builder/value_parser.rs +++ /dev/null @@ -1,2712 +0,0 @@ -use std::convert::TryInto; -use std::ops::RangeBounds; - -use crate::builder::Str; -use crate::builder::StyledStr; -use crate::parser::ValueSource; -use crate::util::AnyValue; -use crate::util::AnyValueId; - -/// Parse/validate argument values -/// -/// Specified with [`Arg::value_parser`][crate::Arg::value_parser]. -/// -/// `ValueParser` defines how to convert a raw argument value into a validated and typed value for -/// use within an application. -/// -/// See -/// - [`value_parser!`][crate::value_parser] for automatically selecting an implementation for a given type -/// - [`ValueParser::new`] for additional [`TypedValueParser`] that can be used -/// -/// # Example -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("color") -/// .long("color") -/// .value_parser(["always", "auto", "never"]) -/// .default_value("auto") -/// ) -/// .arg( -/// clap::Arg::new("hostname") -/// .long("hostname") -/// .value_parser(clap::builder::NonEmptyStringValueParser::new()) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ) -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u16).range(3000..)) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut( -/// ["cmd", "--hostname", "rust-lang.org", "--port", "3001"] -/// ).unwrap(); -/// -/// let color: &String = m.get_one("color") -/// .expect("default"); -/// assert_eq!(color, "auto"); -/// -/// let hostname: &String = m.get_one("hostname") -/// .expect("required"); -/// assert_eq!(hostname, "rust-lang.org"); -/// -/// let port: u16 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -pub struct ValueParser(ValueParserInner); - -enum ValueParserInner { - // Common enough to optimize and for possible values - Bool, - // Common enough to optimize - String, - // Common enough to optimize - OsString, - // Common enough to optimize - PathBuf, - Other(Box), -} - -impl ValueParser { - /// Custom parser for argument values - /// - /// Pre-existing [`TypedValueParser`] implementations include: - /// - `Fn(&str) -> Result` - /// - [`EnumValueParser`] and [`PossibleValuesParser`] for static enumerated values - /// - [`BoolishValueParser`] and [`FalseyValueParser`] for alternative `bool` implementations - /// - [`RangedI64ValueParser`] and [`RangedU64ValueParser`] - /// - [`NonEmptyStringValueParser`] - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// type EnvVar = (String, Option); - /// fn parse_env_var(env: &str) -> Result { - /// if let Some((var, value)) = env.split_once('=') { - /// Ok((var.to_owned(), Some(value.to_owned()))) - /// } else { - /// Ok((env.to_owned(), None)) - /// } - /// } - /// - /// let mut cmd = clap::Command::new("raw") - /// .arg( - /// clap::Arg::new("env") - /// .value_parser(clap::builder::ValueParser::new(parse_env_var)) - /// .required(true) - /// ); - /// - /// let m = cmd.try_get_matches_from_mut(["cmd", "key=value"]).unwrap(); - /// let port: &EnvVar = m.get_one("env") - /// .expect("required"); - /// assert_eq!(*port, ("key".into(), Some("value".into()))); - /// ``` - pub fn new

(other: P) -> Self - where - P: TypedValueParser, - { - Self(ValueParserInner::Other(Box::new(other))) - } - - /// [`bool`] parser for argument values - /// - /// See also: - /// - [`BoolishValueParser`] for different human readable bool representations - /// - [`FalseyValueParser`] for assuming non-false is true - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// let mut cmd = clap::Command::new("raw") - /// .arg( - /// clap::Arg::new("download") - /// .value_parser(clap::value_parser!(bool)) - /// .required(true) - /// ); - /// - /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); - /// let port: bool = *m.get_one("download") - /// .expect("required"); - /// assert_eq!(port, true); - /// - /// assert!(cmd.try_get_matches_from_mut(["cmd", "forever"]).is_err()); - /// ``` - pub const fn bool() -> Self { - Self(ValueParserInner::Bool) - } - - /// [`String`] parser for argument values - /// - /// See also: - /// - [`NonEmptyStringValueParser`] - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// let mut cmd = clap::Command::new("raw") - /// .arg( - /// clap::Arg::new("port") - /// .value_parser(clap::value_parser!(String)) - /// .required(true) - /// ); - /// - /// let m = cmd.try_get_matches_from_mut(["cmd", "80"]).unwrap(); - /// let port: &String = m.get_one("port") - /// .expect("required"); - /// assert_eq!(port, "80"); - /// ``` - pub const fn string() -> Self { - Self(ValueParserInner::String) - } - - /// [`OsString`][std::ffi::OsString] parser for argument values - /// - /// # Example - /// - /// ```rust - /// # #[cfg(unix)] { - /// # use clap_builder as clap; - /// # use clap::{Command, Arg, builder::ValueParser}; - /// use std::ffi::OsString; - /// use std::os::unix::ffi::{OsStrExt,OsStringExt}; - /// let r = Command::new("myprog") - /// .arg( - /// Arg::new("arg") - /// .required(true) - /// .value_parser(ValueParser::os_string()) - /// ) - /// .try_get_matches_from(vec![ - /// OsString::from("myprog"), - /// OsString::from_vec(vec![0xe9]) - /// ]); - /// - /// assert!(r.is_ok()); - /// let m = r.unwrap(); - /// let arg: &OsString = m.get_one("arg") - /// .expect("required"); - /// assert_eq!(arg.as_bytes(), &[0xe9]); - /// # } - /// ``` - pub const fn os_string() -> Self { - Self(ValueParserInner::OsString) - } - - /// [`PathBuf`][std::path::PathBuf] parser for argument values - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// # use std::path::PathBuf; - /// # use std::path::Path; - /// let mut cmd = clap::Command::new("raw") - /// .arg( - /// clap::Arg::new("output") - /// .value_parser(clap::value_parser!(PathBuf)) - /// .required(true) - /// ); - /// - /// let m = cmd.try_get_matches_from_mut(["cmd", "hello.txt"]).unwrap(); - /// let port: &PathBuf = m.get_one("output") - /// .expect("required"); - /// assert_eq!(port, Path::new("hello.txt")); - /// - /// assert!(cmd.try_get_matches_from_mut(["cmd", ""]).is_err()); - /// ``` - pub const fn path_buf() -> Self { - Self(ValueParserInner::PathBuf) - } -} - -impl ValueParser { - /// Parse into a `AnyValue` - /// - /// When `arg` is `None`, an external subcommand value is being parsed. - pub(crate) fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - source: ValueSource, - ) -> Result { - self.any_value_parser().parse_ref_(cmd, arg, value, source) - } - - /// Describes the content of `AnyValue` - pub fn type_id(&self) -> AnyValueId { - self.any_value_parser().type_id() - } - - /// Reflect on enumerated value properties - /// - /// Error checking should not be done with this; it is mostly targeted at user-facing - /// applications like errors and completion. - pub fn possible_values( - &self, - ) -> Option + '_>> { - self.any_value_parser().possible_values() - } - - fn any_value_parser(&self) -> &dyn AnyValueParser { - match &self.0 { - ValueParserInner::Bool => &BoolValueParser {}, - ValueParserInner::String => &StringValueParser {}, - ValueParserInner::OsString => &OsStringValueParser {}, - ValueParserInner::PathBuf => &PathBufValueParser {}, - ValueParserInner::Other(o) => o.as_ref(), - } - } -} - -/// Convert a [`TypedValueParser`] to [`ValueParser`] -/// -/// # Example -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("hostname") -/// .long("hostname") -/// .value_parser(clap::builder::NonEmptyStringValueParser::new()) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut( -/// ["cmd", "--hostname", "rust-lang.org"] -/// ).unwrap(); -/// -/// let hostname: &String = m.get_one("hostname") -/// .expect("required"); -/// assert_eq!(hostname, "rust-lang.org"); -/// ``` -impl

From

for ValueParser -where - P: TypedValueParser + Send + Sync + 'static, -{ - fn from(p: P) -> Self { - Self::new(p) - } -} - -impl From<_AnonymousValueParser> for ValueParser { - fn from(p: _AnonymousValueParser) -> Self { - p.0 - } -} - -/// Create an `i64` [`ValueParser`] from a `N..M` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..4000) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -impl From> for ValueParser { - fn from(value: std::ops::Range) -> Self { - let inner = RangedI64ValueParser::::new().range(value.start..value.end); - Self::from(inner) - } -} - -/// Create an `i64` [`ValueParser`] from a `N..=M` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..=4000) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -impl From> for ValueParser { - fn from(value: std::ops::RangeInclusive) -> Self { - let inner = RangedI64ValueParser::::new().range(value.start()..=value.end()); - Self::from(inner) - } -} - -/// Create an `i64` [`ValueParser`] from a `N..` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -impl From> for ValueParser { - fn from(value: std::ops::RangeFrom) -> Self { - let inner = RangedI64ValueParser::::new().range(value.start..); - Self::from(inner) - } -} - -/// Create an `i64` [`ValueParser`] from a `..M` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..3000) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 80); -/// ``` -impl From> for ValueParser { - fn from(value: std::ops::RangeTo) -> Self { - let inner = RangedI64ValueParser::::new().range(..value.end); - Self::from(inner) - } -} - -/// Create an `i64` [`ValueParser`] from a `..=M` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..=3000) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 80); -/// ``` -impl From> for ValueParser { - fn from(value: std::ops::RangeToInclusive) -> Self { - let inner = RangedI64ValueParser::::new().range(..=value.end); - Self::from(inner) - } -} - -/// Create an `i64` [`ValueParser`] from a `..` range -/// -/// See [`RangedI64ValueParser`] for more control over the output type. -/// -/// See also [`RangedU64ValueParser`] -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: i64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -impl From for ValueParser { - fn from(value: std::ops::RangeFull) -> Self { - let inner = RangedI64ValueParser::::new().range(value); - Self::from(inner) - } -} - -/// Create a [`ValueParser`] with [`PossibleValuesParser`] -/// -/// See [`PossibleValuesParser`] for more flexibility in creating the -/// [`PossibleValue`][crate::builder::PossibleValue]s. -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("color") -/// .long("color") -/// .value_parser(["always", "auto", "never"]) -/// .default_value("auto") -/// ); -/// -/// let m = cmd.try_get_matches_from_mut( -/// ["cmd", "--color", "never"] -/// ).unwrap(); -/// -/// let color: &String = m.get_one("color") -/// .expect("default"); -/// assert_eq!(color, "never"); -/// ``` -impl From<[P; C]> for ValueParser -where - P: Into, -{ - fn from(values: [P; C]) -> Self { - let inner = PossibleValuesParser::from(values); - Self::from(inner) - } -} - -/// Create a [`ValueParser`] with [`PossibleValuesParser`] -/// -/// See [`PossibleValuesParser`] for more flexibility in creating the -/// [`PossibleValue`][crate::builder::PossibleValue]s. -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// let possible = vec!["always", "auto", "never"]; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("color") -/// .long("color") -/// .value_parser(possible) -/// .default_value("auto") -/// ); -/// -/// let m = cmd.try_get_matches_from_mut( -/// ["cmd", "--color", "never"] -/// ).unwrap(); -/// -/// let color: &String = m.get_one("color") -/// .expect("default"); -/// assert_eq!(color, "never"); -/// ``` -impl

From> for ValueParser -where - P: Into, -{ - fn from(values: Vec

) -> Self { - let inner = PossibleValuesParser::from(values); - Self::from(inner) - } -} - -impl std::fmt::Debug for ValueParser { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - match &self.0 { - ValueParserInner::Bool => f.debug_struct("ValueParser::bool").finish(), - ValueParserInner::String => f.debug_struct("ValueParser::string").finish(), - ValueParserInner::OsString => f.debug_struct("ValueParser::os_string").finish(), - ValueParserInner::PathBuf => f.debug_struct("ValueParser::path_buf").finish(), - ValueParserInner::Other(o) => write!(f, "ValueParser::other({:?})", o.type_id()), - } - } -} - -impl Clone for ValueParser { - fn clone(&self) -> Self { - Self(match &self.0 { - ValueParserInner::Bool => ValueParserInner::Bool, - ValueParserInner::String => ValueParserInner::String, - ValueParserInner::OsString => ValueParserInner::OsString, - ValueParserInner::PathBuf => ValueParserInner::PathBuf, - ValueParserInner::Other(o) => ValueParserInner::Other(o.clone_any()), - }) - } -} - -/// A type-erased wrapper for [`TypedValueParser`]. -trait AnyValueParser: Send + Sync + 'static { - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result; - - fn parse_ref_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - _source: ValueSource, - ) -> Result { - self.parse_ref(cmd, arg, value) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result; - - fn parse_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - _source: ValueSource, - ) -> Result { - self.parse(cmd, arg, value) - } - - /// Describes the content of `AnyValue` - fn type_id(&self) -> AnyValueId; - - fn possible_values( - &self, - ) -> Option + '_>>; - - fn clone_any(&self) -> Box; -} - -impl AnyValueParser for P -where - T: std::any::Any + Clone + Send + Sync + 'static, - P: TypedValueParser, -{ - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(TypedValueParser::parse_ref(self, cmd, arg, value)); - Ok(AnyValue::new(value)) - } - - fn parse_ref_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - source: ValueSource, - ) -> Result { - let value = ok!(TypedValueParser::parse_ref_(self, cmd, arg, value, source)); - Ok(AnyValue::new(value)) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - let value = ok!(TypedValueParser::parse(self, cmd, arg, value)); - Ok(AnyValue::new(value)) - } - - fn parse_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - source: ValueSource, - ) -> Result { - let value = ok!(TypedValueParser::parse_(self, cmd, arg, value, source)); - Ok(AnyValue::new(value)) - } - - fn type_id(&self) -> AnyValueId { - AnyValueId::of::() - } - - fn possible_values( - &self, - ) -> Option + '_>> { - P::possible_values(self) - } - - fn clone_any(&self) -> Box { - Box::new(self.clone()) - } -} - -/// Parse/validate argument values -/// -/// As alternatives to implementing `TypedValueParser`, -/// - Use `Fn(&str) -> Result` which implements `TypedValueParser` -/// - [`TypedValueParser::map`] or [`TypedValueParser::try_map`] to adapt an existing `TypedValueParser` -/// -/// See `ValueParserFactory` to register `TypedValueParser::Value` with -/// [`value_parser!`][crate::value_parser]. -/// -/// # Example -/// -/// ```rust -/// # #[cfg(feature = "error-context")] { -/// # use clap_builder as clap; -/// # use clap::error::ErrorKind; -/// # use clap::error::ContextKind; -/// # use clap::error::ContextValue; -/// #[derive(Clone)] -/// struct Custom(u32); -/// -/// #[derive(Clone)] -/// struct CustomValueParser; -/// -/// impl clap::builder::TypedValueParser for CustomValueParser { -/// type Value = Custom; -/// -/// fn parse_ref( -/// &self, -/// cmd: &clap::Command, -/// arg: Option<&clap::Arg>, -/// value: &std::ffi::OsStr, -/// ) -> Result { -/// let inner = clap::value_parser!(u32); -/// let val = inner.parse_ref(cmd, arg, value)?; -/// -/// const INVALID_VALUE: u32 = 10; -/// if val == INVALID_VALUE { -/// let mut err = clap::Error::new(ErrorKind::ValueValidation) -/// .with_cmd(cmd); -/// if let Some(arg) = arg { -/// err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string())); -/// } -/// err.insert(ContextKind::InvalidValue, ContextValue::String(INVALID_VALUE.to_string())); -/// return Err(err); -/// } -/// -/// Ok(Custom(val)) -/// } -/// } -/// # } -/// ``` -pub trait TypedValueParser: Clone + Send + Sync + 'static { - /// Argument's value type - type Value: Send + Sync + Clone; - - /// Parse the argument value - /// - /// When `arg` is `None`, an external subcommand value is being parsed. - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result; - - /// Parse the argument value - /// - /// When `arg` is `None`, an external subcommand value is being parsed. - fn parse_ref_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - _source: ValueSource, - ) -> Result { - self.parse_ref(cmd, arg, value) - } - - /// Parse the argument value - /// - /// When `arg` is `None`, an external subcommand value is being parsed. - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - self.parse_ref(cmd, arg, &value) - } - - /// Parse the argument value - /// - /// When `arg` is `None`, an external subcommand value is being parsed. - fn parse_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - _source: ValueSource, - ) -> Result { - self.parse(cmd, arg, value) - } - - /// Reflect on enumerated value properties - /// - /// Error checking should not be done with this; it is mostly targeted at user-facing - /// applications like errors and completion. - fn possible_values( - &self, - ) -> Option + '_>> { - None - } - - /// Adapt a `TypedValueParser` from one value to another - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::Command; - /// # use clap::Arg; - /// # use clap::builder::TypedValueParser as _; - /// # use clap::builder::BoolishValueParser; - /// let cmd = Command::new("mycmd") - /// .arg( - /// Arg::new("flag") - /// .long("flag") - /// .action(clap::ArgAction::SetTrue) - /// .value_parser( - /// BoolishValueParser::new() - /// .map(|b| -> usize { - /// if b { 10 } else { 5 } - /// }) - /// ) - /// ); - /// - /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap(); - /// assert!(matches.contains_id("flag")); - /// assert_eq!( - /// matches.get_one::("flag").copied(), - /// Some(10) - /// ); - /// - /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap(); - /// assert!(matches.contains_id("flag")); - /// assert_eq!( - /// matches.get_one::("flag").copied(), - /// Some(5) - /// ); - /// ``` - fn map(self, func: F) -> MapValueParser - where - T: Send + Sync + Clone, - F: Fn(Self::Value) -> T + Clone, - { - MapValueParser::new(self, func) - } - - /// Adapt a `TypedValueParser` from one value to another - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// # use std::ffi::OsString; - /// # use std::ffi::OsStr; - /// # use std::path::PathBuf; - /// # use std::path::Path; - /// # use clap::Command; - /// # use clap::Arg; - /// # use clap::builder::TypedValueParser as _; - /// # use clap::builder::OsStringValueParser; - /// let cmd = Command::new("mycmd") - /// .arg( - /// Arg::new("flag") - /// .long("flag") - /// .value_parser( - /// OsStringValueParser::new() - /// .try_map(verify_ext) - /// ) - /// ); - /// - /// fn verify_ext(os: OsString) -> Result { - /// let path = PathBuf::from(os); - /// if path.extension() != Some(OsStr::new("rs")) { - /// return Err("only Rust files are supported"); - /// } - /// Ok(path) - /// } - /// - /// let error = cmd.clone().try_get_matches_from(["mycmd", "--flag", "foo.txt"]).unwrap_err(); - /// error.print(); - /// - /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "foo.rs"]).unwrap(); - /// assert!(matches.contains_id("flag")); - /// assert_eq!( - /// matches.get_one::("flag").map(|s| s.as_path()), - /// Some(Path::new("foo.rs")) - /// ); - /// ``` - fn try_map(self, func: F) -> TryMapValueParser - where - F: Fn(Self::Value) -> Result + Clone + Send + Sync + 'static, - T: Send + Sync + Clone, - E: Into>, - { - TryMapValueParser::new(self, func) - } -} - -impl TypedValueParser for F -where - F: Fn(&str) -> Result + Clone + Send + Sync + 'static, - E: Into>, - T: Send + Sync + Clone, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - let value = ok!((self)(value).map_err(|e| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation(arg, value.to_owned(), e.into()).with_cmd(cmd) - })); - Ok(value) - } -} - -/// Implementation for [`ValueParser::string`] -/// -/// Useful for composing new [`TypedValueParser`]s -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct StringValueParser {} - -impl StringValueParser { - /// Implementation for [`ValueParser::string`] - pub fn new() -> Self { - Self {} - } -} - -impl TypedValueParser for StringValueParser { - type Value = String; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - TypedValueParser::parse(self, cmd, arg, value.to_owned()) - } - - fn parse( - &self, - cmd: &crate::Command, - _arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - let value = ok!(value.into_string().map_err(|_| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - Ok(value) - } -} - -impl Default for StringValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Implementation for [`ValueParser::os_string`] -/// -/// Useful for composing new [`TypedValueParser`]s -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct OsStringValueParser {} - -impl OsStringValueParser { - /// Implementation for [`ValueParser::os_string`] - pub fn new() -> Self { - Self {} - } -} - -impl TypedValueParser for OsStringValueParser { - type Value = std::ffi::OsString; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - TypedValueParser::parse(self, cmd, arg, value.to_owned()) - } - - fn parse( - &self, - _cmd: &crate::Command, - _arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - Ok(value) - } -} - -impl Default for OsStringValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Implementation for [`ValueParser::path_buf`] -/// -/// Useful for composing new [`TypedValueParser`]s -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct PathBufValueParser {} - -impl PathBufValueParser { - /// Implementation for [`ValueParser::path_buf`] - pub fn new() -> Self { - Self {} - } -} - -impl TypedValueParser for PathBufValueParser { - type Value = std::path::PathBuf; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - TypedValueParser::parse(self, cmd, arg, value.to_owned()) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - if value.is_empty() { - return Err(crate::Error::empty_value( - cmd, - &[], - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - )); - } - Ok(Self::Value::from(value)) - } -} - -impl Default for PathBufValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Parse an [`ValueEnum`][crate::ValueEnum] value. -/// -/// See also: -/// - [`PossibleValuesParser`] -/// -/// # Example -/// -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::ColorChoice; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// -/// // Usage -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("color") -/// .value_parser(clap::builder::EnumValueParser::::new()) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap(); -/// let port: ColorChoice = *m.get_one("color") -/// .expect("required"); -/// assert_eq!(port, ColorChoice::Always); -/// -/// // Semantics -/// let value_parser = clap::builder::EnumValueParser::::new(); -/// // or -/// let value_parser = clap::value_parser!(ColorChoice); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("always")).unwrap(), ColorChoice::Always); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("auto")).unwrap(), ColorChoice::Auto); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), ColorChoice::Never); -/// ``` -#[derive(Clone, Debug)] -pub struct EnumValueParser( - std::marker::PhantomData, -); - -impl EnumValueParser { - /// Parse an [`ValueEnum`][crate::ValueEnum] - pub fn new() -> Self { - let phantom: std::marker::PhantomData = Default::default(); - Self(phantom) - } -} - -impl TypedValueParser for EnumValueParser { - type Value = E; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let ignore_case = arg.map(|a| a.is_ignore_case_set()).unwrap_or(false); - let possible_vals = || { - E::value_variants() - .iter() - .filter_map(|v| v.to_possible_value()) - .filter(|v| !v.is_hide_set()) - .map(|v| v.get_name().to_owned()) - .collect::>() - }; - - let value = ok!(value.to_str().ok_or_else(|| { - crate::Error::invalid_value( - cmd, - value.to_string_lossy().into_owned(), - &possible_vals(), - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - ) - })); - let value = ok!(E::value_variants() - .iter() - .find(|v| { - v.to_possible_value() - .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value") - .matches(value, ignore_case) - }) - .ok_or_else(|| { - crate::Error::invalid_value( - cmd, - value.to_owned(), - &possible_vals(), - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - ) - })) - .clone(); - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - Some(Box::new( - E::value_variants() - .iter() - .filter_map(|v| v.to_possible_value()), - )) - } -} - -impl Default for EnumValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue]. -/// -/// See also: -/// - [`EnumValueParser`] for directly supporting [`ValueEnum`][crate::ValueEnum] types -/// - [`TypedValueParser::map`] for adapting values to a more specialized type, like an external -/// enums that can't implement [`ValueEnum`][crate::ValueEnum] -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("color") -/// .value_parser(clap::builder::PossibleValuesParser::new(["always", "auto", "never"])) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap(); -/// let port: &String = m.get_one("color") -/// .expect("required"); -/// assert_eq!(port, "always"); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::PossibleValuesParser::new(["always", "auto", "never"]); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("always")).unwrap(), "always"); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("auto")).unwrap(), "auto"); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), "never"); -/// ``` -#[derive(Clone, Debug)] -pub struct PossibleValuesParser(Vec); - -impl PossibleValuesParser { - /// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue]. - pub fn new(values: impl Into) -> Self { - values.into() - } -} - -impl TypedValueParser for PossibleValuesParser { - type Value = String; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - TypedValueParser::parse(self, cmd, arg, value.to_owned()) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - let value = ok!(value.into_string().map_err(|_| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - - let ignore_case = arg.map(|a| a.is_ignore_case_set()).unwrap_or(false); - if self.0.iter().any(|v| v.matches(&value, ignore_case)) { - Ok(value) - } else { - let possible_vals = self - .0 - .iter() - .filter(|v| !v.is_hide_set()) - .map(|v| v.get_name().to_owned()) - .collect::>(); - - Err(crate::Error::invalid_value( - cmd, - value, - &possible_vals, - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - )) - } - } - - fn possible_values( - &self, - ) -> Option + '_>> { - Some(Box::new(self.0.iter().cloned())) - } -} - -impl From for PossibleValuesParser -where - I: IntoIterator, - T: Into, -{ - fn from(values: I) -> Self { - Self(values.into_iter().map(|t| t.into()).collect()) - } -} - -/// Parse number that fall within a range of values -/// -/// **NOTE:** To capture negative values, you will also need to set -/// [`Arg::allow_negative_numbers`][crate::Arg::allow_negative_numbers] or -/// [`Arg::allow_hyphen_values`][crate::Arg::allow_hyphen_values]. -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u16).range(3000..)) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: u16 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::RangedI64ValueParser::::new().range(-1..200); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err()); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).unwrap(), -1); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50); -/// ``` -#[derive(Copy, Clone, Debug)] -pub struct RangedI64ValueParser + Clone + Send + Sync = i64> { - bounds: (std::ops::Bound, std::ops::Bound), - target: std::marker::PhantomData, -} - -impl + Clone + Send + Sync> RangedI64ValueParser { - /// Select full range of `i64` - pub fn new() -> Self { - Self::from(..) - } - - /// Narrow the supported range - pub fn range>(mut self, range: B) -> Self { - // Consideration: when the user does `value_parser!(u8).range()` - // - Avoid programming mistakes by accidentally expanding the range - // - Make it convenient to limit the range like with `..10` - let start = match range.start_bound() { - l @ std::ops::Bound::Included(i) => { - debug_assert!( - self.bounds.contains(i), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - l @ std::ops::Bound::Excluded(i) => { - debug_assert!( - self.bounds.contains(&i.saturating_add(1)), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(), - }; - let end = match range.end_bound() { - l @ std::ops::Bound::Included(i) => { - debug_assert!( - self.bounds.contains(i), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - l @ std::ops::Bound::Excluded(i) => { - debug_assert!( - self.bounds.contains(&i.saturating_sub(1)), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(), - }; - self.bounds = (start, end); - self - } - - fn format_bounds(&self) -> String { - let mut result = match self.bounds.0 { - std::ops::Bound::Included(i) => i.to_string(), - std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(), - std::ops::Bound::Unbounded => i64::MIN.to_string(), - }; - result.push_str(".."); - match self.bounds.1 { - std::ops::Bound::Included(i) => { - result.push('='); - result.push_str(&i.to_string()); - } - std::ops::Bound::Excluded(i) => { - result.push_str(&i.to_string()); - } - std::ops::Bound::Unbounded => { - result.push_str(&i64::MAX.to_string()); - } - } - result - } -} - -impl + Clone + Send + Sync + 'static> TypedValueParser - for RangedI64ValueParser -where - >::Error: Send + Sync + 'static + std::error::Error + ToString, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - raw_value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(raw_value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - let value = ok!(value.parse::().map_err(|err| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - err.into(), - ) - .with_cmd(cmd) - })); - if !self.bounds.contains(&value) { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - return Err(crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - format!("{} is not in {}", value, self.format_bounds()).into(), - ) - .with_cmd(cmd)); - } - - let value: Result = value.try_into(); - let value = ok!(value.map_err(|err| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - err.into(), - ) - .with_cmd(cmd) - })); - - Ok(value) - } -} - -impl + Clone + Send + Sync, B: RangeBounds> From - for RangedI64ValueParser -{ - fn from(range: B) -> Self { - Self { - bounds: (range.start_bound().cloned(), range.end_bound().cloned()), - target: Default::default(), - } - } -} - -impl + Clone + Send + Sync> Default for RangedI64ValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Parse number that fall within a range of values -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u64).range(3000..)) -/// .action(clap::ArgAction::Set) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap(); -/// let port: u64 = *m.get_one("port") -/// .expect("required"); -/// assert_eq!(port, 3001); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::RangedU64ValueParser::::new().range(0..200); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).is_err()); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50); -/// ``` -#[derive(Copy, Clone, Debug)] -pub struct RangedU64ValueParser = u64> { - bounds: (std::ops::Bound, std::ops::Bound), - target: std::marker::PhantomData, -} - -impl> RangedU64ValueParser { - /// Select full range of `u64` - pub fn new() -> Self { - Self::from(..) - } - - /// Narrow the supported range - pub fn range>(mut self, range: B) -> Self { - // Consideration: when the user does `value_parser!(u8).range()` - // - Avoid programming mistakes by accidentally expanding the range - // - Make it convenient to limit the range like with `..10` - let start = match range.start_bound() { - l @ std::ops::Bound::Included(i) => { - debug_assert!( - self.bounds.contains(i), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - l @ std::ops::Bound::Excluded(i) => { - debug_assert!( - self.bounds.contains(&i.saturating_add(1)), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(), - }; - let end = match range.end_bound() { - l @ std::ops::Bound::Included(i) => { - debug_assert!( - self.bounds.contains(i), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - l @ std::ops::Bound::Excluded(i) => { - debug_assert!( - self.bounds.contains(&i.saturating_sub(1)), - "{} must be in {:?}", - i, - self.bounds - ); - l.cloned() - } - std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(), - }; - self.bounds = (start, end); - self - } - - fn format_bounds(&self) -> String { - let mut result = match self.bounds.0 { - std::ops::Bound::Included(i) => i.to_string(), - std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(), - std::ops::Bound::Unbounded => u64::MIN.to_string(), - }; - result.push_str(".."); - match self.bounds.1 { - std::ops::Bound::Included(i) => { - result.push('='); - result.push_str(&i.to_string()); - } - std::ops::Bound::Excluded(i) => { - result.push_str(&i.to_string()); - } - std::ops::Bound::Unbounded => { - result.push_str(&u64::MAX.to_string()); - } - } - result - } -} - -impl + Clone + Send + Sync + 'static> TypedValueParser - for RangedU64ValueParser -where - >::Error: Send + Sync + 'static + std::error::Error + ToString, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - raw_value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(raw_value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - let value = ok!(value.parse::().map_err(|err| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - err.into(), - ) - .with_cmd(cmd) - })); - if !self.bounds.contains(&value) { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - return Err(crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - format!("{} is not in {}", value, self.format_bounds()).into(), - ) - .with_cmd(cmd)); - } - - let value: Result = value.try_into(); - let value = ok!(value.map_err(|err| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation( - arg, - raw_value.to_string_lossy().into_owned(), - err.into(), - ) - .with_cmd(cmd) - })); - - Ok(value) - } -} - -impl, B: RangeBounds> From for RangedU64ValueParser { - fn from(range: B) -> Self { - Self { - bounds: (range.start_bound().cloned(), range.end_bound().cloned()), - target: Default::default(), - } - } -} - -impl> Default for RangedU64ValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Implementation for [`ValueParser::bool`] -/// -/// Useful for composing new [`TypedValueParser`]s -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct BoolValueParser {} - -impl BoolValueParser { - /// Implementation for [`ValueParser::bool`] - pub fn new() -> Self { - Self {} - } - - fn possible_values() -> impl Iterator { - ["true", "false"] - .iter() - .copied() - .map(crate::builder::PossibleValue::new) - } -} - -impl TypedValueParser for BoolValueParser { - type Value = bool; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = if value == std::ffi::OsStr::new("true") { - true - } else if value == std::ffi::OsStr::new("false") { - false - } else { - // Intentionally showing hidden as we hide all of them - let possible_vals = Self::possible_values() - .map(|v| v.get_name().to_owned()) - .collect::>(); - - return Err(crate::Error::invalid_value( - cmd, - value.to_string_lossy().into_owned(), - &possible_vals, - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - )); - }; - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - Some(Box::new(Self::possible_values())) - } -} - -impl Default for BoolValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Parse false-like string values, everything else is `true` -/// -/// See also: -/// - [`ValueParser::bool`] for assuming non-false is true -/// - [`BoolishValueParser`] for different human readable bool representations -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("append") -/// .value_parser(clap::builder::FalseyValueParser::new()) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); -/// let port: bool = *m.get_one("append") -/// .expect("required"); -/// assert_eq!(port, true); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::FalseyValueParser::new(); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false); -/// ``` -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct FalseyValueParser {} - -impl FalseyValueParser { - /// Parse false-like string values, everything else is `true` - pub fn new() -> Self { - Self {} - } - - fn possible_values() -> impl Iterator { - crate::util::TRUE_LITERALS - .iter() - .chain(crate::util::FALSE_LITERALS.iter()) - .copied() - .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false")) - } -} - -impl TypedValueParser for FalseyValueParser { - type Value = bool; - - fn parse_ref( - &self, - cmd: &crate::Command, - _arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - let value = if value.is_empty() { - false - } else { - crate::util::str_to_bool(value).unwrap_or(true) - }; - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - Some(Box::new(Self::possible_values())) - } -} - -impl Default for FalseyValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Parse bool-like string values, everything else is `true` -/// -/// See also: -/// - [`ValueParser::bool`] for different human readable bool representations -/// - [`FalseyValueParser`] for assuming non-false is true -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("append") -/// .value_parser(clap::builder::BoolishValueParser::new()) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); -/// let port: bool = *m.get_one("append") -/// .expect("required"); -/// assert_eq!(port, true); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::BoolishValueParser::new(); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).is_err()); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("true")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("Yes")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oN")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("1")).unwrap(), true); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false); -/// ``` -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct BoolishValueParser {} - -impl BoolishValueParser { - /// Parse bool-like string values, everything else is `true` - pub fn new() -> Self { - Self {} - } - - fn possible_values() -> impl Iterator { - crate::util::TRUE_LITERALS - .iter() - .chain(crate::util::FALSE_LITERALS.iter()) - .copied() - .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false")) - } -} - -impl TypedValueParser for BoolishValueParser { - type Value = bool; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - let value = ok!(crate::util::str_to_bool(value).ok_or_else(|| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation(arg, value.to_owned(), "value was not a boolean".into()) - .with_cmd(cmd) - })); - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - Some(Box::new(Self::possible_values())) - } -} - -impl Default for BoolishValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Parse non-empty string values -/// -/// See also: -/// - [`ValueParser::string`] -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("append") -/// .value_parser(clap::builder::NonEmptyStringValueParser::new()) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap(); -/// let port: &String = m.get_one("append") -/// .expect("required"); -/// assert_eq!(port, "true"); -/// ``` -/// -/// Semantics: -/// ```rust -/// # use clap_builder as clap; -/// # use std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// let value_parser = clap::builder::NonEmptyStringValueParser::new(); -/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), "random"); -/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err()); -/// ``` -#[derive(Copy, Clone, Debug)] -#[non_exhaustive] -pub struct NonEmptyStringValueParser {} - -impl NonEmptyStringValueParser { - /// Parse non-empty string values - pub fn new() -> Self { - Self {} - } -} - -impl TypedValueParser for NonEmptyStringValueParser { - type Value = String; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - if value.is_empty() { - return Err(crate::Error::empty_value( - cmd, - &[], - arg.map(ToString::to_string) - .unwrap_or_else(|| "...".to_owned()), - )); - } - let value = ok!(value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })); - Ok(value.to_owned()) - } -} - -impl Default for NonEmptyStringValueParser { - fn default() -> Self { - Self::new() - } -} - -/// Adapt a `TypedValueParser` from one value to another -/// -/// See [`TypedValueParser::map`] -#[derive(Clone, Debug)] -pub struct MapValueParser { - parser: P, - func: F, -} - -impl MapValueParser -where - P: TypedValueParser, - P::Value: Send + Sync + Clone, - F: Fn(P::Value) -> T + Clone, - T: Send + Sync + Clone, -{ - fn new(parser: P, func: F) -> Self { - Self { parser, func } - } -} - -impl TypedValueParser for MapValueParser -where - P: TypedValueParser, - P::Value: Send + Sync + Clone, - F: Fn(P::Value) -> T + Clone + Send + Sync + 'static, - T: Send + Sync + Clone, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = ok!(self.parser.parse_ref(cmd, arg, value)); - let value = (self.func)(value); - Ok(value) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - let value = ok!(self.parser.parse(cmd, arg, value)); - let value = (self.func)(value); - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - self.parser.possible_values() - } -} - -/// Adapt a `TypedValueParser` from one value to another -/// -/// See [`TypedValueParser::try_map`] -#[derive(Clone, Debug)] -pub struct TryMapValueParser { - parser: P, - func: F, -} - -impl TryMapValueParser -where - P: TypedValueParser, - P::Value: Send + Sync + Clone, - F: Fn(P::Value) -> Result + Clone + Send + Sync + 'static, - T: Send + Sync + Clone, - E: Into>, -{ - fn new(parser: P, func: F) -> Self { - Self { parser, func } - } -} - -impl TypedValueParser for TryMapValueParser -where - P: TypedValueParser, - P::Value: Send + Sync + Clone, - F: Fn(P::Value) -> Result + Clone + Send + Sync + 'static, - T: Send + Sync + Clone, - E: Into>, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let mid_value = ok!(self.parser.parse_ref(cmd, arg, value)); - let value = ok!((self.func)(mid_value).map_err(|e| { - let arg = arg - .map(|a| a.to_string()) - .unwrap_or_else(|| "...".to_owned()); - crate::Error::value_validation(arg, value.to_string_lossy().into_owned(), e.into()) - .with_cmd(cmd) - })); - Ok(value) - } - - fn possible_values( - &self, - ) -> Option + '_>> { - self.parser.possible_values() - } -} - -/// When encountered, report [ErrorKind::UnknownArgument][crate::error::ErrorKind::UnknownArgument] -/// -/// Useful to help users migrate, either from old versions or similar tools. -/// -/// # Examples -/// -/// ```rust -/// # use clap_builder as clap; -/// # use clap::Command; -/// # use clap::Arg; -/// let cmd = Command::new("mycmd") -/// .args([ -/// Arg::new("current-dir") -/// .short('C'), -/// Arg::new("current-dir-unknown") -/// .long("cwd") -/// .aliases(["current-dir", "directory", "working-directory", "root"]) -/// .value_parser(clap::builder::UnknownArgumentValueParser::suggest_arg("-C")) -/// .hide(true), -/// ]); -/// -/// // Use a supported version of the argument -/// let matches = cmd.clone().try_get_matches_from(["mycmd", "-C", ".."]).unwrap(); -/// assert!(matches.contains_id("current-dir")); -/// assert_eq!( -/// matches.get_many::("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::>(), -/// vec![".."] -/// ); -/// -/// // Use one of the invalid versions -/// let err = cmd.try_get_matches_from(["mycmd", "--cwd", ".."]).unwrap_err(); -/// assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument); -/// ``` -#[derive(Clone, Debug)] -pub struct UnknownArgumentValueParser { - arg: Option, - suggestions: Vec, -} - -impl UnknownArgumentValueParser { - /// Suggest an alternative argument - pub fn suggest_arg(arg: impl Into) -> Self { - Self { - arg: Some(arg.into()), - suggestions: Default::default(), - } - } - - /// Provide a general suggestion - pub fn suggest(text: impl Into) -> Self { - Self { - arg: Default::default(), - suggestions: vec![text.into()], - } - } - - /// Extend the suggestions - pub fn and_suggest(mut self, text: impl Into) -> Self { - self.suggestions.push(text.into()); - self - } -} - -impl TypedValueParser for UnknownArgumentValueParser { - type Value = String; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - TypedValueParser::parse_ref_(self, cmd, arg, value, ValueSource::CommandLine) - } - - fn parse_ref_( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - _value: &std::ffi::OsStr, - source: ValueSource, - ) -> Result { - match source { - ValueSource::DefaultValue => { - TypedValueParser::parse_ref_(&StringValueParser::new(), cmd, arg, _value, source) - } - ValueSource::EnvVariable | ValueSource::CommandLine => { - let arg = match arg { - Some(arg) => arg.to_string(), - None => "..".to_owned(), - }; - let err = crate::Error::unknown_argument( - cmd, - arg, - self.arg.as_ref().map(|s| (s.as_str().to_owned(), None)), - false, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ); - #[cfg(feature = "error-context")] - let err = { - debug_assert_eq!( - err.get(crate::error::ContextKind::Suggested), - None, - "Assuming `Error::unknown_argument` doesn't apply any `Suggested` so we can without caution" - ); - err.insert_context_unchecked( - crate::error::ContextKind::Suggested, - crate::error::ContextValue::StyledStrs(self.suggestions.clone()), - ) - }; - Err(err) - } - } - } -} - -/// Register a type with [value_parser!][crate::value_parser!] -/// -/// # Example -/// -/// ```rust -/// # use clap_builder as clap; -/// #[derive(Copy, Clone, Debug)] -/// pub struct Custom(u32); -/// -/// impl clap::builder::ValueParserFactory for Custom { -/// type Parser = CustomValueParser; -/// fn value_parser() -> Self::Parser { -/// CustomValueParser -/// } -/// } -/// -/// #[derive(Clone, Debug)] -/// pub struct CustomValueParser; -/// impl clap::builder::TypedValueParser for CustomValueParser { -/// type Value = Custom; -/// -/// fn parse_ref( -/// &self, -/// cmd: &clap::Command, -/// arg: Option<&clap::Arg>, -/// value: &std::ffi::OsStr, -/// ) -> Result { -/// let inner = clap::value_parser!(u32); -/// let val = inner.parse_ref(cmd, arg, value)?; -/// Ok(Custom(val)) -/// } -/// } -/// -/// let parser: CustomValueParser = clap::value_parser!(Custom); -/// ``` -pub trait ValueParserFactory { - /// Generated parser, usually [`ValueParser`]. - /// - /// It should at least be a type that supports `Into`. A non-`ValueParser` type - /// allows the caller to do further initialization on the parser. - type Parser; - - /// Create the specified [`Self::Parser`] - fn value_parser() -> Self::Parser; -} -impl ValueParserFactory for String { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::string() // Default `clap_derive` to optimized implementation - } -} -impl ValueParserFactory for Box { - type Parser = MapValueParser Box>; - fn value_parser() -> Self::Parser { - StringValueParser::new().map(String::into_boxed_str) - } -} -impl ValueParserFactory for std::ffi::OsString { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::os_string() // Default `clap_derive` to optimized implementation - } -} -impl ValueParserFactory for Box { - type Parser = - MapValueParser Box>; - fn value_parser() -> Self::Parser { - OsStringValueParser::new().map(std::ffi::OsString::into_boxed_os_str) - } -} -impl ValueParserFactory for std::path::PathBuf { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::path_buf() // Default `clap_derive` to optimized implementation - } -} -impl ValueParserFactory for Box { - type Parser = - MapValueParser Box>; - fn value_parser() -> Self::Parser { - PathBufValueParser::new().map(std::path::PathBuf::into_boxed_path) - } -} -impl ValueParserFactory for bool { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::bool() // Default `clap_derive` to optimized implementation - } -} -impl ValueParserFactory for u8 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = u8::MIN.into(); - let end: i64 = u8::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for i8 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = i8::MIN.into(); - let end: i64 = i8::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for u16 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = u16::MIN.into(); - let end: i64 = u16::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for i16 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = i16::MIN.into(); - let end: i64 = i16::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for u32 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = u32::MIN.into(); - let end: i64 = u32::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for i32 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - let start: i64 = i32::MIN.into(); - let end: i64 = i32::MAX.into(); - RangedI64ValueParser::new().range(start..=end) - } -} -impl ValueParserFactory for u64 { - type Parser = RangedU64ValueParser; - fn value_parser() -> Self::Parser { - RangedU64ValueParser::new() - } -} -impl ValueParserFactory for i64 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - RangedI64ValueParser::new() - } -} -impl ValueParserFactory for std::num::Wrapping -where - T: ValueParserFactory, - ::Parser: TypedValueParser, - T: Send + Sync + Clone, -{ - type Parser = MapValueParser<::Parser, fn(T) -> std::num::Wrapping>; - fn value_parser() -> Self::Parser { - T::value_parser().map(std::num::Wrapping) - } -} -impl ValueParserFactory for Box -where - T: ValueParserFactory, - ::Parser: TypedValueParser, - T: Send + Sync + Clone, -{ - type Parser = MapValueParser<::Parser, fn(T) -> Box>; - fn value_parser() -> Self::Parser { - T::value_parser().map(Box::new) - } -} -impl ValueParserFactory for std::sync::Arc -where - T: ValueParserFactory, - ::Parser: TypedValueParser, - T: Send + Sync + Clone, -{ - type Parser = MapValueParser<::Parser, fn(T) -> std::sync::Arc>; - fn value_parser() -> Self::Parser { - T::value_parser().map(std::sync::Arc::new) - } -} - -#[doc(hidden)] -#[derive(Debug)] -pub struct _AutoValueParser(std::marker::PhantomData); - -impl _AutoValueParser { - #[doc(hidden)] - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self(Default::default()) - } -} - -/// Unstable [`ValueParser`] -/// -/// Implementation may change to more specific instance in the future -#[doc(hidden)] -#[derive(Debug)] -pub struct _AnonymousValueParser(ValueParser); - -#[doc(hidden)] -pub mod via_prelude { - use super::*; - - #[doc(hidden)] - pub trait _ValueParserViaFactory: private::_ValueParserViaFactorySealed { - type Parser; - fn value_parser(&self) -> Self::Parser; - } - impl _ValueParserViaFactory for &&&&&&_AutoValueParser

{ - type Parser = P::Parser; - fn value_parser(&self) -> Self::Parser { - P::value_parser() - } - } - - #[doc(hidden)] - pub trait _ValueParserViaValueEnum: private::_ValueParserViaValueEnumSealed { - type Output; - - fn value_parser(&self) -> Self::Output; - } - impl _ValueParserViaValueEnum - for &&&&&_AutoValueParser - { - type Output = EnumValueParser; - - fn value_parser(&self) -> Self::Output { - EnumValueParser::::new() - } - } - - #[doc(hidden)] - pub trait _ValueParserViaFromOsString: private::_ValueParserViaFromOsStringSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaFromOsString for &&&&_AutoValueParser - where - FromOsString: From + std::any::Any + Clone + Send + Sync + 'static, - { - fn value_parser(&self) -> _AnonymousValueParser { - _AnonymousValueParser( - OsStringValueParser::new() - .map(|s| FromOsString::from(s)) - .into(), - ) - } - } - - #[doc(hidden)] - pub trait _ValueParserViaFromOsStr: private::_ValueParserViaFromOsStrSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaFromOsStr for &&&_AutoValueParser - where - FromOsStr: - for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Clone + Send + Sync + 'static, - { - fn value_parser(&self) -> _AnonymousValueParser { - _AnonymousValueParser( - OsStringValueParser::new() - .map(|s| FromOsStr::from(&s)) - .into(), - ) - } - } - - #[doc(hidden)] - pub trait _ValueParserViaFromString: private::_ValueParserViaFromStringSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaFromString for &&_AutoValueParser - where - FromString: From + std::any::Any + Clone + Send + Sync + 'static, - { - fn value_parser(&self) -> _AnonymousValueParser { - _AnonymousValueParser(StringValueParser::new().map(|s| FromString::from(s)).into()) - } - } - - #[doc(hidden)] - pub trait _ValueParserViaFromStr: private::_ValueParserViaFromStrSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaFromStr for &_AutoValueParser - where - FromStr: for<'s> From<&'s str> + std::any::Any + Clone + Send + Sync + 'static, - { - fn value_parser(&self) -> _AnonymousValueParser { - _AnonymousValueParser(StringValueParser::new().map(|s| FromStr::from(&s)).into()) - } - } - - #[doc(hidden)] - pub trait _ValueParserViaParse: private::_ValueParserViaParseSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaParse for _AutoValueParser - where - Parse: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static, - ::Err: Into>, - { - fn value_parser(&self) -> _AnonymousValueParser { - let func: fn(&str) -> Result::Err> = - Parse::from_str; - _AnonymousValueParser(ValueParser::new(func)) - } - } -} - -/// Select a [`ValueParser`] implementation from the intended type -/// -/// Supported types -/// - [`ValueParserFactory` types][ValueParserFactory], including -/// - [Native types][ValueParser]: `bool`, `String`, `OsString`, `PathBuf` -/// - [Ranged numeric types][RangedI64ValueParser]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64` -/// - [`ValueEnum` types][crate::ValueEnum] -/// - [`From` types][std::convert::From] and [`From<&OsStr>` types][std::convert::From] -/// - [`From` types][std::convert::From] and [`From<&str>` types][std::convert::From] -/// - [`FromStr` types][std::str::FromStr], including usize, isize -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # use clap_builder as clap; -/// # use std::path::PathBuf; -/// # use std::path::Path; -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("output") -/// .value_parser(clap::value_parser!(PathBuf)) -/// .required(true) -/// ); -/// -/// let m = cmd.try_get_matches_from_mut(["cmd", "file.txt"]).unwrap(); -/// let port: &PathBuf = m.get_one("output") -/// .expect("required"); -/// assert_eq!(port, Path::new("file.txt")); -/// ``` -/// -/// Example mappings: -/// ```rust -/// # use clap_builder as clap; -/// # use clap::ColorChoice; -/// // Built-in types -/// let parser = clap::value_parser!(String); -/// assert_eq!(format!("{parser:?}"), "ValueParser::string"); -/// let parser = clap::value_parser!(std::ffi::OsString); -/// assert_eq!(format!("{parser:?}"), "ValueParser::os_string"); -/// let parser = clap::value_parser!(std::path::PathBuf); -/// assert_eq!(format!("{parser:?}"), "ValueParser::path_buf"); -/// clap::value_parser!(u16).range(3000..); -/// clap::value_parser!(u64).range(3000..); -/// -/// // FromStr types -/// let parser = clap::value_parser!(usize); -/// assert_eq!(format!("{parser:?}"), "_AnonymousValueParser(ValueParser::other(usize))"); -/// -/// // ValueEnum types -/// clap::value_parser!(ColorChoice); -/// ``` -#[macro_export] -macro_rules! value_parser { - ($name:ty) => {{ - use $crate::builder::via_prelude::*; - let auto = $crate::builder::_AutoValueParser::<$name>::new(); - (&&&&&&auto).value_parser() - }}; -} - -mod private { - use super::*; - - // Prefer these so `clap_derive` defaults to optimized implementations - pub trait _ValueParserViaSelfSealed {} - impl> _ValueParserViaSelfSealed for &&&&&&&_AutoValueParser

{} - - pub trait _ValueParserViaFactorySealed {} - impl _ValueParserViaFactorySealed for &&&&&&_AutoValueParser

{} - - pub trait _ValueParserViaValueEnumSealed {} - impl _ValueParserViaValueEnumSealed for &&&&&_AutoValueParser {} - - pub trait _ValueParserViaFromOsStringSealed {} - impl _ValueParserViaFromOsStringSealed for &&&&_AutoValueParser where - FromOsString: From + std::any::Any + Send + Sync + 'static - { - } - - pub trait _ValueParserViaFromOsStrSealed {} - impl _ValueParserViaFromOsStrSealed for &&&_AutoValueParser where - FromOsStr: for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Send + Sync + 'static - { - } - - pub trait _ValueParserViaFromStringSealed {} - impl _ValueParserViaFromStringSealed for &&_AutoValueParser where - FromString: From + std::any::Any + Send + Sync + 'static - { - } - - pub trait _ValueParserViaFromStrSealed {} - impl _ValueParserViaFromStrSealed for &_AutoValueParser where - FromStr: for<'s> From<&'s str> + std::any::Any + Send + Sync + 'static - { - } - - pub trait _ValueParserViaParseSealed {} - impl _ValueParserViaParseSealed for _AutoValueParser - where - Parse: std::str::FromStr + std::any::Any + Send + Sync + 'static, - ::Err: Into>, - { - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn ensure_typed_applies_to_parse() { - fn parse(_: &str) -> Result { - Ok(10) - } - let cmd = crate::Command::new("cmd"); - let arg = None; - assert_eq!( - TypedValueParser::parse_ref(&parse, &cmd, arg, std::ffi::OsStr::new("foo")).unwrap(), - 10 - ); - } -} -- cgit v1.2.3