aboutsummaryrefslogtreecommitdiff
path: root/vendor/clap_builder/src/builder/value_parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap_builder/src/builder/value_parser.rs')
-rw-r--r--vendor/clap_builder/src/builder/value_parser.rs2712
1 files changed, 0 insertions, 2712 deletions
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<dyn AnyValueParser>),
-}
-
-impl ValueParser {
- /// Custom parser for argument values
- ///
- /// Pre-existing [`TypedValueParser`] implementations include:
- /// - `Fn(&str) -> Result<T, E>`
- /// - [`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<String>);
- /// fn parse_env_var(env: &str) -> Result<EnvVar, std::io::Error> {
- /// 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<P>(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<AnyValue, crate::Error> {
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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<P> From<P> 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<std::ops::Range<i64>> for ValueParser {
- fn from(value: std::ops::Range<i64>) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<std::ops::RangeInclusive<i64>> for ValueParser {
- fn from(value: std::ops::RangeInclusive<i64>) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<std::ops::RangeFrom<i64>> for ValueParser {
- fn from(value: std::ops::RangeFrom<i64>) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<std::ops::RangeTo<i64>> for ValueParser {
- fn from(value: std::ops::RangeTo<i64>) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<std::ops::RangeToInclusive<i64>> for ValueParser {
- fn from(value: std::ops::RangeToInclusive<i64>) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<std::ops::RangeFull> for ValueParser {
- fn from(value: std::ops::RangeFull) -> Self {
- let inner = RangedI64ValueParser::<i64>::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<P, const C: usize> From<[P; C]> for ValueParser
-where
- P: Into<super::PossibleValue>,
-{
- 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<P> From<Vec<P>> for ValueParser
-where
- P: Into<super::PossibleValue>,
-{
- fn from(values: Vec<P>) -> 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<AnyValue, crate::Error>;
-
- fn parse_ref_(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: &std::ffi::OsStr,
- _source: ValueSource,
- ) -> Result<AnyValue, crate::Error> {
- self.parse_ref(cmd, arg, value)
- }
-
- fn parse(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- ) -> Result<AnyValue, crate::Error>;
-
- fn parse_(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- _source: ValueSource,
- ) -> Result<AnyValue, crate::Error> {
- self.parse(cmd, arg, value)
- }
-
- /// Describes the content of `AnyValue`
- fn type_id(&self) -> AnyValueId;
-
- fn possible_values(
- &self,
- ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>;
-
- fn clone_any(&self) -> Box<dyn AnyValueParser>;
-}
-
-impl<T, P> AnyValueParser for P
-where
- T: std::any::Any + Clone + Send + Sync + 'static,
- P: TypedValueParser<Value = T>,
-{
- fn parse_ref(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: &std::ffi::OsStr,
- ) -> Result<AnyValue, crate::Error> {
- 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<AnyValue, crate::Error> {
- 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<AnyValue, crate::Error> {
- 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<AnyValue, crate::Error> {
- let value = ok!(TypedValueParser::parse_(self, cmd, arg, value, source));
- Ok(AnyValue::new(value))
- }
-
- fn type_id(&self) -> AnyValueId {
- AnyValueId::of::<T>()
- }
-
- fn possible_values(
- &self,
- ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- P::possible_values(self)
- }
-
- fn clone_any(&self) -> Box<dyn AnyValueParser> {
- Box::new(self.clone())
- }
-}
-
-/// Parse/validate argument values
-///
-/// As alternatives to implementing `TypedValueParser`,
-/// - Use `Fn(&str) -> Result<T, E>` 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<Self::Value, clap::Error> {
-/// 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<Self::Value, crate::Error>;
-
- /// 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::Value, crate::Error> {
- 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::Value, crate::Error> {
- 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::Value, crate::Error> {
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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::<usize>("flag").copied(),
- /// Some(10)
- /// );
- ///
- /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
- /// assert!(matches.contains_id("flag"));
- /// assert_eq!(
- /// matches.get_one::<usize>("flag").copied(),
- /// Some(5)
- /// );
- /// ```
- fn map<T, F>(self, func: F) -> MapValueParser<Self, F>
- 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<PathBuf, &'static str> {
- /// 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::<PathBuf>("flag").map(|s| s.as_path()),
- /// Some(Path::new("foo.rs"))
- /// );
- /// ```
- fn try_map<T, E, F>(self, func: F) -> TryMapValueParser<Self, F>
- where
- F: Fn(Self::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
- T: Send + Sync + Clone,
- E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
- {
- TryMapValueParser::new(self, func)
- }
-}
-
-impl<F, T, E> TypedValueParser for F
-where
- F: Fn(&str) -> Result<T, E> + Clone + Send + Sync + 'static,
- E: Into<Box<dyn std::error::Error + 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<Self::Value, crate::Error> {
- 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<Self::Value, crate::Error> {
- TypedValueParser::parse(self, cmd, arg, value.to_owned())
- }
-
- fn parse(
- &self,
- cmd: &crate::Command,
- _arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- ) -> Result<Self::Value, crate::Error> {
- 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<Self::Value, crate::Error> {
- TypedValueParser::parse(self, cmd, arg, value.to_owned())
- }
-
- fn parse(
- &self,
- _cmd: &crate::Command,
- _arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- ) -> Result<Self::Value, crate::Error> {
- 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<Self::Value, crate::Error> {
- TypedValueParser::parse(self, cmd, arg, value.to_owned())
- }
-
- fn parse(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- ) -> Result<Self::Value, crate::Error> {
- 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::<ColorChoice>::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::<ColorChoice>::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<E: crate::ValueEnum + Clone + Send + Sync + 'static>(
- std::marker::PhantomData<E>,
-);
-
-impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> EnumValueParser<E> {
- /// Parse an [`ValueEnum`][crate::ValueEnum]
- pub fn new() -> Self {
- let phantom: std::marker::PhantomData<E> = Default::default();
- Self(phantom)
- }
-}
-
-impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> TypedValueParser for EnumValueParser<E> {
- type Value = E;
-
- fn parse_ref(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: &std::ffi::OsStr,
- ) -> Result<Self::Value, crate::Error> {
- 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::<Vec<_>>()
- };
-
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- Some(Box::new(
- E::value_variants()
- .iter()
- .filter_map(|v| v.to_possible_value()),
- ))
- }
-}
-
-impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> Default for EnumValueParser<E> {
- 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<super::PossibleValue>);
-
-impl PossibleValuesParser {
- /// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue].
- pub fn new(values: impl Into<PossibleValuesParser>) -> 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<Self::Value, crate::Error> {
- TypedValueParser::parse(self, cmd, arg, value.to_owned())
- }
-
- fn parse(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: std::ffi::OsString,
- ) -> Result<String, crate::Error> {
- 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::<Vec<_>>();
-
- Err(crate::Error::invalid_value(
- cmd,
- value,
- &possible_vals,
- arg.map(ToString::to_string)
- .unwrap_or_else(|| "...".to_owned()),
- ))
- }
- }
-
- fn possible_values(
- &self,
- ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- Some(Box::new(self.0.iter().cloned()))
- }
-}
-
-impl<I, T> From<I> for PossibleValuesParser
-where
- I: IntoIterator<Item = T>,
- T: Into<super::PossibleValue>,
-{
- 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::<i32>::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<T: std::convert::TryFrom<i64> + Clone + Send + Sync = i64> {
- bounds: (std::ops::Bound<i64>, std::ops::Bound<i64>),
- target: std::marker::PhantomData<T>,
-}
-
-impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> {
- /// Select full range of `i64`
- pub fn new() -> Self {
- Self::from(..)
- }
-
- /// Narrow the supported range
- pub fn range<B: RangeBounds<i64>>(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<T: std::convert::TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser
- for RangedI64ValueParser<T>
-where
- <T as std::convert::TryFrom<i64>>::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<Self::Value, crate::Error> {
- 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::<i64>().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<Self::Value, _> = 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<T: std::convert::TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B>
- for RangedI64ValueParser<T>
-{
- fn from(range: B) -> Self {
- Self {
- bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
- target: Default::default(),
- }
- }
-}
-
-impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> {
- 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::<u32>::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<T: std::convert::TryFrom<u64> = u64> {
- bounds: (std::ops::Bound<u64>, std::ops::Bound<u64>),
- target: std::marker::PhantomData<T>,
-}
-
-impl<T: std::convert::TryFrom<u64>> RangedU64ValueParser<T> {
- /// Select full range of `u64`
- pub fn new() -> Self {
- Self::from(..)
- }
-
- /// Narrow the supported range
- pub fn range<B: RangeBounds<u64>>(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<T: std::convert::TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser
- for RangedU64ValueParser<T>
-where
- <T as std::convert::TryFrom<u64>>::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<Self::Value, crate::Error> {
- 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::<u64>().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<Self::Value, _> = 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<T: std::convert::TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> {
- fn from(range: B) -> Self {
- Self {
- bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
- target: Default::default(),
- }
- }
-}
-
-impl<T: std::convert::TryFrom<u64>> Default for RangedU64ValueParser<T> {
- 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<Item = crate::builder::PossibleValue> {
- ["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<Self::Value, crate::Error> {
- 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::<Vec<_>>();
-
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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<Item = crate::builder::PossibleValue> {
- 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<Self::Value, crate::Error> {
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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<Item = crate::builder::PossibleValue> {
- 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<Self::Value, crate::Error> {
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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<Self::Value, crate::Error> {
- 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<P, F> {
- parser: P,
- func: F,
-}
-
-impl<P, F, T> MapValueParser<P, F>
-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<P, F, T> TypedValueParser for MapValueParser<P, F>
-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<Self::Value, crate::Error> {
- 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<Self::Value, crate::Error> {
- let value = ok!(self.parser.parse(cmd, arg, value));
- let value = (self.func)(value);
- Ok(value)
- }
-
- fn possible_values(
- &self,
- ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- self.parser.possible_values()
- }
-}
-
-/// Adapt a `TypedValueParser` from one value to another
-///
-/// See [`TypedValueParser::try_map`]
-#[derive(Clone, Debug)]
-pub struct TryMapValueParser<P, F> {
- parser: P,
- func: F,
-}
-
-impl<P, F, T, E> TryMapValueParser<P, F>
-where
- P: TypedValueParser,
- P::Value: Send + Sync + Clone,
- F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
- T: Send + Sync + Clone,
- E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
-{
- fn new(parser: P, func: F) -> Self {
- Self { parser, func }
- }
-}
-
-impl<P, F, T, E> TypedValueParser for TryMapValueParser<P, F>
-where
- P: TypedValueParser,
- P::Value: Send + Sync + Clone,
- F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
- T: Send + Sync + Clone,
- E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
-{
- type Value = T;
-
- fn parse_ref(
- &self,
- cmd: &crate::Command,
- arg: Option<&crate::Arg>,
- value: &std::ffi::OsStr,
- ) -> Result<Self::Value, crate::Error> {
- 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<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
- 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::<String>("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
-/// 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<Str>,
- suggestions: Vec<StyledStr>,
-}
-
-impl UnknownArgumentValueParser {
- /// Suggest an alternative argument
- pub fn suggest_arg(arg: impl Into<Str>) -> Self {
- Self {
- arg: Some(arg.into()),
- suggestions: Default::default(),
- }
- }
-
- /// Provide a general suggestion
- pub fn suggest(text: impl Into<StyledStr>) -> Self {
- Self {
- arg: Default::default(),
- suggestions: vec![text.into()],
- }
- }
-
- /// Extend the suggestions
- pub fn and_suggest(mut self, text: impl Into<StyledStr>) -> 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<Self::Value, crate::Error> {
- 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<Self::Value, crate::Error> {
- 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<Self::Value, clap::Error> {
-/// 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<ValueParser>`. 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<str> {
- type Parser = MapValueParser<StringValueParser, fn(String) -> Box<str>>;
- 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<std::ffi::OsStr> {
- type Parser =
- MapValueParser<OsStringValueParser, fn(std::ffi::OsString) -> Box<std::ffi::OsStr>>;
- 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<std::path::Path> {
- type Parser =
- MapValueParser<PathBufValueParser, fn(std::path::PathBuf) -> Box<std::path::Path>>;
- 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<u8>;
- 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<i8>;
- 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<u16>;
- 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<i16>;
- 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<u32>;
- 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<i32>;
- 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<u64>;
- fn value_parser() -> Self::Parser {
- RangedU64ValueParser::new()
- }
-}
-impl ValueParserFactory for i64 {
- type Parser = RangedI64ValueParser<i64>;
- fn value_parser() -> Self::Parser {
- RangedI64ValueParser::new()
- }
-}
-impl<T> ValueParserFactory for std::num::Wrapping<T>
-where
- T: ValueParserFactory,
- <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
- T: Send + Sync + Clone,
-{
- type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::num::Wrapping<T>>;
- fn value_parser() -> Self::Parser {
- T::value_parser().map(std::num::Wrapping)
- }
-}
-impl<T> ValueParserFactory for Box<T>
-where
- T: ValueParserFactory,
- <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
- T: Send + Sync + Clone,
-{
- type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> Box<T>>;
- fn value_parser() -> Self::Parser {
- T::value_parser().map(Box::new)
- }
-}
-impl<T> ValueParserFactory for std::sync::Arc<T>
-where
- T: ValueParserFactory,
- <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
- T: Send + Sync + Clone,
-{
- type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::sync::Arc<T>>;
- fn value_parser() -> Self::Parser {
- T::value_parser().map(std::sync::Arc::new)
- }
-}
-
-#[doc(hidden)]
-#[derive(Debug)]
-pub struct _AutoValueParser<T>(std::marker::PhantomData<T>);
-
-impl<T> _AutoValueParser<T> {
- #[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<P: ValueParserFactory> _ValueParserViaFactory for &&&&&&_AutoValueParser<P> {
- 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<E: crate::ValueEnum + Clone + Send + Sync + 'static> _ValueParserViaValueEnum
- for &&&&&_AutoValueParser<E>
- {
- type Output = EnumValueParser<E>;
-
- fn value_parser(&self) -> Self::Output {
- EnumValueParser::<E>::new()
- }
- }
-
- #[doc(hidden)]
- pub trait _ValueParserViaFromOsString: private::_ValueParserViaFromOsStringSealed {
- fn value_parser(&self) -> _AnonymousValueParser;
- }
- impl<FromOsString> _ValueParserViaFromOsString for &&&&_AutoValueParser<FromOsString>
- where
- FromOsString: From<std::ffi::OsString> + 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<FromOsStr> _ValueParserViaFromOsStr for &&&_AutoValueParser<FromOsStr>
- 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<FromString> _ValueParserViaFromString for &&_AutoValueParser<FromString>
- where
- FromString: From<String> + 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<FromStr> _ValueParserViaFromStr for &_AutoValueParser<FromStr>
- 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<Parse> _ValueParserViaParse for _AutoValueParser<Parse>
- where
- Parse: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static,
- <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
- {
- fn value_parser(&self) -> _AnonymousValueParser {
- let func: fn(&str) -> Result<Parse, <Parse as std::str::FromStr>::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<OsString>` types][std::convert::From] and [`From<&OsStr>` types][std::convert::From]
-/// - [`From<String>` 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<P: Into<ValueParser>> _ValueParserViaSelfSealed for &&&&&&&_AutoValueParser<P> {}
-
- pub trait _ValueParserViaFactorySealed {}
- impl<P: ValueParserFactory> _ValueParserViaFactorySealed for &&&&&&_AutoValueParser<P> {}
-
- pub trait _ValueParserViaValueEnumSealed {}
- impl<E: crate::ValueEnum> _ValueParserViaValueEnumSealed for &&&&&_AutoValueParser<E> {}
-
- pub trait _ValueParserViaFromOsStringSealed {}
- impl<FromOsString> _ValueParserViaFromOsStringSealed for &&&&_AutoValueParser<FromOsString> where
- FromOsString: From<std::ffi::OsString> + std::any::Any + Send + Sync + 'static
- {
- }
-
- pub trait _ValueParserViaFromOsStrSealed {}
- impl<FromOsStr> _ValueParserViaFromOsStrSealed for &&&_AutoValueParser<FromOsStr> where
- FromOsStr: for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Send + Sync + 'static
- {
- }
-
- pub trait _ValueParserViaFromStringSealed {}
- impl<FromString> _ValueParserViaFromStringSealed for &&_AutoValueParser<FromString> where
- FromString: From<String> + std::any::Any + Send + Sync + 'static
- {
- }
-
- pub trait _ValueParserViaFromStrSealed {}
- impl<FromStr> _ValueParserViaFromStrSealed for &_AutoValueParser<FromStr> where
- FromStr: for<'s> From<&'s str> + std::any::Any + Send + Sync + 'static
- {
- }
-
- pub trait _ValueParserViaParseSealed {}
- impl<Parse> _ValueParserViaParseSealed for _AutoValueParser<Parse>
- where
- Parse: std::str::FromStr + std::any::Any + Send + Sync + 'static,
- <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
- {
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn ensure_typed_applies_to_parse() {
- fn parse(_: &str) -> Result<usize, std::io::Error> {
- 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
- );
- }
-}