From 20431706a863f92cb37dc512fef6e48d192aaf2c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:11:38 +0200 Subject: Merging upstream version 1.66.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/clap/src/builder/value_parser.rs | 2089 ------------------------------- 1 file changed, 2089 deletions(-) delete mode 100644 vendor/clap/src/builder/value_parser.rs (limited to 'vendor/clap/src/builder/value_parser.rs') diff --git a/vendor/clap/src/builder/value_parser.rs b/vendor/clap/src/builder/value_parser.rs deleted file mode 100644 index 0492f2782..000000000 --- a/vendor/clap/src/builder/value_parser.rs +++ /dev/null @@ -1,2089 +0,0 @@ -use std::convert::TryInto; -use std::ops::RangeBounds; - -use crate::parser::AnyValue; -use crate::parser::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 -/// 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()) -/// .takes_value(true) -/// .required(true) -/// ) -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u16).range(3000..)) -/// .takes_value(true) -/// .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 - /// - /// To create a custom parser, see [`TypedValueParser`] - /// - /// Pre-existing implementations include: - /// - [`EnumValueParser`] and [`PossibleValuesParser`] for static enumerated values - /// - [`BoolishValueParser`] and [`FalseyValueParser`] for alternative `bool` implementations - /// - [`RangedI64ValueParser`] and [`RangedU64ValueParser`] - /// - [`NonEmptyStringValueParser`] - /// - /// # Example - /// - /// ```rust - /// 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, - P::Value: Send + Sync + Clone, - { - 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 - /// 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 - /// 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 - /// - #[cfg_attr(not(unix), doc = " ```ignore")] - #[cfg_attr(unix, doc = " ```rust")] - /// # 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 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, - ) -> Result { - self.any_value_parser().parse_ref(cmd, arg, value) - } - - /// 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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("hostname") -/// .long("hostname") -/// .value_parser(clap::builder::NonEmptyStringValueParser::new()) -/// .takes_value(true) -/// .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, - P::Value: Send + Sync + Clone, -{ - 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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..4000) -/// .takes_value(true) -/// .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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..=4000) -/// .takes_value(true) -/// .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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(3000..) -/// .takes_value(true) -/// .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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..3000) -/// .takes_value(true) -/// .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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..=3000) -/// .takes_value(true) -/// .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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(..) -/// .takes_value(true) -/// .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::PossibleValue]s. -/// -/// # Examples -/// -/// ```rust -/// 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) - } -} - -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( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result; - - /// 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 = TypedValueParser::parse_ref(self, cmd, arg, value)?; - Ok(AnyValue::new(value)) - } - - fn parse( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - let value = TypedValueParser::parse(self, cmd, arg, value)?; - 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 -pub trait TypedValueParser: Clone + Send + Sync + 'static { - /// Argument's value type - type Value; - - /// 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( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: std::ffi::OsString, - ) -> Result { - self.parse_ref(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 - } -} - -impl TypedValueParser for F -where - F: Fn(&str) -> Result + Clone + Send + Sync + 'static, - E: Into>, -{ - type Value = T; - - fn parse_ref( - &self, - cmd: &crate::Command, - arg: Option<&crate::Arg>, - value: &std::ffi::OsStr, - ) -> Result { - let value = value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })?; - let value = (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 = 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 std::ffi::OsStr; -/// # use clap::builder::TypedValueParser; -/// # let cmd = clap::Command::new("test"); -/// # let arg = None; -/// -/// #[derive(Copy, Clone, Debug, PartialEq, Eq)] -/// enum ColorChoice { -/// Always, -/// Auto, -/// Never, -/// } -/// -/// impl clap::ValueEnum for ColorChoice { -/// fn value_variants<'a>() -> &'a [Self] { -/// &[Self::Always, Self::Auto, Self::Never] -/// } -/// -/// fn to_possible_value<'a>(&self) -> Option> { -/// match self { -/// Self::Always => Some(clap::PossibleValue::new("always")), -/// Self::Auto => Some(clap::PossibleValue::new("auto")), -/// Self::Never => Some(clap::PossibleValue::new("never")), -/// } -/// } -/// } -/// -/// // 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()) - .collect::>() - }; - - let value = 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 = 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::PossibleValue]. -/// -/// See also: -/// - [`EnumValueParser`] -/// -/// # Example -/// -/// Usage: -/// ```rust -/// 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 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 pf [`PossibleValue`][crate::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 = 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(crate::builder::PossibleValue::get_name) - .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 -/// -/// # Example -/// -/// Usage: -/// ```rust -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u16).range(3000..)) -/// .takes_value(true) -/// .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 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 = raw_value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })?; - let value = 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 = 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 -/// let mut cmd = clap::Command::new("raw") -/// .arg( -/// clap::Arg::new("port") -/// .long("port") -/// .value_parser(clap::value_parser!(u64).range(3000..)) -/// .takes_value(true) -/// .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 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 = raw_value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })?; - let value = 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 = 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::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()) - .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 -/// 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 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::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 = 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 -/// 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 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::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 = value.to_str().ok_or_else(|| { - crate::Error::invalid_utf8( - cmd, - crate::output::Usage::new(cmd).create_usage_with_title(&[]), - ) - })?; - let value = 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 -/// 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 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 = 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() - } -} - -/// Register a type with [value_parser!][crate::value_parser!] -/// -/// # Example -/// -/// ```rust -/// #[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() - } -} -impl ValueParserFactory for std::ffi::OsString { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::os_string() - } -} -impl ValueParserFactory for std::path::PathBuf { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::path_buf() - } -} -impl ValueParserFactory for bool { - type Parser = ValueParser; - fn value_parser() -> Self::Parser { - ValueParser::bool() - } -} -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 i64 { - type Parser = RangedI64ValueParser; - fn value_parser() -> Self::Parser { - RangedI64ValueParser::new() - } -} -impl ValueParserFactory for u64 { - type Parser = RangedU64ValueParser; - fn value_parser() -> Self::Parser { - RangedU64ValueParser::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 _ValueParserViaFromStr: private::_ValueParserViaFromStrSealed { - fn value_parser(&self) -> _AnonymousValueParser; - } - impl _ValueParserViaFromStr for _AutoValueParser - where - FromStr: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static, - ::Err: - Into>, - { - fn value_parser(&self) -> _AnonymousValueParser { - let func: fn(&str) -> Result::Err> = - FromStr::from_str; - _AnonymousValueParser(ValueParser::new(func)) - } - } -} - -/// Select a [`ValueParser`] implementation from the intended type -/// -/// To register a custom type with this macro, implement [`ValueParserFactory`]. -/// -/// # Example -/// -/// Usage: -/// ```rust -/// # 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")); -/// ``` -/// -/// Supported types: -/// ```rust -/// // 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"); -/// let parser = clap::value_parser!(u16).range(3000..); -/// assert_eq!(format!("{:?}", parser), "RangedI64ValueParser { bounds: (Included(3000), Included(65535)), target: PhantomData }"); -/// let parser = clap::value_parser!(u64).range(3000..); -/// assert_eq!(format!("{:?}", parser), "RangedU64ValueParser { bounds: (Included(3000), Unbounded), target: PhantomData }"); -/// -/// // FromStr types -/// let parser = clap::value_parser!(usize); -/// assert_eq!(format!("{:?}", parser), "_AnonymousValueParser(ValueParser::other(usize))"); -/// -/// // ValueEnum types -/// #[derive(Copy, Clone, Debug, PartialEq, Eq)] -/// enum ColorChoice { -/// Always, -/// Auto, -/// Never, -/// } -/// impl clap::ValueEnum for ColorChoice { -/// // ... -/// # fn value_variants<'a>() -> &'a [Self] { -/// # &[Self::Always, Self::Auto, Self::Never] -/// # } -/// # fn to_possible_value<'a>(&self) -> Option> { -/// # match self { -/// # Self::Always => Some(clap::PossibleValue::new("always")), -/// # Self::Auto => Some(clap::PossibleValue::new("auto")), -/// # Self::Never => Some(clap::PossibleValue::new("never")), -/// # } -/// # } -/// } -/// let parser = clap::value_parser!(ColorChoice); -/// assert_eq!(format!("{:?}", parser), "EnumValueParser(PhantomData)"); -/// ``` -#[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::*; - - pub trait _ValueParserViaSelfSealed {} - impl> _ValueParserViaSelfSealed for &&&_AutoValueParser

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

{} - - pub trait _ValueParserViaValueEnumSealed {} - impl _ValueParserViaValueEnumSealed for &_AutoValueParser {} - - pub trait _ValueParserViaFromStrSealed {} - impl _ValueParserViaFromStrSealed for _AutoValueParser - where - FromStr: 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