clap_builder/builder/
value_parser.rs

1use std::convert::TryInto;
2use std::ops::RangeBounds;
3
4use crate::builder::Str;
5use crate::builder::StyledStr;
6use crate::parser::ValueSource;
7use crate::util::AnyValue;
8use crate::util::AnyValueId;
9
10/// Parse/validate argument values
11///
12/// Specified with [`Arg::value_parser`][crate::Arg::value_parser].
13///
14/// `ValueParser` defines how to convert a raw argument value into a validated and typed value for
15/// use within an application.
16///
17/// See
18/// - [`value_parser!`][crate::value_parser] for automatically selecting an implementation for a given type
19/// - [`ValueParser::new`] for additional [`TypedValueParser`] that can be used
20///
21/// # Example
22///
23/// ```rust
24/// # use clap_builder as clap;
25/// let mut cmd = clap::Command::new("raw")
26///     .arg(
27///         clap::Arg::new("color")
28///             .long("color")
29///             .value_parser(["always", "auto", "never"])
30///             .default_value("auto")
31///     )
32///     .arg(
33///         clap::Arg::new("hostname")
34///             .long("hostname")
35///             .value_parser(clap::builder::NonEmptyStringValueParser::new())
36///             .action(clap::ArgAction::Set)
37///             .required(true)
38///     )
39///     .arg(
40///         clap::Arg::new("port")
41///             .long("port")
42///             .value_parser(clap::value_parser!(u16).range(3000..))
43///             .action(clap::ArgAction::Set)
44///             .required(true)
45///     );
46///
47/// let m = cmd.try_get_matches_from_mut(
48///     ["cmd", "--hostname", "rust-lang.org", "--port", "3001"]
49/// ).unwrap();
50///
51/// let color: &String = m.get_one("color")
52///     .expect("default");
53/// assert_eq!(color, "auto");
54///
55/// let hostname: &String = m.get_one("hostname")
56///     .expect("required");
57/// assert_eq!(hostname, "rust-lang.org");
58///
59/// let port: u16 = *m.get_one("port")
60///     .expect("required");
61/// assert_eq!(port, 3001);
62/// ```
63pub struct ValueParser(ValueParserInner);
64
65enum ValueParserInner {
66    // Common enough to optimize and for possible values
67    Bool,
68    // Common enough to optimize
69    String,
70    // Common enough to optimize
71    OsString,
72    // Common enough to optimize
73    PathBuf,
74    Other(Box<dyn AnyValueParser>),
75}
76
77impl ValueParser {
78    /// Custom parser for argument values
79    ///
80    /// Pre-existing [`TypedValueParser`] implementations include:
81    /// - `Fn(&str) -> Result<T, E>`
82    /// - [`EnumValueParser`] and  [`PossibleValuesParser`] for static enumerated values
83    /// - [`BoolishValueParser`] and [`FalseyValueParser`] for alternative `bool` implementations
84    /// - [`RangedI64ValueParser`] and [`RangedU64ValueParser`]
85    /// - [`NonEmptyStringValueParser`]
86    ///
87    /// # Example
88    ///
89    /// ```rust
90    /// # use clap_builder as clap;
91    /// type EnvVar = (String, Option<String>);
92    /// fn parse_env_var(env: &str) -> Result<EnvVar, std::io::Error> {
93    ///     if let Some((var, value)) = env.split_once('=') {
94    ///         Ok((var.to_owned(), Some(value.to_owned())))
95    ///     } else {
96    ///         Ok((env.to_owned(), None))
97    ///     }
98    /// }
99    ///
100    /// let mut cmd = clap::Command::new("raw")
101    ///     .arg(
102    ///         clap::Arg::new("env")
103    ///             .value_parser(clap::builder::ValueParser::new(parse_env_var))
104    ///             .required(true)
105    ///     );
106    ///
107    /// let m = cmd.try_get_matches_from_mut(["cmd", "key=value"]).unwrap();
108    /// let port: &EnvVar = m.get_one("env")
109    ///     .expect("required");
110    /// assert_eq!(*port, ("key".into(), Some("value".into())));
111    /// ```
112    pub fn new<P>(other: P) -> Self
113    where
114        P: TypedValueParser,
115    {
116        Self(ValueParserInner::Other(Box::new(other)))
117    }
118
119    /// [`bool`] parser for argument values
120    ///
121    /// See also:
122    /// - [`BoolishValueParser`] for different human readable bool representations
123    /// - [`FalseyValueParser`] for assuming non-false is true
124    ///
125    /// # Example
126    ///
127    /// ```rust
128    /// # use clap_builder as clap;
129    /// let mut cmd = clap::Command::new("raw")
130    ///     .arg(
131    ///         clap::Arg::new("download")
132    ///             .value_parser(clap::value_parser!(bool))
133    ///             .required(true)
134    ///     );
135    ///
136    /// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
137    /// let port: bool = *m.get_one("download")
138    ///     .expect("required");
139    /// assert_eq!(port, true);
140    ///
141    /// assert!(cmd.try_get_matches_from_mut(["cmd", "forever"]).is_err());
142    /// ```
143    pub const fn bool() -> Self {
144        Self(ValueParserInner::Bool)
145    }
146
147    /// [`String`] parser for argument values
148    ///
149    /// See also:
150    /// - [`NonEmptyStringValueParser`]
151    ///
152    /// # Example
153    ///
154    /// ```rust
155    /// # use clap_builder as clap;
156    /// let mut cmd = clap::Command::new("raw")
157    ///     .arg(
158    ///         clap::Arg::new("port")
159    ///             .value_parser(clap::value_parser!(String))
160    ///             .required(true)
161    ///     );
162    ///
163    /// let m = cmd.try_get_matches_from_mut(["cmd", "80"]).unwrap();
164    /// let port: &String = m.get_one("port")
165    ///     .expect("required");
166    /// assert_eq!(port, "80");
167    /// ```
168    pub const fn string() -> Self {
169        Self(ValueParserInner::String)
170    }
171
172    /// [`OsString`][std::ffi::OsString] parser for argument values
173    ///
174    /// # Example
175    ///
176    /// ```rust
177    /// # #[cfg(unix)] {
178    /// # use clap_builder as clap;
179    /// # use clap::{Command, Arg, builder::ValueParser};
180    /// use std::ffi::OsString;
181    /// use std::os::unix::ffi::{OsStrExt,OsStringExt};
182    /// let r = Command::new("myprog")
183    ///     .arg(
184    ///         Arg::new("arg")
185    ///         .required(true)
186    ///         .value_parser(ValueParser::os_string())
187    ///     )
188    ///     .try_get_matches_from(vec![
189    ///         OsString::from("myprog"),
190    ///         OsString::from_vec(vec![0xe9])
191    ///     ]);
192    ///
193    /// assert!(r.is_ok());
194    /// let m = r.unwrap();
195    /// let arg: &OsString = m.get_one("arg")
196    ///     .expect("required");
197    /// assert_eq!(arg.as_bytes(), &[0xe9]);
198    /// # }
199    /// ```
200    pub const fn os_string() -> Self {
201        Self(ValueParserInner::OsString)
202    }
203
204    /// [`PathBuf`][std::path::PathBuf] parser for argument values
205    ///
206    /// # Example
207    ///
208    /// ```rust
209    /// # use clap_builder as clap;
210    /// # use std::path::PathBuf;
211    /// # use std::path::Path;
212    /// let mut cmd = clap::Command::new("raw")
213    ///     .arg(
214    ///         clap::Arg::new("output")
215    ///             .value_parser(clap::value_parser!(PathBuf))
216    ///             .required(true)
217    ///     );
218    ///
219    /// let m = cmd.try_get_matches_from_mut(["cmd", "hello.txt"]).unwrap();
220    /// let port: &PathBuf = m.get_one("output")
221    ///     .expect("required");
222    /// assert_eq!(port, Path::new("hello.txt"));
223    ///
224    /// assert!(cmd.try_get_matches_from_mut(["cmd", ""]).is_err());
225    /// ```
226    pub const fn path_buf() -> Self {
227        Self(ValueParserInner::PathBuf)
228    }
229}
230
231impl ValueParser {
232    /// Parse into a `AnyValue`
233    ///
234    /// When `arg` is `None`, an external subcommand value is being parsed.
235    pub(crate) fn parse_ref(
236        &self,
237        cmd: &crate::Command,
238        arg: Option<&crate::Arg>,
239        value: &std::ffi::OsStr,
240        source: ValueSource,
241    ) -> Result<AnyValue, crate::Error> {
242        self.any_value_parser().parse_ref_(cmd, arg, value, source)
243    }
244
245    /// Describes the content of `AnyValue`
246    pub fn type_id(&self) -> AnyValueId {
247        self.any_value_parser().type_id()
248    }
249
250    /// Reflect on enumerated value properties
251    ///
252    /// Error checking should not be done with this; it is mostly targeted at user-facing
253    /// applications like errors and completion.
254    pub fn possible_values(
255        &self,
256    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
257        self.any_value_parser().possible_values()
258    }
259
260    fn any_value_parser(&self) -> &dyn AnyValueParser {
261        match &self.0 {
262            ValueParserInner::Bool => &BoolValueParser {},
263            ValueParserInner::String => &StringValueParser {},
264            ValueParserInner::OsString => &OsStringValueParser {},
265            ValueParserInner::PathBuf => &PathBufValueParser {},
266            ValueParserInner::Other(o) => o.as_ref(),
267        }
268    }
269}
270
271/// Convert a [`TypedValueParser`] to [`ValueParser`]
272///
273/// # Example
274///
275/// ```rust
276/// # use clap_builder as clap;
277/// let mut cmd = clap::Command::new("raw")
278///     .arg(
279///         clap::Arg::new("hostname")
280///             .long("hostname")
281///             .value_parser(clap::builder::NonEmptyStringValueParser::new())
282///             .action(clap::ArgAction::Set)
283///             .required(true)
284///     );
285///
286/// let m = cmd.try_get_matches_from_mut(
287///     ["cmd", "--hostname", "rust-lang.org"]
288/// ).unwrap();
289///
290/// let hostname: &String = m.get_one("hostname")
291///     .expect("required");
292/// assert_eq!(hostname, "rust-lang.org");
293/// ```
294impl<P> From<P> for ValueParser
295where
296    P: TypedValueParser + Send + Sync + 'static,
297{
298    fn from(p: P) -> Self {
299        Self::new(p)
300    }
301}
302
303impl From<_AnonymousValueParser> for ValueParser {
304    fn from(p: _AnonymousValueParser) -> Self {
305        p.0
306    }
307}
308
309/// Create an `i64` [`ValueParser`] from a `N..M` range
310///
311/// See [`RangedI64ValueParser`] for more control over the output type.
312///
313/// See also [`RangedU64ValueParser`]
314///
315/// # Examples
316///
317/// ```rust
318/// # use clap_builder as clap;
319/// let mut cmd = clap::Command::new("raw")
320///     .arg(
321///         clap::Arg::new("port")
322///             .long("port")
323///             .value_parser(3000..4000)
324///             .action(clap::ArgAction::Set)
325///             .required(true)
326///     );
327///
328/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
329/// let port: i64 = *m.get_one("port")
330///     .expect("required");
331/// assert_eq!(port, 3001);
332/// ```
333impl From<std::ops::Range<i64>> for ValueParser {
334    fn from(value: std::ops::Range<i64>) -> Self {
335        let inner = RangedI64ValueParser::<i64>::new().range(value.start..value.end);
336        Self::from(inner)
337    }
338}
339
340/// Create an `i64` [`ValueParser`] from a `N..=M` range
341///
342/// See [`RangedI64ValueParser`] for more control over the output type.
343///
344/// See also [`RangedU64ValueParser`]
345///
346/// # Examples
347///
348/// ```rust
349/// # use clap_builder as clap;
350/// let mut cmd = clap::Command::new("raw")
351///     .arg(
352///         clap::Arg::new("port")
353///             .long("port")
354///             .value_parser(3000..=4000)
355///             .action(clap::ArgAction::Set)
356///             .required(true)
357///     );
358///
359/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
360/// let port: i64 = *m.get_one("port")
361///     .expect("required");
362/// assert_eq!(port, 3001);
363/// ```
364impl From<std::ops::RangeInclusive<i64>> for ValueParser {
365    fn from(value: std::ops::RangeInclusive<i64>) -> Self {
366        let inner = RangedI64ValueParser::<i64>::new().range(value.start()..=value.end());
367        Self::from(inner)
368    }
369}
370
371/// Create an `i64` [`ValueParser`] from a `N..` range
372///
373/// See [`RangedI64ValueParser`] for more control over the output type.
374///
375/// See also [`RangedU64ValueParser`]
376///
377/// # Examples
378///
379/// ```rust
380/// # use clap_builder as clap;
381/// let mut cmd = clap::Command::new("raw")
382///     .arg(
383///         clap::Arg::new("port")
384///             .long("port")
385///             .value_parser(3000..)
386///             .action(clap::ArgAction::Set)
387///             .required(true)
388///     );
389///
390/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
391/// let port: i64 = *m.get_one("port")
392///     .expect("required");
393/// assert_eq!(port, 3001);
394/// ```
395impl From<std::ops::RangeFrom<i64>> for ValueParser {
396    fn from(value: std::ops::RangeFrom<i64>) -> Self {
397        let inner = RangedI64ValueParser::<i64>::new().range(value.start..);
398        Self::from(inner)
399    }
400}
401
402/// Create an `i64` [`ValueParser`] from a `..M` range
403///
404/// See [`RangedI64ValueParser`] for more control over the output type.
405///
406/// See also [`RangedU64ValueParser`]
407///
408/// # Examples
409///
410/// ```rust
411/// # use clap_builder as clap;
412/// let mut cmd = clap::Command::new("raw")
413///     .arg(
414///         clap::Arg::new("port")
415///             .long("port")
416///             .value_parser(..3000)
417///             .action(clap::ArgAction::Set)
418///             .required(true)
419///     );
420///
421/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap();
422/// let port: i64 = *m.get_one("port")
423///     .expect("required");
424/// assert_eq!(port, 80);
425/// ```
426impl From<std::ops::RangeTo<i64>> for ValueParser {
427    fn from(value: std::ops::RangeTo<i64>) -> Self {
428        let inner = RangedI64ValueParser::<i64>::new().range(..value.end);
429        Self::from(inner)
430    }
431}
432
433/// Create an `i64` [`ValueParser`] from a `..=M` range
434///
435/// See [`RangedI64ValueParser`] for more control over the output type.
436///
437/// See also [`RangedU64ValueParser`]
438///
439/// # Examples
440///
441/// ```rust
442/// # use clap_builder as clap;
443/// let mut cmd = clap::Command::new("raw")
444///     .arg(
445///         clap::Arg::new("port")
446///             .long("port")
447///             .value_parser(..=3000)
448///             .action(clap::ArgAction::Set)
449///             .required(true)
450///     );
451///
452/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "80"]).unwrap();
453/// let port: i64 = *m.get_one("port")
454///     .expect("required");
455/// assert_eq!(port, 80);
456/// ```
457impl From<std::ops::RangeToInclusive<i64>> for ValueParser {
458    fn from(value: std::ops::RangeToInclusive<i64>) -> Self {
459        let inner = RangedI64ValueParser::<i64>::new().range(..=value.end);
460        Self::from(inner)
461    }
462}
463
464/// Create an `i64` [`ValueParser`] from a `..` range
465///
466/// See [`RangedI64ValueParser`] for more control over the output type.
467///
468/// See also [`RangedU64ValueParser`]
469///
470/// # Examples
471///
472/// ```rust
473/// # use clap_builder as clap;
474/// let mut cmd = clap::Command::new("raw")
475///     .arg(
476///         clap::Arg::new("port")
477///             .long("port")
478///             .value_parser(..)
479///             .action(clap::ArgAction::Set)
480///             .required(true)
481///     );
482///
483/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
484/// let port: i64 = *m.get_one("port")
485///     .expect("required");
486/// assert_eq!(port, 3001);
487/// ```
488impl From<std::ops::RangeFull> for ValueParser {
489    fn from(value: std::ops::RangeFull) -> Self {
490        let inner = RangedI64ValueParser::<i64>::new().range(value);
491        Self::from(inner)
492    }
493}
494
495/// Create a [`ValueParser`] with [`PossibleValuesParser`]
496///
497/// See [`PossibleValuesParser`] for more flexibility in creating the
498/// [`PossibleValue`][crate::builder::PossibleValue]s.
499///
500/// # Examples
501///
502/// ```rust
503/// # use clap_builder as clap;
504/// let mut cmd = clap::Command::new("raw")
505///     .arg(
506///         clap::Arg::new("color")
507///             .long("color")
508///             .value_parser(["always", "auto", "never"])
509///             .default_value("auto")
510///     );
511///
512/// let m = cmd.try_get_matches_from_mut(
513///     ["cmd", "--color", "never"]
514/// ).unwrap();
515///
516/// let color: &String = m.get_one("color")
517///     .expect("default");
518/// assert_eq!(color, "never");
519/// ```
520impl<P, const C: usize> From<[P; C]> for ValueParser
521where
522    P: Into<super::PossibleValue>,
523{
524    fn from(values: [P; C]) -> Self {
525        let inner = PossibleValuesParser::from(values);
526        Self::from(inner)
527    }
528}
529
530/// Create a [`ValueParser`] with [`PossibleValuesParser`]
531///
532/// See [`PossibleValuesParser`] for more flexibility in creating the
533/// [`PossibleValue`][crate::builder::PossibleValue]s.
534///
535/// # Examples
536///
537/// ```rust
538/// # use clap_builder as clap;
539/// let possible = vec!["always", "auto", "never"];
540/// let mut cmd = clap::Command::new("raw")
541///     .arg(
542///         clap::Arg::new("color")
543///             .long("color")
544///             .value_parser(possible)
545///             .default_value("auto")
546///     );
547///
548/// let m = cmd.try_get_matches_from_mut(
549///     ["cmd", "--color", "never"]
550/// ).unwrap();
551///
552/// let color: &String = m.get_one("color")
553///     .expect("default");
554/// assert_eq!(color, "never");
555/// ```
556impl<P> From<Vec<P>> for ValueParser
557where
558    P: Into<super::PossibleValue>,
559{
560    fn from(values: Vec<P>) -> Self {
561        let inner = PossibleValuesParser::from(values);
562        Self::from(inner)
563    }
564}
565
566impl std::fmt::Debug for ValueParser {
567    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
568        match &self.0 {
569            ValueParserInner::Bool => f.debug_struct("ValueParser::bool").finish(),
570            ValueParserInner::String => f.debug_struct("ValueParser::string").finish(),
571            ValueParserInner::OsString => f.debug_struct("ValueParser::os_string").finish(),
572            ValueParserInner::PathBuf => f.debug_struct("ValueParser::path_buf").finish(),
573            ValueParserInner::Other(o) => write!(f, "ValueParser::other({:?})", o.type_id()),
574        }
575    }
576}
577
578impl Clone for ValueParser {
579    fn clone(&self) -> Self {
580        Self(match &self.0 {
581            ValueParserInner::Bool => ValueParserInner::Bool,
582            ValueParserInner::String => ValueParserInner::String,
583            ValueParserInner::OsString => ValueParserInner::OsString,
584            ValueParserInner::PathBuf => ValueParserInner::PathBuf,
585            ValueParserInner::Other(o) => ValueParserInner::Other(o.clone_any()),
586        })
587    }
588}
589
590/// A type-erased wrapper for [`TypedValueParser`].
591trait AnyValueParser: Send + Sync + 'static {
592    fn parse_ref(
593        &self,
594        cmd: &crate::Command,
595        arg: Option<&crate::Arg>,
596        value: &std::ffi::OsStr,
597    ) -> Result<AnyValue, crate::Error>;
598
599    fn parse_ref_(
600        &self,
601        cmd: &crate::Command,
602        arg: Option<&crate::Arg>,
603        value: &std::ffi::OsStr,
604        _source: ValueSource,
605    ) -> Result<AnyValue, crate::Error> {
606        self.parse_ref(cmd, arg, value)
607    }
608
609    /// Describes the content of `AnyValue`
610    fn type_id(&self) -> AnyValueId;
611
612    fn possible_values(
613        &self,
614    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>;
615
616    fn clone_any(&self) -> Box<dyn AnyValueParser>;
617}
618
619impl<T, P> AnyValueParser for P
620where
621    T: std::any::Any + Clone + Send + Sync + 'static,
622    P: TypedValueParser<Value = T>,
623{
624    fn parse_ref(
625        &self,
626        cmd: &crate::Command,
627        arg: Option<&crate::Arg>,
628        value: &std::ffi::OsStr,
629    ) -> Result<AnyValue, crate::Error> {
630        let value = ok!(TypedValueParser::parse_ref(self, cmd, arg, value));
631        Ok(AnyValue::new(value))
632    }
633
634    fn parse_ref_(
635        &self,
636        cmd: &crate::Command,
637        arg: Option<&crate::Arg>,
638        value: &std::ffi::OsStr,
639        source: ValueSource,
640    ) -> Result<AnyValue, crate::Error> {
641        let value = ok!(TypedValueParser::parse_ref_(self, cmd, arg, value, source));
642        Ok(AnyValue::new(value))
643    }
644
645    fn type_id(&self) -> AnyValueId {
646        AnyValueId::of::<T>()
647    }
648
649    fn possible_values(
650        &self,
651    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
652        P::possible_values(self)
653    }
654
655    fn clone_any(&self) -> Box<dyn AnyValueParser> {
656        Box::new(self.clone())
657    }
658}
659
660/// Parse/validate argument values
661///
662/// As alternatives to implementing `TypedValueParser`,
663/// - Use `Fn(&str) -> Result<T, E>` which implements `TypedValueParser`
664/// - [`TypedValueParser::map`] or [`TypedValueParser::try_map`] to adapt an existing `TypedValueParser`
665///
666/// See `ValueParserFactory` to register `TypedValueParser::Value` with
667/// [`value_parser!`][crate::value_parser].
668///
669/// # Example
670///
671/// ```rust
672/// # #[cfg(feature = "error-context")] {
673/// # use clap_builder as clap;
674/// # use clap::error::ErrorKind;
675/// # use clap::error::ContextKind;
676/// # use clap::error::ContextValue;
677/// #[derive(Clone)]
678/// struct Custom(u32);
679///
680/// #[derive(Clone)]
681/// struct CustomValueParser;
682///
683/// impl clap::builder::TypedValueParser for CustomValueParser {
684///     type Value = Custom;
685///
686///     fn parse_ref(
687///         &self,
688///         cmd: &clap::Command,
689///         arg: Option<&clap::Arg>,
690///         value: &std::ffi::OsStr,
691///     ) -> Result<Self::Value, clap::Error> {
692///         let inner = clap::value_parser!(u32);
693///         let val = inner.parse_ref(cmd, arg, value)?;
694///
695///         const INVALID_VALUE: u32 = 10;
696///         if val == INVALID_VALUE {
697///             let mut err = clap::Error::new(ErrorKind::ValueValidation)
698///                 .with_cmd(cmd);
699///             if let Some(arg) = arg {
700///                 err.insert(ContextKind::InvalidArg, ContextValue::String(arg.to_string()));
701///             }
702///             err.insert(ContextKind::InvalidValue, ContextValue::String(INVALID_VALUE.to_string()));
703///             return Err(err);
704///         }
705///
706///         Ok(Custom(val))
707///     }
708/// }
709/// # }
710/// ```
711pub trait TypedValueParser: Clone + Send + Sync + 'static {
712    /// Argument's value type
713    type Value: Send + Sync + Clone;
714
715    /// Parse the argument value
716    ///
717    /// When `arg` is `None`, an external subcommand value is being parsed.
718    fn parse_ref(
719        &self,
720        cmd: &crate::Command,
721        arg: Option<&crate::Arg>,
722        value: &std::ffi::OsStr,
723    ) -> Result<Self::Value, crate::Error>;
724
725    /// Parse the argument value
726    ///
727    /// When `arg` is `None`, an external subcommand value is being parsed.
728    fn parse_ref_(
729        &self,
730        cmd: &crate::Command,
731        arg: Option<&crate::Arg>,
732        value: &std::ffi::OsStr,
733        _source: ValueSource,
734    ) -> Result<Self::Value, crate::Error> {
735        self.parse_ref(cmd, arg, value)
736    }
737
738    /// Parse the argument value
739    ///
740    /// When `arg` is `None`, an external subcommand value is being parsed.
741    fn parse(
742        &self,
743        cmd: &crate::Command,
744        arg: Option<&crate::Arg>,
745        value: std::ffi::OsString,
746    ) -> Result<Self::Value, crate::Error> {
747        self.parse_ref(cmd, arg, &value)
748    }
749
750    /// Parse the argument value
751    ///
752    /// When `arg` is `None`, an external subcommand value is being parsed.
753    fn parse_(
754        &self,
755        cmd: &crate::Command,
756        arg: Option<&crate::Arg>,
757        value: std::ffi::OsString,
758        _source: ValueSource,
759    ) -> Result<Self::Value, crate::Error> {
760        self.parse(cmd, arg, value)
761    }
762
763    /// Reflect on enumerated value properties
764    ///
765    /// Error checking should not be done with this; it is mostly targeted at user-facing
766    /// applications like errors and completion.
767    fn possible_values(
768        &self,
769    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
770        None
771    }
772
773    /// Adapt a `TypedValueParser` from one value to another
774    ///
775    /// # Example
776    ///
777    /// ```rust
778    /// # use clap_builder as clap;
779    /// # use clap::Command;
780    /// # use clap::Arg;
781    /// # use clap::builder::TypedValueParser as _;
782    /// # use clap::builder::BoolishValueParser;
783    /// let cmd = Command::new("mycmd")
784    ///     .arg(
785    ///         Arg::new("flag")
786    ///             .long("flag")
787    ///             .action(clap::ArgAction::SetTrue)
788    ///             .value_parser(
789    ///                 BoolishValueParser::new()
790    ///                 .map(|b| -> usize {
791    ///                     if b { 10 } else { 5 }
792    ///                 })
793    ///             )
794    ///     );
795    ///
796    /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
797    /// assert!(matches.contains_id("flag"));
798    /// assert_eq!(
799    ///     matches.get_one::<usize>("flag").copied(),
800    ///     Some(10)
801    /// );
802    ///
803    /// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
804    /// assert!(matches.contains_id("flag"));
805    /// assert_eq!(
806    ///     matches.get_one::<usize>("flag").copied(),
807    ///     Some(5)
808    /// );
809    /// ```
810    fn map<T, F>(self, func: F) -> MapValueParser<Self, F>
811    where
812        T: Send + Sync + Clone,
813        F: Fn(Self::Value) -> T + Clone,
814    {
815        MapValueParser::new(self, func)
816    }
817
818    /// Adapt a `TypedValueParser` from one value to another
819    ///
820    /// # Example
821    ///
822    /// ```rust
823    /// # use clap_builder as clap;
824    /// # use std::ffi::OsString;
825    /// # use std::ffi::OsStr;
826    /// # use std::path::PathBuf;
827    /// # use std::path::Path;
828    /// # use clap::Command;
829    /// # use clap::Arg;
830    /// # use clap::builder::TypedValueParser as _;
831    /// # use clap::builder::OsStringValueParser;
832    /// let cmd = Command::new("mycmd")
833    ///     .arg(
834    ///         Arg::new("flag")
835    ///             .long("flag")
836    ///             .value_parser(
837    ///                 OsStringValueParser::new()
838    ///                 .try_map(verify_ext)
839    ///             )
840    ///     );
841    ///
842    /// fn verify_ext(os: OsString) -> Result<PathBuf, &'static str> {
843    ///     let path = PathBuf::from(os);
844    ///     if path.extension() != Some(OsStr::new("rs")) {
845    ///         return Err("only Rust files are supported");
846    ///     }
847    ///     Ok(path)
848    /// }
849    ///
850    /// let error = cmd.clone().try_get_matches_from(["mycmd", "--flag", "foo.txt"]).unwrap_err();
851    /// error.print();
852    ///
853    /// let matches = cmd.try_get_matches_from(["mycmd", "--flag", "foo.rs"]).unwrap();
854    /// assert!(matches.contains_id("flag"));
855    /// assert_eq!(
856    ///     matches.get_one::<PathBuf>("flag").map(|s| s.as_path()),
857    ///     Some(Path::new("foo.rs"))
858    /// );
859    /// ```
860    fn try_map<T, E, F>(self, func: F) -> TryMapValueParser<Self, F>
861    where
862        F: Fn(Self::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
863        T: Send + Sync + Clone,
864        E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
865    {
866        TryMapValueParser::new(self, func)
867    }
868}
869
870impl<F, T, E> TypedValueParser for F
871where
872    F: Fn(&str) -> Result<T, E> + Clone + Send + Sync + 'static,
873    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
874    T: Send + Sync + Clone,
875{
876    type Value = T;
877
878    fn parse_ref(
879        &self,
880        cmd: &crate::Command,
881        arg: Option<&crate::Arg>,
882        value: &std::ffi::OsStr,
883    ) -> Result<Self::Value, crate::Error> {
884        let value = ok!(value.to_str().ok_or_else(|| {
885            crate::Error::invalid_utf8(
886                cmd,
887                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
888            )
889        }));
890        let value = ok!((self)(value).map_err(|e| {
891            let arg = arg
892                .map(|a| a.to_string())
893                .unwrap_or_else(|| "...".to_owned());
894            crate::Error::value_validation(arg, value.to_owned(), e.into()).with_cmd(cmd)
895        }));
896        Ok(value)
897    }
898}
899
900/// Implementation for [`ValueParser::string`]
901///
902/// Useful for composing new [`TypedValueParser`]s
903#[derive(Copy, Clone, Debug)]
904#[non_exhaustive]
905pub struct StringValueParser {}
906
907impl StringValueParser {
908    /// Implementation for [`ValueParser::string`]
909    pub fn new() -> Self {
910        Self {}
911    }
912}
913
914impl TypedValueParser for StringValueParser {
915    type Value = String;
916
917    fn parse_ref(
918        &self,
919        cmd: &crate::Command,
920        arg: Option<&crate::Arg>,
921        value: &std::ffi::OsStr,
922    ) -> Result<Self::Value, crate::Error> {
923        TypedValueParser::parse(self, cmd, arg, value.to_owned())
924    }
925
926    fn parse(
927        &self,
928        cmd: &crate::Command,
929        _arg: Option<&crate::Arg>,
930        value: std::ffi::OsString,
931    ) -> Result<Self::Value, crate::Error> {
932        let value = ok!(value.into_string().map_err(|_| {
933            crate::Error::invalid_utf8(
934                cmd,
935                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
936            )
937        }));
938        Ok(value)
939    }
940}
941
942impl Default for StringValueParser {
943    fn default() -> Self {
944        Self::new()
945    }
946}
947
948/// Implementation for [`ValueParser::os_string`]
949///
950/// Useful for composing new [`TypedValueParser`]s
951#[derive(Copy, Clone, Debug)]
952#[non_exhaustive]
953pub struct OsStringValueParser {}
954
955impl OsStringValueParser {
956    /// Implementation for [`ValueParser::os_string`]
957    pub fn new() -> Self {
958        Self {}
959    }
960}
961
962impl TypedValueParser for OsStringValueParser {
963    type Value = std::ffi::OsString;
964
965    fn parse_ref(
966        &self,
967        cmd: &crate::Command,
968        arg: Option<&crate::Arg>,
969        value: &std::ffi::OsStr,
970    ) -> Result<Self::Value, crate::Error> {
971        TypedValueParser::parse(self, cmd, arg, value.to_owned())
972    }
973
974    fn parse(
975        &self,
976        _cmd: &crate::Command,
977        _arg: Option<&crate::Arg>,
978        value: std::ffi::OsString,
979    ) -> Result<Self::Value, crate::Error> {
980        Ok(value)
981    }
982}
983
984impl Default for OsStringValueParser {
985    fn default() -> Self {
986        Self::new()
987    }
988}
989
990/// Implementation for [`ValueParser::path_buf`]
991///
992/// Useful for composing new [`TypedValueParser`]s
993#[derive(Copy, Clone, Debug)]
994#[non_exhaustive]
995pub struct PathBufValueParser {}
996
997impl PathBufValueParser {
998    /// Implementation for [`ValueParser::path_buf`]
999    pub fn new() -> Self {
1000        Self {}
1001    }
1002}
1003
1004impl TypedValueParser for PathBufValueParser {
1005    type Value = std::path::PathBuf;
1006
1007    fn parse_ref(
1008        &self,
1009        cmd: &crate::Command,
1010        arg: Option<&crate::Arg>,
1011        value: &std::ffi::OsStr,
1012    ) -> Result<Self::Value, crate::Error> {
1013        TypedValueParser::parse(self, cmd, arg, value.to_owned())
1014    }
1015
1016    fn parse(
1017        &self,
1018        cmd: &crate::Command,
1019        arg: Option<&crate::Arg>,
1020        value: std::ffi::OsString,
1021    ) -> Result<Self::Value, crate::Error> {
1022        if value.is_empty() {
1023            return Err(crate::Error::empty_value(
1024                cmd,
1025                &[],
1026                arg.map(ToString::to_string)
1027                    .unwrap_or_else(|| "...".to_owned()),
1028            ));
1029        }
1030        Ok(Self::Value::from(value))
1031    }
1032}
1033
1034impl Default for PathBufValueParser {
1035    fn default() -> Self {
1036        Self::new()
1037    }
1038}
1039
1040/// Parse an [`ValueEnum`][crate::ValueEnum] value.
1041///
1042/// See also:
1043/// - [`PossibleValuesParser`]
1044///
1045/// # Example
1046///
1047/// ```rust
1048/// # use clap_builder as clap;
1049/// # use std::ffi::OsStr;
1050/// # use clap::ColorChoice;
1051/// # use clap::builder::TypedValueParser;
1052/// # let cmd = clap::Command::new("test");
1053/// # let arg = None;
1054///
1055/// // Usage
1056/// let mut cmd = clap::Command::new("raw")
1057///     .arg(
1058///         clap::Arg::new("color")
1059///             .value_parser(clap::builder::EnumValueParser::<ColorChoice>::new())
1060///             .required(true)
1061///     );
1062///
1063/// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap();
1064/// let port: ColorChoice = *m.get_one("color")
1065///     .expect("required");
1066/// assert_eq!(port, ColorChoice::Always);
1067///
1068/// // Semantics
1069/// let value_parser = clap::builder::EnumValueParser::<ColorChoice>::new();
1070/// // or
1071/// let value_parser = clap::value_parser!(ColorChoice);
1072/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1073/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1074/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("always")).unwrap(), ColorChoice::Always);
1075/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("auto")).unwrap(), ColorChoice::Auto);
1076/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), ColorChoice::Never);
1077/// ```
1078#[derive(Clone, Debug)]
1079pub struct EnumValueParser<E: crate::ValueEnum + Clone + Send + Sync + 'static>(
1080    std::marker::PhantomData<E>,
1081);
1082
1083impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> EnumValueParser<E> {
1084    /// Parse an [`ValueEnum`][crate::ValueEnum]
1085    pub fn new() -> Self {
1086        let phantom: std::marker::PhantomData<E> = Default::default();
1087        Self(phantom)
1088    }
1089}
1090
1091impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> TypedValueParser for EnumValueParser<E> {
1092    type Value = E;
1093
1094    fn parse_ref(
1095        &self,
1096        cmd: &crate::Command,
1097        arg: Option<&crate::Arg>,
1098        value: &std::ffi::OsStr,
1099    ) -> Result<Self::Value, crate::Error> {
1100        let ignore_case = arg.map(|a| a.is_ignore_case_set()).unwrap_or(false);
1101        let possible_vals = || {
1102            E::value_variants()
1103                .iter()
1104                .filter_map(|v| v.to_possible_value())
1105                .filter(|v| !v.is_hide_set())
1106                .map(|v| v.get_name().to_owned())
1107                .collect::<Vec<_>>()
1108        };
1109
1110        let value = ok!(value.to_str().ok_or_else(|| {
1111            crate::Error::invalid_value(
1112                cmd,
1113                value.to_string_lossy().into_owned(),
1114                &possible_vals(),
1115                arg.map(ToString::to_string)
1116                    .unwrap_or_else(|| "...".to_owned()),
1117            )
1118        }));
1119        let value = ok!(E::value_variants()
1120            .iter()
1121            .find(|v| {
1122                v.to_possible_value()
1123                    .expect("ValueEnum::value_variants contains only values with a corresponding ValueEnum::to_possible_value")
1124                    .matches(value, ignore_case)
1125            })
1126            .ok_or_else(|| {
1127            crate::Error::invalid_value(
1128                cmd,
1129                value.to_owned(),
1130                &possible_vals(),
1131                arg.map(ToString::to_string)
1132                    .unwrap_or_else(|| "...".to_owned()),
1133            )
1134            }))
1135            .clone();
1136        Ok(value)
1137    }
1138
1139    fn possible_values(
1140        &self,
1141    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1142        Some(Box::new(
1143            E::value_variants()
1144                .iter()
1145                .filter_map(|v| v.to_possible_value()),
1146        ))
1147    }
1148}
1149
1150impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> Default for EnumValueParser<E> {
1151    fn default() -> Self {
1152        Self::new()
1153    }
1154}
1155
1156/// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue].
1157///
1158/// See also:
1159/// - [`EnumValueParser`] for directly supporting [`ValueEnum`][crate::ValueEnum] types
1160/// - [`TypedValueParser::map`] for adapting values to a more specialized type, like an external
1161///   enums that can't implement [`ValueEnum`][crate::ValueEnum]
1162///
1163/// # Example
1164///
1165/// Usage:
1166/// ```rust
1167/// # use clap_builder as clap;
1168/// let mut cmd = clap::Command::new("raw")
1169///     .arg(
1170///         clap::Arg::new("color")
1171///             .value_parser(clap::builder::PossibleValuesParser::new(["always", "auto", "never"]))
1172///             .required(true)
1173///     );
1174///
1175/// let m = cmd.try_get_matches_from_mut(["cmd", "always"]).unwrap();
1176/// let port: &String = m.get_one("color")
1177///     .expect("required");
1178/// assert_eq!(port, "always");
1179/// ```
1180///
1181/// Semantics:
1182/// ```rust
1183/// # use clap_builder as clap;
1184/// # use std::ffi::OsStr;
1185/// # use clap::builder::TypedValueParser;
1186/// # let cmd = clap::Command::new("test");
1187/// # let arg = None;
1188/// let value_parser = clap::builder::PossibleValuesParser::new(["always", "auto", "never"]);
1189/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1190/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1191/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("always")).unwrap(), "always");
1192/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("auto")).unwrap(), "auto");
1193/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("never")).unwrap(), "never");
1194/// ```
1195#[derive(Clone, Debug)]
1196pub struct PossibleValuesParser(Vec<super::PossibleValue>);
1197
1198impl PossibleValuesParser {
1199    /// Verify the value is from an enumerated set of [`PossibleValue`][crate::builder::PossibleValue].
1200    pub fn new(values: impl Into<PossibleValuesParser>) -> Self {
1201        values.into()
1202    }
1203}
1204
1205impl TypedValueParser for PossibleValuesParser {
1206    type Value = String;
1207
1208    fn parse_ref(
1209        &self,
1210        cmd: &crate::Command,
1211        arg: Option<&crate::Arg>,
1212        value: &std::ffi::OsStr,
1213    ) -> Result<Self::Value, crate::Error> {
1214        TypedValueParser::parse(self, cmd, arg, value.to_owned())
1215    }
1216
1217    fn parse(
1218        &self,
1219        cmd: &crate::Command,
1220        arg: Option<&crate::Arg>,
1221        value: std::ffi::OsString,
1222    ) -> Result<String, crate::Error> {
1223        let value = ok!(value.into_string().map_err(|_| {
1224            crate::Error::invalid_utf8(
1225                cmd,
1226                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1227            )
1228        }));
1229
1230        let ignore_case = arg.map(|a| a.is_ignore_case_set()).unwrap_or(false);
1231        if self.0.iter().any(|v| v.matches(&value, ignore_case)) {
1232            Ok(value)
1233        } else {
1234            let possible_vals = self
1235                .0
1236                .iter()
1237                .filter(|v| !v.is_hide_set())
1238                .map(|v| v.get_name().to_owned())
1239                .collect::<Vec<_>>();
1240
1241            Err(crate::Error::invalid_value(
1242                cmd,
1243                value,
1244                &possible_vals,
1245                arg.map(ToString::to_string)
1246                    .unwrap_or_else(|| "...".to_owned()),
1247            ))
1248        }
1249    }
1250
1251    fn possible_values(
1252        &self,
1253    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1254        Some(Box::new(self.0.iter().cloned()))
1255    }
1256}
1257
1258impl<I, T> From<I> for PossibleValuesParser
1259where
1260    I: IntoIterator<Item = T>,
1261    T: Into<super::PossibleValue>,
1262{
1263    fn from(values: I) -> Self {
1264        Self(values.into_iter().map(|t| t.into()).collect())
1265    }
1266}
1267
1268/// Parse number that fall within a range of values
1269///
1270/// <div class="warning">
1271///
1272/// **NOTE:** To capture negative values, you will also need to set
1273/// [`Arg::allow_negative_numbers`][crate::Arg::allow_negative_numbers] or
1274/// [`Arg::allow_hyphen_values`][crate::Arg::allow_hyphen_values].
1275///
1276/// </div>
1277///
1278/// # Example
1279///
1280/// Usage:
1281/// ```rust
1282/// # use clap_builder as clap;
1283/// let mut cmd = clap::Command::new("raw")
1284///     .arg(
1285///         clap::Arg::new("port")
1286///             .long("port")
1287///             .value_parser(clap::value_parser!(u16).range(3000..))
1288///             .action(clap::ArgAction::Set)
1289///             .required(true)
1290///     );
1291///
1292/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
1293/// let port: u16 = *m.get_one("port")
1294///     .expect("required");
1295/// assert_eq!(port, 3001);
1296/// ```
1297///
1298/// Semantics:
1299/// ```rust
1300/// # use clap_builder as clap;
1301/// # use std::ffi::OsStr;
1302/// # use clap::builder::TypedValueParser;
1303/// # let cmd = clap::Command::new("test");
1304/// # let arg = None;
1305/// let value_parser = clap::builder::RangedI64ValueParser::<i32>::new().range(-1..200);
1306/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1307/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1308/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err());
1309/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err());
1310/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).unwrap(), -1);
1311/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0);
1312/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
1313/// ```
1314#[derive(Copy, Clone, Debug)]
1315pub struct RangedI64ValueParser<T: TryFrom<i64> + Clone + Send + Sync = i64> {
1316    bounds: (std::ops::Bound<i64>, std::ops::Bound<i64>),
1317    target: std::marker::PhantomData<T>,
1318}
1319
1320impl<T: TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> {
1321    /// Select full range of `i64`
1322    pub fn new() -> Self {
1323        Self::from(..)
1324    }
1325
1326    /// Narrow the supported range
1327    pub fn range<B: RangeBounds<i64>>(mut self, range: B) -> Self {
1328        // Consideration: when the user does `value_parser!(u8).range()`
1329        // - Avoid programming mistakes by accidentally expanding the range
1330        // - Make it convenient to limit the range like with `..10`
1331        let start = match range.start_bound() {
1332            l @ std::ops::Bound::Included(i) => {
1333                debug_assert!(
1334                    self.bounds.contains(i),
1335                    "{} must be in {:?}",
1336                    i,
1337                    self.bounds
1338                );
1339                l.cloned()
1340            }
1341            l @ std::ops::Bound::Excluded(i) => {
1342                debug_assert!(
1343                    self.bounds.contains(&i.saturating_add(1)),
1344                    "{} must be in {:?}",
1345                    i,
1346                    self.bounds
1347                );
1348                l.cloned()
1349            }
1350            std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(),
1351        };
1352        let end = match range.end_bound() {
1353            l @ std::ops::Bound::Included(i) => {
1354                debug_assert!(
1355                    self.bounds.contains(i),
1356                    "{} must be in {:?}",
1357                    i,
1358                    self.bounds
1359                );
1360                l.cloned()
1361            }
1362            l @ std::ops::Bound::Excluded(i) => {
1363                debug_assert!(
1364                    self.bounds.contains(&i.saturating_sub(1)),
1365                    "{} must be in {:?}",
1366                    i,
1367                    self.bounds
1368                );
1369                l.cloned()
1370            }
1371            std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(),
1372        };
1373        self.bounds = (start, end);
1374        self
1375    }
1376
1377    fn format_bounds(&self) -> String {
1378        let mut result = match self.bounds.0 {
1379            std::ops::Bound::Included(i) => i.to_string(),
1380            std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(),
1381            std::ops::Bound::Unbounded => i64::MIN.to_string(),
1382        };
1383        result.push_str("..");
1384        match self.bounds.1 {
1385            std::ops::Bound::Included(i) => {
1386                result.push('=');
1387                result.push_str(&i.to_string());
1388            }
1389            std::ops::Bound::Excluded(i) => {
1390                result.push_str(&i.to_string());
1391            }
1392            std::ops::Bound::Unbounded => {
1393                result.push_str(&i64::MAX.to_string());
1394            }
1395        }
1396        result
1397    }
1398}
1399
1400impl<T: TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser for RangedI64ValueParser<T>
1401where
1402    <T as TryFrom<i64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
1403{
1404    type Value = T;
1405
1406    fn parse_ref(
1407        &self,
1408        cmd: &crate::Command,
1409        arg: Option<&crate::Arg>,
1410        raw_value: &std::ffi::OsStr,
1411    ) -> Result<Self::Value, crate::Error> {
1412        let value = ok!(raw_value.to_str().ok_or_else(|| {
1413            crate::Error::invalid_utf8(
1414                cmd,
1415                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1416            )
1417        }));
1418        let value = ok!(value.parse::<i64>().map_err(|err| {
1419            let arg = arg
1420                .map(|a| a.to_string())
1421                .unwrap_or_else(|| "...".to_owned());
1422            crate::Error::value_validation(
1423                arg,
1424                raw_value.to_string_lossy().into_owned(),
1425                err.into(),
1426            )
1427            .with_cmd(cmd)
1428        }));
1429        if !self.bounds.contains(&value) {
1430            let arg = arg
1431                .map(|a| a.to_string())
1432                .unwrap_or_else(|| "...".to_owned());
1433            return Err(crate::Error::value_validation(
1434                arg,
1435                raw_value.to_string_lossy().into_owned(),
1436                format!("{} is not in {}", value, self.format_bounds()).into(),
1437            )
1438            .with_cmd(cmd));
1439        }
1440
1441        let value: Result<Self::Value, _> = value.try_into();
1442        let value = ok!(value.map_err(|err| {
1443            let arg = arg
1444                .map(|a| a.to_string())
1445                .unwrap_or_else(|| "...".to_owned());
1446            crate::Error::value_validation(
1447                arg,
1448                raw_value.to_string_lossy().into_owned(),
1449                err.into(),
1450            )
1451            .with_cmd(cmd)
1452        }));
1453
1454        Ok(value)
1455    }
1456}
1457
1458impl<T: TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B>
1459    for RangedI64ValueParser<T>
1460{
1461    fn from(range: B) -> Self {
1462        Self {
1463            bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
1464            target: Default::default(),
1465        }
1466    }
1467}
1468
1469impl<T: TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> {
1470    fn default() -> Self {
1471        Self::new()
1472    }
1473}
1474
1475/// Parse number that fall within a range of values
1476///
1477/// # Example
1478///
1479/// Usage:
1480/// ```rust
1481/// # use clap_builder as clap;
1482/// let mut cmd = clap::Command::new("raw")
1483///     .arg(
1484///         clap::Arg::new("port")
1485///             .long("port")
1486///             .value_parser(clap::value_parser!(u64).range(3000..))
1487///             .action(clap::ArgAction::Set)
1488///             .required(true)
1489///     );
1490///
1491/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
1492/// let port: u64 = *m.get_one("port")
1493///     .expect("required");
1494/// assert_eq!(port, 3001);
1495/// ```
1496///
1497/// Semantics:
1498/// ```rust
1499/// # use clap_builder as clap;
1500/// # use std::ffi::OsStr;
1501/// # use clap::builder::TypedValueParser;
1502/// # let cmd = clap::Command::new("test");
1503/// # let arg = None;
1504/// let value_parser = clap::builder::RangedU64ValueParser::<u32>::new().range(0..200);
1505/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1506/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1507/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err());
1508/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err());
1509/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).is_err());
1510/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0);
1511/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
1512/// ```
1513#[derive(Copy, Clone, Debug)]
1514pub struct RangedU64ValueParser<T: TryFrom<u64> = u64> {
1515    bounds: (std::ops::Bound<u64>, std::ops::Bound<u64>),
1516    target: std::marker::PhantomData<T>,
1517}
1518
1519impl<T: TryFrom<u64>> RangedU64ValueParser<T> {
1520    /// Select full range of `u64`
1521    pub fn new() -> Self {
1522        Self::from(..)
1523    }
1524
1525    /// Narrow the supported range
1526    pub fn range<B: RangeBounds<u64>>(mut self, range: B) -> Self {
1527        // Consideration: when the user does `value_parser!(u8).range()`
1528        // - Avoid programming mistakes by accidentally expanding the range
1529        // - Make it convenient to limit the range like with `..10`
1530        let start = match range.start_bound() {
1531            l @ std::ops::Bound::Included(i) => {
1532                debug_assert!(
1533                    self.bounds.contains(i),
1534                    "{} must be in {:?}",
1535                    i,
1536                    self.bounds
1537                );
1538                l.cloned()
1539            }
1540            l @ std::ops::Bound::Excluded(i) => {
1541                debug_assert!(
1542                    self.bounds.contains(&i.saturating_add(1)),
1543                    "{} must be in {:?}",
1544                    i,
1545                    self.bounds
1546                );
1547                l.cloned()
1548            }
1549            std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(),
1550        };
1551        let end = match range.end_bound() {
1552            l @ std::ops::Bound::Included(i) => {
1553                debug_assert!(
1554                    self.bounds.contains(i),
1555                    "{} must be in {:?}",
1556                    i,
1557                    self.bounds
1558                );
1559                l.cloned()
1560            }
1561            l @ std::ops::Bound::Excluded(i) => {
1562                debug_assert!(
1563                    self.bounds.contains(&i.saturating_sub(1)),
1564                    "{} must be in {:?}",
1565                    i,
1566                    self.bounds
1567                );
1568                l.cloned()
1569            }
1570            std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(),
1571        };
1572        self.bounds = (start, end);
1573        self
1574    }
1575
1576    fn format_bounds(&self) -> String {
1577        let mut result = match self.bounds.0 {
1578            std::ops::Bound::Included(i) => i.to_string(),
1579            std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(),
1580            std::ops::Bound::Unbounded => u64::MIN.to_string(),
1581        };
1582        result.push_str("..");
1583        match self.bounds.1 {
1584            std::ops::Bound::Included(i) => {
1585                result.push('=');
1586                result.push_str(&i.to_string());
1587            }
1588            std::ops::Bound::Excluded(i) => {
1589                result.push_str(&i.to_string());
1590            }
1591            std::ops::Bound::Unbounded => {
1592                result.push_str(&u64::MAX.to_string());
1593            }
1594        }
1595        result
1596    }
1597}
1598
1599impl<T: TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser for RangedU64ValueParser<T>
1600where
1601    <T as TryFrom<u64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
1602{
1603    type Value = T;
1604
1605    fn parse_ref(
1606        &self,
1607        cmd: &crate::Command,
1608        arg: Option<&crate::Arg>,
1609        raw_value: &std::ffi::OsStr,
1610    ) -> Result<Self::Value, crate::Error> {
1611        let value = ok!(raw_value.to_str().ok_or_else(|| {
1612            crate::Error::invalid_utf8(
1613                cmd,
1614                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1615            )
1616        }));
1617        let value = ok!(value.parse::<u64>().map_err(|err| {
1618            let arg = arg
1619                .map(|a| a.to_string())
1620                .unwrap_or_else(|| "...".to_owned());
1621            crate::Error::value_validation(
1622                arg,
1623                raw_value.to_string_lossy().into_owned(),
1624                err.into(),
1625            )
1626            .with_cmd(cmd)
1627        }));
1628        if !self.bounds.contains(&value) {
1629            let arg = arg
1630                .map(|a| a.to_string())
1631                .unwrap_or_else(|| "...".to_owned());
1632            return Err(crate::Error::value_validation(
1633                arg,
1634                raw_value.to_string_lossy().into_owned(),
1635                format!("{} is not in {}", value, self.format_bounds()).into(),
1636            )
1637            .with_cmd(cmd));
1638        }
1639
1640        let value: Result<Self::Value, _> = value.try_into();
1641        let value = ok!(value.map_err(|err| {
1642            let arg = arg
1643                .map(|a| a.to_string())
1644                .unwrap_or_else(|| "...".to_owned());
1645            crate::Error::value_validation(
1646                arg,
1647                raw_value.to_string_lossy().into_owned(),
1648                err.into(),
1649            )
1650            .with_cmd(cmd)
1651        }));
1652
1653        Ok(value)
1654    }
1655}
1656
1657impl<T: TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> {
1658    fn from(range: B) -> Self {
1659        Self {
1660            bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
1661            target: Default::default(),
1662        }
1663    }
1664}
1665
1666impl<T: TryFrom<u64>> Default for RangedU64ValueParser<T> {
1667    fn default() -> Self {
1668        Self::new()
1669    }
1670}
1671
1672/// Implementation for [`ValueParser::bool`]
1673///
1674/// Useful for composing new [`TypedValueParser`]s
1675#[derive(Copy, Clone, Debug)]
1676#[non_exhaustive]
1677pub struct BoolValueParser {}
1678
1679impl BoolValueParser {
1680    /// Implementation for [`ValueParser::bool`]
1681    pub fn new() -> Self {
1682        Self {}
1683    }
1684
1685    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1686        ["true", "false"]
1687            .iter()
1688            .copied()
1689            .map(crate::builder::PossibleValue::new)
1690    }
1691}
1692
1693impl TypedValueParser for BoolValueParser {
1694    type Value = bool;
1695
1696    fn parse_ref(
1697        &self,
1698        cmd: &crate::Command,
1699        arg: Option<&crate::Arg>,
1700        value: &std::ffi::OsStr,
1701    ) -> Result<Self::Value, crate::Error> {
1702        let value = if value == std::ffi::OsStr::new("true") {
1703            true
1704        } else if value == std::ffi::OsStr::new("false") {
1705            false
1706        } else {
1707            // Intentionally showing hidden as we hide all of them
1708            let possible_vals = Self::possible_values()
1709                .map(|v| v.get_name().to_owned())
1710                .collect::<Vec<_>>();
1711
1712            return Err(crate::Error::invalid_value(
1713                cmd,
1714                value.to_string_lossy().into_owned(),
1715                &possible_vals,
1716                arg.map(ToString::to_string)
1717                    .unwrap_or_else(|| "...".to_owned()),
1718            ));
1719        };
1720        Ok(value)
1721    }
1722
1723    fn possible_values(
1724        &self,
1725    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1726        Some(Box::new(Self::possible_values()))
1727    }
1728}
1729
1730impl Default for BoolValueParser {
1731    fn default() -> Self {
1732        Self::new()
1733    }
1734}
1735
1736/// Parse false-like string values, everything else is `true`
1737///
1738/// See also:
1739/// - [`ValueParser::bool`] for assuming non-false is true
1740/// - [`BoolishValueParser`] for different human readable bool representations
1741///
1742/// # Example
1743///
1744/// Usage:
1745/// ```rust
1746/// # use clap_builder as clap;
1747/// let mut cmd = clap::Command::new("raw")
1748///     .arg(
1749///         clap::Arg::new("append")
1750///             .value_parser(clap::builder::FalseyValueParser::new())
1751///             .required(true)
1752///     );
1753///
1754/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1755/// let port: bool = *m.get_one("append")
1756///     .expect("required");
1757/// assert_eq!(port, true);
1758/// ```
1759///
1760/// Semantics:
1761/// ```rust
1762/// # use clap_builder as clap;
1763/// # use std::ffi::OsStr;
1764/// # use clap::builder::TypedValueParser;
1765/// # let cmd = clap::Command::new("test");
1766/// # let arg = None;
1767/// let value_parser = clap::builder::FalseyValueParser::new();
1768/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), true);
1769/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).unwrap(), true);
1770/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).unwrap(), false);
1771/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false);
1772/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false);
1773/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false);
1774/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false);
1775/// ```
1776#[derive(Copy, Clone, Debug)]
1777#[non_exhaustive]
1778pub struct FalseyValueParser {}
1779
1780impl FalseyValueParser {
1781    /// Parse false-like string values, everything else is `true`
1782    pub fn new() -> Self {
1783        Self {}
1784    }
1785
1786    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1787        crate::util::TRUE_LITERALS
1788            .iter()
1789            .chain(crate::util::FALSE_LITERALS.iter())
1790            .copied()
1791            .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false"))
1792    }
1793}
1794
1795impl TypedValueParser for FalseyValueParser {
1796    type Value = bool;
1797
1798    fn parse_ref(
1799        &self,
1800        cmd: &crate::Command,
1801        _arg: Option<&crate::Arg>,
1802        value: &std::ffi::OsStr,
1803    ) -> Result<Self::Value, crate::Error> {
1804        let value = ok!(value.to_str().ok_or_else(|| {
1805            crate::Error::invalid_utf8(
1806                cmd,
1807                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1808            )
1809        }));
1810        let value = if value.is_empty() {
1811            false
1812        } else {
1813            crate::util::str_to_bool(value).unwrap_or(true)
1814        };
1815        Ok(value)
1816    }
1817
1818    fn possible_values(
1819        &self,
1820    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1821        Some(Box::new(Self::possible_values()))
1822    }
1823}
1824
1825impl Default for FalseyValueParser {
1826    fn default() -> Self {
1827        Self::new()
1828    }
1829}
1830
1831/// Parse bool-like string values
1832///
1833/// See also:
1834/// - [`ValueParser::bool`] for different human readable bool representations
1835/// - [`FalseyValueParser`] for assuming non-false is true
1836///
1837/// # Example
1838///
1839/// Usage:
1840/// ```rust
1841/// # use clap_builder as clap;
1842/// let mut cmd = clap::Command::new("raw")
1843///     .arg(
1844///         clap::Arg::new("append")
1845///             .value_parser(clap::builder::BoolishValueParser::new())
1846///             .required(true)
1847///     );
1848///
1849/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1850/// let port: bool = *m.get_one("append")
1851///     .expect("required");
1852/// assert_eq!(port, true);
1853/// ```
1854///
1855/// Semantics:
1856/// ```rust
1857/// # use clap_builder as clap;
1858/// # use std::ffi::OsStr;
1859/// # use clap::builder::TypedValueParser;
1860/// # let cmd = clap::Command::new("test");
1861/// # let arg = None;
1862/// let value_parser = clap::builder::BoolishValueParser::new();
1863/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1864/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1865/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).is_err());
1866/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("true")).unwrap(), true);
1867/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("Yes")).unwrap(), true);
1868/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oN")).unwrap(), true);
1869/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("1")).unwrap(), true);
1870/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false);
1871/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false);
1872/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false);
1873/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false);
1874/// ```
1875#[derive(Copy, Clone, Debug)]
1876#[non_exhaustive]
1877pub struct BoolishValueParser {}
1878
1879impl BoolishValueParser {
1880    /// Parse bool-like string values
1881    pub fn new() -> Self {
1882        Self {}
1883    }
1884
1885    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1886        crate::util::TRUE_LITERALS
1887            .iter()
1888            .chain(crate::util::FALSE_LITERALS.iter())
1889            .copied()
1890            .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false"))
1891    }
1892}
1893
1894impl TypedValueParser for BoolishValueParser {
1895    type Value = bool;
1896
1897    fn parse_ref(
1898        &self,
1899        cmd: &crate::Command,
1900        arg: Option<&crate::Arg>,
1901        value: &std::ffi::OsStr,
1902    ) -> Result<Self::Value, crate::Error> {
1903        let value = ok!(value.to_str().ok_or_else(|| {
1904            crate::Error::invalid_utf8(
1905                cmd,
1906                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1907            )
1908        }));
1909        let value = ok!(crate::util::str_to_bool(value).ok_or_else(|| {
1910            let arg = arg
1911                .map(|a| a.to_string())
1912                .unwrap_or_else(|| "...".to_owned());
1913            crate::Error::value_validation(arg, value.to_owned(), "value was not a boolean".into())
1914                .with_cmd(cmd)
1915        }));
1916        Ok(value)
1917    }
1918
1919    fn possible_values(
1920        &self,
1921    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1922        Some(Box::new(Self::possible_values()))
1923    }
1924}
1925
1926impl Default for BoolishValueParser {
1927    fn default() -> Self {
1928        Self::new()
1929    }
1930}
1931
1932/// Parse non-empty string values
1933///
1934/// See also:
1935/// - [`ValueParser::string`]
1936///
1937/// # Example
1938///
1939/// Usage:
1940/// ```rust
1941/// # use clap_builder as clap;
1942/// let mut cmd = clap::Command::new("raw")
1943///     .arg(
1944///         clap::Arg::new("append")
1945///             .value_parser(clap::builder::NonEmptyStringValueParser::new())
1946///             .required(true)
1947///     );
1948///
1949/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1950/// let port: &String = m.get_one("append")
1951///     .expect("required");
1952/// assert_eq!(port, "true");
1953/// ```
1954///
1955/// Semantics:
1956/// ```rust
1957/// # use clap_builder as clap;
1958/// # use std::ffi::OsStr;
1959/// # use clap::builder::TypedValueParser;
1960/// # let cmd = clap::Command::new("test");
1961/// # let arg = None;
1962/// let value_parser = clap::builder::NonEmptyStringValueParser::new();
1963/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), "random");
1964/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1965/// ```
1966#[derive(Copy, Clone, Debug)]
1967#[non_exhaustive]
1968pub struct NonEmptyStringValueParser {}
1969
1970impl NonEmptyStringValueParser {
1971    /// Parse non-empty string values
1972    pub fn new() -> Self {
1973        Self {}
1974    }
1975}
1976
1977impl TypedValueParser for NonEmptyStringValueParser {
1978    type Value = String;
1979
1980    fn parse_ref(
1981        &self,
1982        cmd: &crate::Command,
1983        arg: Option<&crate::Arg>,
1984        value: &std::ffi::OsStr,
1985    ) -> Result<Self::Value, crate::Error> {
1986        if value.is_empty() {
1987            return Err(crate::Error::empty_value(
1988                cmd,
1989                &[],
1990                arg.map(ToString::to_string)
1991                    .unwrap_or_else(|| "...".to_owned()),
1992            ));
1993        }
1994        let value = ok!(value.to_str().ok_or_else(|| {
1995            crate::Error::invalid_utf8(
1996                cmd,
1997                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1998            )
1999        }));
2000        Ok(value.to_owned())
2001    }
2002}
2003
2004impl Default for NonEmptyStringValueParser {
2005    fn default() -> Self {
2006        Self::new()
2007    }
2008}
2009
2010/// Adapt a `TypedValueParser` from one value to another
2011///
2012/// See [`TypedValueParser::map`]
2013#[derive(Clone, Debug)]
2014pub struct MapValueParser<P, F> {
2015    parser: P,
2016    func: F,
2017}
2018
2019impl<P, F, T> MapValueParser<P, F>
2020where
2021    P: TypedValueParser,
2022    P::Value: Send + Sync + Clone,
2023    F: Fn(P::Value) -> T + Clone,
2024    T: Send + Sync + Clone,
2025{
2026    fn new(parser: P, func: F) -> Self {
2027        Self { parser, func }
2028    }
2029}
2030
2031impl<P, F, T> TypedValueParser for MapValueParser<P, F>
2032where
2033    P: TypedValueParser,
2034    P::Value: Send + Sync + Clone,
2035    F: Fn(P::Value) -> T + Clone + Send + Sync + 'static,
2036    T: Send + Sync + Clone,
2037{
2038    type Value = T;
2039
2040    fn parse_ref(
2041        &self,
2042        cmd: &crate::Command,
2043        arg: Option<&crate::Arg>,
2044        value: &std::ffi::OsStr,
2045    ) -> Result<Self::Value, crate::Error> {
2046        let value = ok!(self.parser.parse_ref(cmd, arg, value));
2047        let value = (self.func)(value);
2048        Ok(value)
2049    }
2050
2051    fn parse(
2052        &self,
2053        cmd: &crate::Command,
2054        arg: Option<&crate::Arg>,
2055        value: std::ffi::OsString,
2056    ) -> Result<Self::Value, crate::Error> {
2057        let value = ok!(self.parser.parse(cmd, arg, value));
2058        let value = (self.func)(value);
2059        Ok(value)
2060    }
2061
2062    fn possible_values(
2063        &self,
2064    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
2065        self.parser.possible_values()
2066    }
2067}
2068
2069/// Adapt a `TypedValueParser` from one value to another
2070///
2071/// See [`TypedValueParser::try_map`]
2072#[derive(Clone, Debug)]
2073pub struct TryMapValueParser<P, F> {
2074    parser: P,
2075    func: F,
2076}
2077
2078impl<P, F, T, E> TryMapValueParser<P, F>
2079where
2080    P: TypedValueParser,
2081    P::Value: Send + Sync + Clone,
2082    F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
2083    T: Send + Sync + Clone,
2084    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2085{
2086    fn new(parser: P, func: F) -> Self {
2087        Self { parser, func }
2088    }
2089}
2090
2091impl<P, F, T, E> TypedValueParser for TryMapValueParser<P, F>
2092where
2093    P: TypedValueParser,
2094    P::Value: Send + Sync + Clone,
2095    F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
2096    T: Send + Sync + Clone,
2097    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2098{
2099    type Value = T;
2100
2101    fn parse_ref(
2102        &self,
2103        cmd: &crate::Command,
2104        arg: Option<&crate::Arg>,
2105        value: &std::ffi::OsStr,
2106    ) -> Result<Self::Value, crate::Error> {
2107        let mid_value = ok!(self.parser.parse_ref(cmd, arg, value));
2108        let value = ok!((self.func)(mid_value).map_err(|e| {
2109            let arg = arg
2110                .map(|a| a.to_string())
2111                .unwrap_or_else(|| "...".to_owned());
2112            crate::Error::value_validation(arg, value.to_string_lossy().into_owned(), e.into())
2113                .with_cmd(cmd)
2114        }));
2115        Ok(value)
2116    }
2117
2118    fn possible_values(
2119        &self,
2120    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
2121        self.parser.possible_values()
2122    }
2123}
2124
2125/// When encountered, report [`ErrorKind::UnknownArgument`][crate::error::ErrorKind::UnknownArgument]
2126///
2127/// Useful to help users migrate, either from old versions or similar tools.
2128///
2129/// # Examples
2130///
2131/// ```rust
2132/// # use clap_builder as clap;
2133/// # use clap::Command;
2134/// # use clap::Arg;
2135/// let cmd = Command::new("mycmd")
2136///     .args([
2137///         Arg::new("current-dir")
2138///             .short('C'),
2139///         Arg::new("current-dir-unknown")
2140///             .long("cwd")
2141///             .aliases(["current-dir", "directory", "working-directory", "root"])
2142///             .value_parser(clap::builder::UnknownArgumentValueParser::suggest_arg("-C"))
2143///             .hide(true),
2144///     ]);
2145///
2146/// // Use a supported version of the argument
2147/// let matches = cmd.clone().try_get_matches_from(["mycmd", "-C", ".."]).unwrap();
2148/// assert!(matches.contains_id("current-dir"));
2149/// assert_eq!(
2150///     matches.get_many::<String>("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
2151///     vec![".."]
2152/// );
2153///
2154/// // Use one of the invalid versions
2155/// let err = cmd.try_get_matches_from(["mycmd", "--cwd", ".."]).unwrap_err();
2156/// assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
2157/// ```
2158#[derive(Clone, Debug)]
2159pub struct UnknownArgumentValueParser {
2160    arg: Option<Str>,
2161    suggestions: Vec<StyledStr>,
2162}
2163
2164impl UnknownArgumentValueParser {
2165    /// Suggest an alternative argument
2166    pub fn suggest_arg(arg: impl Into<Str>) -> Self {
2167        Self {
2168            arg: Some(arg.into()),
2169            suggestions: Default::default(),
2170        }
2171    }
2172
2173    /// Provide a general suggestion
2174    pub fn suggest(text: impl Into<StyledStr>) -> Self {
2175        Self {
2176            arg: Default::default(),
2177            suggestions: vec![text.into()],
2178        }
2179    }
2180
2181    /// Extend the suggestions
2182    pub fn and_suggest(mut self, text: impl Into<StyledStr>) -> Self {
2183        self.suggestions.push(text.into());
2184        self
2185    }
2186}
2187
2188impl TypedValueParser for UnknownArgumentValueParser {
2189    type Value = String;
2190
2191    fn parse_ref(
2192        &self,
2193        cmd: &crate::Command,
2194        arg: Option<&crate::Arg>,
2195        value: &std::ffi::OsStr,
2196    ) -> Result<Self::Value, crate::Error> {
2197        TypedValueParser::parse_ref_(self, cmd, arg, value, ValueSource::CommandLine)
2198    }
2199
2200    fn parse_ref_(
2201        &self,
2202        cmd: &crate::Command,
2203        arg: Option<&crate::Arg>,
2204        _value: &std::ffi::OsStr,
2205        source: ValueSource,
2206    ) -> Result<Self::Value, crate::Error> {
2207        match source {
2208            ValueSource::DefaultValue => {
2209                TypedValueParser::parse_ref_(&StringValueParser::new(), cmd, arg, _value, source)
2210            }
2211            ValueSource::EnvVariable | ValueSource::CommandLine => {
2212                let arg = match arg {
2213                    Some(arg) => arg.to_string(),
2214                    None => "..".to_owned(),
2215                };
2216                let err = crate::Error::unknown_argument(
2217                    cmd,
2218                    arg,
2219                    self.arg.as_ref().map(|s| (s.as_str().to_owned(), None)),
2220                    false,
2221                    crate::output::Usage::new(cmd).create_usage_with_title(&[]),
2222                );
2223                #[cfg(feature = "error-context")]
2224                let err = {
2225                    debug_assert_eq!(
2226                        err.get(crate::error::ContextKind::Suggested),
2227                        None,
2228                        "Assuming `Error::unknown_argument` doesn't apply any `Suggested` so we can without caution"
2229                    );
2230                    err.insert_context_unchecked(
2231                        crate::error::ContextKind::Suggested,
2232                        crate::error::ContextValue::StyledStrs(self.suggestions.clone()),
2233                    )
2234                };
2235                Err(err)
2236            }
2237        }
2238    }
2239}
2240
2241/// Register a type with [`value_parser!`][crate::value_parser!]
2242///
2243/// # Example
2244///
2245/// ```rust
2246/// # use clap_builder as clap;
2247/// #[derive(Copy, Clone, Debug)]
2248/// pub struct Custom(u32);
2249///
2250/// impl clap::builder::ValueParserFactory for Custom {
2251///     type Parser = CustomValueParser;
2252///     fn value_parser() -> Self::Parser {
2253///         CustomValueParser
2254///     }
2255/// }
2256///
2257/// #[derive(Clone, Debug)]
2258/// pub struct CustomValueParser;
2259/// impl clap::builder::TypedValueParser for CustomValueParser {
2260///     type Value = Custom;
2261///
2262///     fn parse_ref(
2263///         &self,
2264///         cmd: &clap::Command,
2265///         arg: Option<&clap::Arg>,
2266///         value: &std::ffi::OsStr,
2267///     ) -> Result<Self::Value, clap::Error> {
2268///         let inner = clap::value_parser!(u32);
2269///         let val = inner.parse_ref(cmd, arg, value)?;
2270///         Ok(Custom(val))
2271///     }
2272/// }
2273///
2274/// let parser: CustomValueParser = clap::value_parser!(Custom);
2275/// ```
2276pub trait ValueParserFactory {
2277    /// Generated parser, usually [`ValueParser`].
2278    ///
2279    /// It should at least be a type that supports `Into<ValueParser>`.  A non-`ValueParser` type
2280    /// allows the caller to do further initialization on the parser.
2281    type Parser;
2282
2283    /// Create the specified [`Self::Parser`]
2284    fn value_parser() -> Self::Parser;
2285}
2286impl ValueParserFactory for String {
2287    type Parser = ValueParser;
2288    fn value_parser() -> Self::Parser {
2289        ValueParser::string() // Default `clap_derive` to optimized implementation
2290    }
2291}
2292impl ValueParserFactory for Box<str> {
2293    type Parser = MapValueParser<StringValueParser, fn(String) -> Box<str>>;
2294    fn value_parser() -> Self::Parser {
2295        StringValueParser::new().map(String::into_boxed_str)
2296    }
2297}
2298impl ValueParserFactory for std::ffi::OsString {
2299    type Parser = ValueParser;
2300    fn value_parser() -> Self::Parser {
2301        ValueParser::os_string() // Default `clap_derive` to optimized implementation
2302    }
2303}
2304impl ValueParserFactory for Box<std::ffi::OsStr> {
2305    type Parser =
2306        MapValueParser<OsStringValueParser, fn(std::ffi::OsString) -> Box<std::ffi::OsStr>>;
2307    fn value_parser() -> Self::Parser {
2308        OsStringValueParser::new().map(std::ffi::OsString::into_boxed_os_str)
2309    }
2310}
2311impl ValueParserFactory for std::path::PathBuf {
2312    type Parser = ValueParser;
2313    fn value_parser() -> Self::Parser {
2314        ValueParser::path_buf() // Default `clap_derive` to optimized implementation
2315    }
2316}
2317impl ValueParserFactory for Box<std::path::Path> {
2318    type Parser =
2319        MapValueParser<PathBufValueParser, fn(std::path::PathBuf) -> Box<std::path::Path>>;
2320    fn value_parser() -> Self::Parser {
2321        PathBufValueParser::new().map(std::path::PathBuf::into_boxed_path)
2322    }
2323}
2324impl ValueParserFactory for bool {
2325    type Parser = ValueParser;
2326    fn value_parser() -> Self::Parser {
2327        ValueParser::bool() // Default `clap_derive` to optimized implementation
2328    }
2329}
2330impl ValueParserFactory for u8 {
2331    type Parser = RangedI64ValueParser<u8>;
2332    fn value_parser() -> Self::Parser {
2333        let start: i64 = u8::MIN.into();
2334        let end: i64 = u8::MAX.into();
2335        RangedI64ValueParser::new().range(start..=end)
2336    }
2337}
2338impl ValueParserFactory for i8 {
2339    type Parser = RangedI64ValueParser<i8>;
2340    fn value_parser() -> Self::Parser {
2341        let start: i64 = i8::MIN.into();
2342        let end: i64 = i8::MAX.into();
2343        RangedI64ValueParser::new().range(start..=end)
2344    }
2345}
2346impl ValueParserFactory for u16 {
2347    type Parser = RangedI64ValueParser<u16>;
2348    fn value_parser() -> Self::Parser {
2349        let start: i64 = u16::MIN.into();
2350        let end: i64 = u16::MAX.into();
2351        RangedI64ValueParser::new().range(start..=end)
2352    }
2353}
2354impl ValueParserFactory for i16 {
2355    type Parser = RangedI64ValueParser<i16>;
2356    fn value_parser() -> Self::Parser {
2357        let start: i64 = i16::MIN.into();
2358        let end: i64 = i16::MAX.into();
2359        RangedI64ValueParser::new().range(start..=end)
2360    }
2361}
2362impl ValueParserFactory for u32 {
2363    type Parser = RangedI64ValueParser<u32>;
2364    fn value_parser() -> Self::Parser {
2365        let start: i64 = u32::MIN.into();
2366        let end: i64 = u32::MAX.into();
2367        RangedI64ValueParser::new().range(start..=end)
2368    }
2369}
2370impl ValueParserFactory for i32 {
2371    type Parser = RangedI64ValueParser<i32>;
2372    fn value_parser() -> Self::Parser {
2373        let start: i64 = i32::MIN.into();
2374        let end: i64 = i32::MAX.into();
2375        RangedI64ValueParser::new().range(start..=end)
2376    }
2377}
2378impl ValueParserFactory for u64 {
2379    type Parser = RangedU64ValueParser<u64>;
2380    fn value_parser() -> Self::Parser {
2381        RangedU64ValueParser::new()
2382    }
2383}
2384impl ValueParserFactory for i64 {
2385    type Parser = RangedI64ValueParser<i64>;
2386    fn value_parser() -> Self::Parser {
2387        RangedI64ValueParser::new()
2388    }
2389}
2390impl<T> ValueParserFactory for std::num::Saturating<T>
2391where
2392    T: ValueParserFactory,
2393    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2394    T: Send + Sync + Clone,
2395{
2396    type Parser =
2397        MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::num::Saturating<T>>;
2398    fn value_parser() -> Self::Parser {
2399        T::value_parser().map(std::num::Saturating)
2400    }
2401}
2402impl<T> ValueParserFactory for std::num::Wrapping<T>
2403where
2404    T: ValueParserFactory,
2405    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2406    T: Send + Sync + Clone,
2407{
2408    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::num::Wrapping<T>>;
2409    fn value_parser() -> Self::Parser {
2410        T::value_parser().map(std::num::Wrapping)
2411    }
2412}
2413impl<T> ValueParserFactory for Box<T>
2414where
2415    T: ValueParserFactory,
2416    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2417    T: Send + Sync + Clone,
2418{
2419    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> Box<T>>;
2420    fn value_parser() -> Self::Parser {
2421        T::value_parser().map(Box::new)
2422    }
2423}
2424impl<T> ValueParserFactory for std::sync::Arc<T>
2425where
2426    T: ValueParserFactory,
2427    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2428    T: Send + Sync + Clone,
2429{
2430    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::sync::Arc<T>>;
2431    fn value_parser() -> Self::Parser {
2432        T::value_parser().map(std::sync::Arc::new)
2433    }
2434}
2435
2436#[doc(hidden)]
2437#[derive(Debug)]
2438#[allow(non_camel_case_types)]
2439pub struct _infer_ValueParser_for<T>(std::marker::PhantomData<T>);
2440
2441impl<T> _infer_ValueParser_for<T> {
2442    #[doc(hidden)]
2443    #[allow(clippy::new_without_default)]
2444    pub fn new() -> Self {
2445        Self(Default::default())
2446    }
2447}
2448
2449/// Unstable [`ValueParser`]
2450///
2451/// Implementation may change to more specific instance in the future
2452#[doc(hidden)]
2453#[derive(Debug)]
2454pub struct _AnonymousValueParser(ValueParser);
2455
2456#[doc(hidden)]
2457pub mod impl_prelude {
2458    use super::*;
2459
2460    #[doc(hidden)]
2461    #[allow(non_camel_case_types)]
2462    pub trait _impls_ValueParserFactory: private::_impls_ValueParserFactorySealed {
2463        type Parser;
2464        fn value_parser(&self) -> Self::Parser;
2465    }
2466    impl<P: ValueParserFactory> _impls_ValueParserFactory for &&&&&&_infer_ValueParser_for<P> {
2467        type Parser = P::Parser;
2468        fn value_parser(&self) -> Self::Parser {
2469            P::value_parser()
2470        }
2471    }
2472
2473    #[doc(hidden)]
2474    #[allow(non_camel_case_types)]
2475    pub trait _impls_ValueEnum: private::_impls_ValueEnumSealed {
2476        type Output;
2477
2478        fn value_parser(&self) -> Self::Output;
2479    }
2480    impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> _impls_ValueEnum
2481        for &&&&&_infer_ValueParser_for<E>
2482    {
2483        type Output = EnumValueParser<E>;
2484
2485        fn value_parser(&self) -> Self::Output {
2486            EnumValueParser::<E>::new()
2487        }
2488    }
2489
2490    #[doc(hidden)]
2491    #[allow(non_camel_case_types)]
2492    pub trait _impls_From_OsString: private::_impls_From_OsStringSealed {
2493        fn value_parser(&self) -> _AnonymousValueParser;
2494    }
2495    impl<FromOsString> _impls_From_OsString for &&&&_infer_ValueParser_for<FromOsString>
2496    where
2497        FromOsString: From<std::ffi::OsString> + std::any::Any + Clone + Send + Sync + 'static,
2498    {
2499        fn value_parser(&self) -> _AnonymousValueParser {
2500            _AnonymousValueParser(
2501                OsStringValueParser::new()
2502                    .map(|s| FromOsString::from(s))
2503                    .into(),
2504            )
2505        }
2506    }
2507
2508    #[doc(hidden)]
2509    #[allow(non_camel_case_types)]
2510    pub trait _impls_From_OsStr: private::_impls_From_OsStrSealed {
2511        fn value_parser(&self) -> _AnonymousValueParser;
2512    }
2513    impl<FromOsStr> _impls_From_OsStr for &&&_infer_ValueParser_for<FromOsStr>
2514    where
2515        FromOsStr:
2516            for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Clone + Send + Sync + 'static,
2517    {
2518        fn value_parser(&self) -> _AnonymousValueParser {
2519            _AnonymousValueParser(
2520                OsStringValueParser::new()
2521                    .map(|s| FromOsStr::from(&s))
2522                    .into(),
2523            )
2524        }
2525    }
2526
2527    #[doc(hidden)]
2528    #[allow(non_camel_case_types)]
2529    pub trait _impls_From_String: private::_impls_From_StringSealed {
2530        fn value_parser(&self) -> _AnonymousValueParser;
2531    }
2532    impl<FromString> _impls_From_String for &&_infer_ValueParser_for<FromString>
2533    where
2534        FromString: From<String> + std::any::Any + Clone + Send + Sync + 'static,
2535    {
2536        fn value_parser(&self) -> _AnonymousValueParser {
2537            _AnonymousValueParser(StringValueParser::new().map(|s| FromString::from(s)).into())
2538        }
2539    }
2540
2541    #[doc(hidden)]
2542    #[allow(non_camel_case_types)]
2543    pub trait _impls_From_str: private::_impls_From_strSealed {
2544        fn value_parser(&self) -> _AnonymousValueParser;
2545    }
2546    impl<FromStr> _impls_From_str for &_infer_ValueParser_for<FromStr>
2547    where
2548        FromStr: for<'s> From<&'s str> + std::any::Any + Clone + Send + Sync + 'static,
2549    {
2550        fn value_parser(&self) -> _AnonymousValueParser {
2551            _AnonymousValueParser(StringValueParser::new().map(|s| FromStr::from(&s)).into())
2552        }
2553    }
2554
2555    #[doc(hidden)]
2556    #[allow(non_camel_case_types)]
2557    pub trait _impls_FromStr: private::_impls_FromStrSealed {
2558        fn value_parser(&self) -> _AnonymousValueParser;
2559    }
2560    impl<Parse> _impls_FromStr for _infer_ValueParser_for<Parse>
2561    where
2562        Parse: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static,
2563        <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2564    {
2565        fn value_parser(&self) -> _AnonymousValueParser {
2566            let func: fn(&str) -> Result<Parse, <Parse as std::str::FromStr>::Err> =
2567                Parse::from_str;
2568            _AnonymousValueParser(ValueParser::new(func))
2569        }
2570    }
2571}
2572
2573/// Select a [`ValueParser`] implementation from the intended type
2574///
2575/// Supported types
2576/// - [`ValueParserFactory` types][ValueParserFactory], including
2577///   - [Native types][ValueParser]: `bool`, `String`, `OsString`, `PathBuf`
2578///   - [Ranged numeric types][RangedI64ValueParser]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`
2579/// - [`ValueEnum` types][crate::ValueEnum]
2580/// - [`From<OsString>` types][std::convert::From] and [`From<&OsStr>` types][std::convert::From]
2581/// - [`From<String>` types][std::convert::From] and [`From<&str>` types][std::convert::From]
2582/// - [`FromStr` types][std::str::FromStr], including usize, isize
2583///
2584/// # Example
2585///
2586/// Usage:
2587/// ```rust
2588/// # use clap_builder as clap;
2589/// # use std::path::PathBuf;
2590/// # use std::path::Path;
2591/// let mut cmd = clap::Command::new("raw")
2592///     .arg(
2593///         clap::Arg::new("output")
2594///             .value_parser(clap::value_parser!(PathBuf))
2595///             .required(true)
2596///     );
2597///
2598/// let m = cmd.try_get_matches_from_mut(["cmd", "file.txt"]).unwrap();
2599/// let port: &PathBuf = m.get_one("output")
2600///     .expect("required");
2601/// assert_eq!(port, Path::new("file.txt"));
2602/// ```
2603///
2604/// Example mappings:
2605/// ```rust
2606/// # use clap_builder as clap;
2607/// # use clap::ColorChoice;
2608/// // Built-in types
2609/// let parser = clap::value_parser!(String);
2610/// assert_eq!(format!("{parser:?}"), "ValueParser::string");
2611/// let parser = clap::value_parser!(std::ffi::OsString);
2612/// assert_eq!(format!("{parser:?}"), "ValueParser::os_string");
2613/// let parser = clap::value_parser!(std::path::PathBuf);
2614/// assert_eq!(format!("{parser:?}"), "ValueParser::path_buf");
2615/// clap::value_parser!(u16).range(3000..);
2616/// clap::value_parser!(u64).range(3000..);
2617///
2618/// // FromStr types
2619/// let parser = clap::value_parser!(usize);
2620/// assert_eq!(format!("{parser:?}"), "_AnonymousValueParser(ValueParser::other(usize))");
2621///
2622/// // ValueEnum types
2623/// clap::value_parser!(ColorChoice);
2624/// ```
2625#[macro_export]
2626macro_rules! value_parser {
2627    ($name:ty) => {{
2628        use $crate::builder::impl_prelude::*;
2629        let auto = $crate::builder::_infer_ValueParser_for::<$name>::new();
2630        (&&&&&&auto).value_parser()
2631    }};
2632}
2633
2634mod private {
2635    use super::*;
2636
2637    #[allow(non_camel_case_types)]
2638    pub trait _impls_ValueParserFactorySealed {}
2639    impl<P: ValueParserFactory> _impls_ValueParserFactorySealed for &&&&&&_infer_ValueParser_for<P> {}
2640
2641    #[allow(non_camel_case_types)]
2642    pub trait _impls_ValueEnumSealed {}
2643    impl<E: crate::ValueEnum> _impls_ValueEnumSealed for &&&&&_infer_ValueParser_for<E> {}
2644
2645    #[allow(non_camel_case_types)]
2646    pub trait _impls_From_OsStringSealed {}
2647    impl<FromOsString> _impls_From_OsStringSealed for &&&&_infer_ValueParser_for<FromOsString> where
2648        FromOsString: From<std::ffi::OsString> + std::any::Any + Send + Sync + 'static
2649    {
2650    }
2651
2652    #[allow(non_camel_case_types)]
2653    pub trait _impls_From_OsStrSealed {}
2654    impl<FromOsStr> _impls_From_OsStrSealed for &&&_infer_ValueParser_for<FromOsStr> where
2655        FromOsStr: for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Send + Sync + 'static
2656    {
2657    }
2658
2659    #[allow(non_camel_case_types)]
2660    pub trait _impls_From_StringSealed {}
2661    impl<FromString> _impls_From_StringSealed for &&_infer_ValueParser_for<FromString> where
2662        FromString: From<String> + std::any::Any + Send + Sync + 'static
2663    {
2664    }
2665
2666    #[allow(non_camel_case_types)]
2667    pub trait _impls_From_strSealed {}
2668    impl<FromStr> _impls_From_strSealed for &_infer_ValueParser_for<FromStr> where
2669        FromStr: for<'s> From<&'s str> + std::any::Any + Send + Sync + 'static
2670    {
2671    }
2672
2673    #[allow(non_camel_case_types)]
2674    pub trait _impls_FromStrSealed {}
2675    impl<Parse> _impls_FromStrSealed for _infer_ValueParser_for<Parse>
2676    where
2677        Parse: std::str::FromStr + std::any::Any + Send + Sync + 'static,
2678        <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2679    {
2680    }
2681}
2682
2683#[cfg(test)]
2684mod test {
2685    use super::*;
2686
2687    #[test]
2688    fn ensure_typed_applies_to_parse() {
2689        fn parse(_: &str) -> Result<usize, std::io::Error> {
2690            Ok(10)
2691        }
2692        let cmd = crate::Command::new("cmd");
2693        let arg = None;
2694        assert_eq!(
2695            TypedValueParser::parse_ref(&parse, &cmd, arg, std::ffi::OsStr::new("foo")).unwrap(),
2696            10
2697        );
2698    }
2699}