Skip to content

Commit

Permalink
Merge pull request #4257 from epage/os_str
Browse files Browse the repository at this point in the history
feat(parser): Support more types with `value_parser!`
  • Loading branch information
epage committed Sep 26, 2022
2 parents 0380d8d + bd6b67c commit c5c3c00
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/builder/str.rs
Expand Up @@ -131,7 +131,7 @@ impl AsRef<[u8]> for Str {
impl AsRef<std::ffi::OsStr> for Str {
#[inline]
fn as_ref(&self) -> &std::ffi::OsStr {
(&**self).as_ref()
(**self).as_ref()
}
}

Expand Down
126 changes: 106 additions & 20 deletions src/builder/value_parser.rs
Expand Up @@ -1930,25 +1930,25 @@ pub trait ValueParserFactory {
impl ValueParserFactory for String {
type Parser = ValueParser;
fn value_parser() -> Self::Parser {
ValueParser::string()
ValueParser::string() // Default `clap_derive` to optimized implementation
}
}
impl ValueParserFactory for std::ffi::OsString {
type Parser = ValueParser;
fn value_parser() -> Self::Parser {
ValueParser::os_string()
ValueParser::os_string() // Default `clap_derive` to optimized implementation
}
}
impl ValueParserFactory for std::path::PathBuf {
type Parser = ValueParser;
fn value_parser() -> Self::Parser {
ValueParser::path_buf()
ValueParser::path_buf() // Default `clap_derive` to optimized implementation
}
}
impl ValueParserFactory for bool {
type Parser = ValueParser;
fn value_parser() -> Self::Parser {
ValueParser::bool()
ValueParser::bool() // Default `clap_derive` to optimized implementation
}
}
impl ValueParserFactory for u8 {
Expand Down Expand Up @@ -2040,7 +2040,7 @@ pub mod via_prelude {
type Parser;
fn value_parser(&self) -> Self::Parser;
}
impl<P: ValueParserFactory> _ValueParserViaFactory for &&_AutoValueParser<P> {
impl<P: ValueParserFactory> _ValueParserViaFactory for &&&&&&_AutoValueParser<P> {
type Parser = P::Parser;
fn value_parser(&self) -> Self::Parser {
P::value_parser()
Expand All @@ -2054,7 +2054,7 @@ pub mod via_prelude {
fn value_parser(&self) -> Self::Output;
}
impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> _ValueParserViaValueEnum
for &_AutoValueParser<E>
for &&&&&_AutoValueParser<E>
{
type Output = EnumValueParser<E>;

Expand All @@ -2063,19 +2063,79 @@ pub mod via_prelude {
}
}

#[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>
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
FromStr: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static,
<FromStr as std::str::FromStr>::Err:
Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
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<FromStr, <FromStr as std::str::FromStr>::Err> =
FromStr::from_str;
let func: fn(&str) -> Result<Parse, <Parse as std::str::FromStr>::Err> =
Parse::from_str;
_AnonymousValueParser(ValueParser::new(func))
}
}
Expand All @@ -2088,6 +2148,8 @@ pub mod via_prelude {
/// - [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
Expand Down Expand Up @@ -2155,28 +2217,52 @@ macro_rules! value_parser {
($name:ty) => {{
use $crate::builder::via_prelude::*;
let auto = $crate::builder::_AutoValueParser::<$name>::new();
(&&&auto).value_parser()
(&&&&&&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> {}
impl<P: Into<ValueParser>> _ValueParserViaSelfSealed for &&&&&&&_AutoValueParser<P> {}

pub trait _ValueParserViaFactorySealed {}
impl<P: ValueParserFactory> _ValueParserViaFactorySealed for &&_AutoValueParser<P> {}
impl<P: ValueParserFactory> _ValueParserViaFactorySealed for &&&&&&_AutoValueParser<P> {}

pub trait _ValueParserViaValueEnumSealed {}
impl<E: crate::ValueEnum> _ValueParserViaValueEnumSealed for &_AutoValueParser<E> {}
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>
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
FromStr: std::str::FromStr + std::any::Any + Send + Sync + 'static,
<FromStr as std::str::FromStr>::Err:
Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
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>>,
{
}
}
Expand Down

0 comments on commit c5c3c00

Please sign in to comment.