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/// **NOTE:** To capture negative values, you will also need to set
1271/// [`Arg::allow_negative_numbers`][crate::Arg::allow_negative_numbers] or
1272/// [`Arg::allow_hyphen_values`][crate::Arg::allow_hyphen_values].
1273///
1274/// # Example
1275///
1276/// Usage:
1277/// ```rust
1278/// # use clap_builder as clap;
1279/// let mut cmd = clap::Command::new("raw")
1280///     .arg(
1281///         clap::Arg::new("port")
1282///             .long("port")
1283///             .value_parser(clap::value_parser!(u16).range(3000..))
1284///             .action(clap::ArgAction::Set)
1285///             .required(true)
1286///     );
1287///
1288/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
1289/// let port: u16 = *m.get_one("port")
1290///     .expect("required");
1291/// assert_eq!(port, 3001);
1292/// ```
1293///
1294/// Semantics:
1295/// ```rust
1296/// # use clap_builder as clap;
1297/// # use std::ffi::OsStr;
1298/// # use clap::builder::TypedValueParser;
1299/// # let cmd = clap::Command::new("test");
1300/// # let arg = None;
1301/// let value_parser = clap::builder::RangedI64ValueParser::<i32>::new().range(-1..200);
1302/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1303/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1304/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err());
1305/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err());
1306/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).unwrap(), -1);
1307/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0);
1308/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
1309/// ```
1310#[derive(Copy, Clone, Debug)]
1311pub struct RangedI64ValueParser<T: TryFrom<i64> + Clone + Send + Sync = i64> {
1312    bounds: (std::ops::Bound<i64>, std::ops::Bound<i64>),
1313    target: std::marker::PhantomData<T>,
1314}
1315
1316impl<T: TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> {
1317    /// Select full range of `i64`
1318    pub fn new() -> Self {
1319        Self::from(..)
1320    }
1321
1322    /// Narrow the supported range
1323    pub fn range<B: RangeBounds<i64>>(mut self, range: B) -> Self {
1324        // Consideration: when the user does `value_parser!(u8).range()`
1325        // - Avoid programming mistakes by accidentally expanding the range
1326        // - Make it convenient to limit the range like with `..10`
1327        let start = match range.start_bound() {
1328            l @ std::ops::Bound::Included(i) => {
1329                debug_assert!(
1330                    self.bounds.contains(i),
1331                    "{} must be in {:?}",
1332                    i,
1333                    self.bounds
1334                );
1335                l.cloned()
1336            }
1337            l @ std::ops::Bound::Excluded(i) => {
1338                debug_assert!(
1339                    self.bounds.contains(&i.saturating_add(1)),
1340                    "{} must be in {:?}",
1341                    i,
1342                    self.bounds
1343                );
1344                l.cloned()
1345            }
1346            std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(),
1347        };
1348        let end = match range.end_bound() {
1349            l @ std::ops::Bound::Included(i) => {
1350                debug_assert!(
1351                    self.bounds.contains(i),
1352                    "{} must be in {:?}",
1353                    i,
1354                    self.bounds
1355                );
1356                l.cloned()
1357            }
1358            l @ std::ops::Bound::Excluded(i) => {
1359                debug_assert!(
1360                    self.bounds.contains(&i.saturating_sub(1)),
1361                    "{} must be in {:?}",
1362                    i,
1363                    self.bounds
1364                );
1365                l.cloned()
1366            }
1367            std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(),
1368        };
1369        self.bounds = (start, end);
1370        self
1371    }
1372
1373    fn format_bounds(&self) -> String {
1374        let mut result = match self.bounds.0 {
1375            std::ops::Bound::Included(i) => i.to_string(),
1376            std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(),
1377            std::ops::Bound::Unbounded => i64::MIN.to_string(),
1378        };
1379        result.push_str("..");
1380        match self.bounds.1 {
1381            std::ops::Bound::Included(i) => {
1382                result.push('=');
1383                result.push_str(&i.to_string());
1384            }
1385            std::ops::Bound::Excluded(i) => {
1386                result.push_str(&i.to_string());
1387            }
1388            std::ops::Bound::Unbounded => {
1389                result.push_str(&i64::MAX.to_string());
1390            }
1391        }
1392        result
1393    }
1394}
1395
1396impl<T: TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser for RangedI64ValueParser<T>
1397where
1398    <T as TryFrom<i64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
1399{
1400    type Value = T;
1401
1402    fn parse_ref(
1403        &self,
1404        cmd: &crate::Command,
1405        arg: Option<&crate::Arg>,
1406        raw_value: &std::ffi::OsStr,
1407    ) -> Result<Self::Value, crate::Error> {
1408        let value = ok!(raw_value.to_str().ok_or_else(|| {
1409            crate::Error::invalid_utf8(
1410                cmd,
1411                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1412            )
1413        }));
1414        let value = ok!(value.parse::<i64>().map_err(|err| {
1415            let arg = arg
1416                .map(|a| a.to_string())
1417                .unwrap_or_else(|| "...".to_owned());
1418            crate::Error::value_validation(
1419                arg,
1420                raw_value.to_string_lossy().into_owned(),
1421                err.into(),
1422            )
1423            .with_cmd(cmd)
1424        }));
1425        if !self.bounds.contains(&value) {
1426            let arg = arg
1427                .map(|a| a.to_string())
1428                .unwrap_or_else(|| "...".to_owned());
1429            return Err(crate::Error::value_validation(
1430                arg,
1431                raw_value.to_string_lossy().into_owned(),
1432                format!("{} is not in {}", value, self.format_bounds()).into(),
1433            )
1434            .with_cmd(cmd));
1435        }
1436
1437        let value: Result<Self::Value, _> = value.try_into();
1438        let value = ok!(value.map_err(|err| {
1439            let arg = arg
1440                .map(|a| a.to_string())
1441                .unwrap_or_else(|| "...".to_owned());
1442            crate::Error::value_validation(
1443                arg,
1444                raw_value.to_string_lossy().into_owned(),
1445                err.into(),
1446            )
1447            .with_cmd(cmd)
1448        }));
1449
1450        Ok(value)
1451    }
1452}
1453
1454impl<T: TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B>
1455    for RangedI64ValueParser<T>
1456{
1457    fn from(range: B) -> Self {
1458        Self {
1459            bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
1460            target: Default::default(),
1461        }
1462    }
1463}
1464
1465impl<T: TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> {
1466    fn default() -> Self {
1467        Self::new()
1468    }
1469}
1470
1471/// Parse number that fall within a range of values
1472///
1473/// # Example
1474///
1475/// Usage:
1476/// ```rust
1477/// # use clap_builder as clap;
1478/// let mut cmd = clap::Command::new("raw")
1479///     .arg(
1480///         clap::Arg::new("port")
1481///             .long("port")
1482///             .value_parser(clap::value_parser!(u64).range(3000..))
1483///             .action(clap::ArgAction::Set)
1484///             .required(true)
1485///     );
1486///
1487/// let m = cmd.try_get_matches_from_mut(["cmd", "--port", "3001"]).unwrap();
1488/// let port: u64 = *m.get_one("port")
1489///     .expect("required");
1490/// assert_eq!(port, 3001);
1491/// ```
1492///
1493/// Semantics:
1494/// ```rust
1495/// # use clap_builder as clap;
1496/// # use std::ffi::OsStr;
1497/// # use clap::builder::TypedValueParser;
1498/// # let cmd = clap::Command::new("test");
1499/// # let arg = None;
1500/// let value_parser = clap::builder::RangedU64ValueParser::<u32>::new().range(0..200);
1501/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1502/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1503/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-200")).is_err());
1504/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("300")).is_err());
1505/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("-1")).is_err());
1506/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), 0);
1507/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("50")).unwrap(), 50);
1508/// ```
1509#[derive(Copy, Clone, Debug)]
1510pub struct RangedU64ValueParser<T: TryFrom<u64> = u64> {
1511    bounds: (std::ops::Bound<u64>, std::ops::Bound<u64>),
1512    target: std::marker::PhantomData<T>,
1513}
1514
1515impl<T: TryFrom<u64>> RangedU64ValueParser<T> {
1516    /// Select full range of `u64`
1517    pub fn new() -> Self {
1518        Self::from(..)
1519    }
1520
1521    /// Narrow the supported range
1522    pub fn range<B: RangeBounds<u64>>(mut self, range: B) -> Self {
1523        // Consideration: when the user does `value_parser!(u8).range()`
1524        // - Avoid programming mistakes by accidentally expanding the range
1525        // - Make it convenient to limit the range like with `..10`
1526        let start = match range.start_bound() {
1527            l @ std::ops::Bound::Included(i) => {
1528                debug_assert!(
1529                    self.bounds.contains(i),
1530                    "{} must be in {:?}",
1531                    i,
1532                    self.bounds
1533                );
1534                l.cloned()
1535            }
1536            l @ std::ops::Bound::Excluded(i) => {
1537                debug_assert!(
1538                    self.bounds.contains(&i.saturating_add(1)),
1539                    "{} must be in {:?}",
1540                    i,
1541                    self.bounds
1542                );
1543                l.cloned()
1544            }
1545            std::ops::Bound::Unbounded => self.bounds.start_bound().cloned(),
1546        };
1547        let end = match range.end_bound() {
1548            l @ std::ops::Bound::Included(i) => {
1549                debug_assert!(
1550                    self.bounds.contains(i),
1551                    "{} must be in {:?}",
1552                    i,
1553                    self.bounds
1554                );
1555                l.cloned()
1556            }
1557            l @ std::ops::Bound::Excluded(i) => {
1558                debug_assert!(
1559                    self.bounds.contains(&i.saturating_sub(1)),
1560                    "{} must be in {:?}",
1561                    i,
1562                    self.bounds
1563                );
1564                l.cloned()
1565            }
1566            std::ops::Bound::Unbounded => self.bounds.end_bound().cloned(),
1567        };
1568        self.bounds = (start, end);
1569        self
1570    }
1571
1572    fn format_bounds(&self) -> String {
1573        let mut result = match self.bounds.0 {
1574            std::ops::Bound::Included(i) => i.to_string(),
1575            std::ops::Bound::Excluded(i) => i.saturating_add(1).to_string(),
1576            std::ops::Bound::Unbounded => u64::MIN.to_string(),
1577        };
1578        result.push_str("..");
1579        match self.bounds.1 {
1580            std::ops::Bound::Included(i) => {
1581                result.push('=');
1582                result.push_str(&i.to_string());
1583            }
1584            std::ops::Bound::Excluded(i) => {
1585                result.push_str(&i.to_string());
1586            }
1587            std::ops::Bound::Unbounded => {
1588                result.push_str(&u64::MAX.to_string());
1589            }
1590        }
1591        result
1592    }
1593}
1594
1595impl<T: TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser for RangedU64ValueParser<T>
1596where
1597    <T as TryFrom<u64>>::Error: Send + Sync + 'static + std::error::Error + ToString,
1598{
1599    type Value = T;
1600
1601    fn parse_ref(
1602        &self,
1603        cmd: &crate::Command,
1604        arg: Option<&crate::Arg>,
1605        raw_value: &std::ffi::OsStr,
1606    ) -> Result<Self::Value, crate::Error> {
1607        let value = ok!(raw_value.to_str().ok_or_else(|| {
1608            crate::Error::invalid_utf8(
1609                cmd,
1610                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1611            )
1612        }));
1613        let value = ok!(value.parse::<u64>().map_err(|err| {
1614            let arg = arg
1615                .map(|a| a.to_string())
1616                .unwrap_or_else(|| "...".to_owned());
1617            crate::Error::value_validation(
1618                arg,
1619                raw_value.to_string_lossy().into_owned(),
1620                err.into(),
1621            )
1622            .with_cmd(cmd)
1623        }));
1624        if !self.bounds.contains(&value) {
1625            let arg = arg
1626                .map(|a| a.to_string())
1627                .unwrap_or_else(|| "...".to_owned());
1628            return Err(crate::Error::value_validation(
1629                arg,
1630                raw_value.to_string_lossy().into_owned(),
1631                format!("{} is not in {}", value, self.format_bounds()).into(),
1632            )
1633            .with_cmd(cmd));
1634        }
1635
1636        let value: Result<Self::Value, _> = value.try_into();
1637        let value = ok!(value.map_err(|err| {
1638            let arg = arg
1639                .map(|a| a.to_string())
1640                .unwrap_or_else(|| "...".to_owned());
1641            crate::Error::value_validation(
1642                arg,
1643                raw_value.to_string_lossy().into_owned(),
1644                err.into(),
1645            )
1646            .with_cmd(cmd)
1647        }));
1648
1649        Ok(value)
1650    }
1651}
1652
1653impl<T: TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> {
1654    fn from(range: B) -> Self {
1655        Self {
1656            bounds: (range.start_bound().cloned(), range.end_bound().cloned()),
1657            target: Default::default(),
1658        }
1659    }
1660}
1661
1662impl<T: TryFrom<u64>> Default for RangedU64ValueParser<T> {
1663    fn default() -> Self {
1664        Self::new()
1665    }
1666}
1667
1668/// Implementation for [`ValueParser::bool`]
1669///
1670/// Useful for composing new [`TypedValueParser`]s
1671#[derive(Copy, Clone, Debug)]
1672#[non_exhaustive]
1673pub struct BoolValueParser {}
1674
1675impl BoolValueParser {
1676    /// Implementation for [`ValueParser::bool`]
1677    pub fn new() -> Self {
1678        Self {}
1679    }
1680
1681    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1682        ["true", "false"]
1683            .iter()
1684            .copied()
1685            .map(crate::builder::PossibleValue::new)
1686    }
1687}
1688
1689impl TypedValueParser for BoolValueParser {
1690    type Value = bool;
1691
1692    fn parse_ref(
1693        &self,
1694        cmd: &crate::Command,
1695        arg: Option<&crate::Arg>,
1696        value: &std::ffi::OsStr,
1697    ) -> Result<Self::Value, crate::Error> {
1698        let value = if value == std::ffi::OsStr::new("true") {
1699            true
1700        } else if value == std::ffi::OsStr::new("false") {
1701            false
1702        } else {
1703            // Intentionally showing hidden as we hide all of them
1704            let possible_vals = Self::possible_values()
1705                .map(|v| v.get_name().to_owned())
1706                .collect::<Vec<_>>();
1707
1708            return Err(crate::Error::invalid_value(
1709                cmd,
1710                value.to_string_lossy().into_owned(),
1711                &possible_vals,
1712                arg.map(ToString::to_string)
1713                    .unwrap_or_else(|| "...".to_owned()),
1714            ));
1715        };
1716        Ok(value)
1717    }
1718
1719    fn possible_values(
1720        &self,
1721    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1722        Some(Box::new(Self::possible_values()))
1723    }
1724}
1725
1726impl Default for BoolValueParser {
1727    fn default() -> Self {
1728        Self::new()
1729    }
1730}
1731
1732/// Parse false-like string values, everything else is `true`
1733///
1734/// See also:
1735/// - [`ValueParser::bool`] for assuming non-false is true
1736/// - [`BoolishValueParser`] for different human readable bool representations
1737///
1738/// # Example
1739///
1740/// Usage:
1741/// ```rust
1742/// # use clap_builder as clap;
1743/// let mut cmd = clap::Command::new("raw")
1744///     .arg(
1745///         clap::Arg::new("append")
1746///             .value_parser(clap::builder::FalseyValueParser::new())
1747///             .required(true)
1748///     );
1749///
1750/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1751/// let port: bool = *m.get_one("append")
1752///     .expect("required");
1753/// assert_eq!(port, true);
1754/// ```
1755///
1756/// Semantics:
1757/// ```rust
1758/// # use clap_builder as clap;
1759/// # use std::ffi::OsStr;
1760/// # use clap::builder::TypedValueParser;
1761/// # let cmd = clap::Command::new("test");
1762/// # let arg = None;
1763/// let value_parser = clap::builder::FalseyValueParser::new();
1764/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), true);
1765/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).unwrap(), true);
1766/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).unwrap(), false);
1767/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false);
1768/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false);
1769/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false);
1770/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false);
1771/// ```
1772#[derive(Copy, Clone, Debug)]
1773#[non_exhaustive]
1774pub struct FalseyValueParser {}
1775
1776impl FalseyValueParser {
1777    /// Parse false-like string values, everything else is `true`
1778    pub fn new() -> Self {
1779        Self {}
1780    }
1781
1782    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1783        crate::util::TRUE_LITERALS
1784            .iter()
1785            .chain(crate::util::FALSE_LITERALS.iter())
1786            .copied()
1787            .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false"))
1788    }
1789}
1790
1791impl TypedValueParser for FalseyValueParser {
1792    type Value = bool;
1793
1794    fn parse_ref(
1795        &self,
1796        cmd: &crate::Command,
1797        _arg: Option<&crate::Arg>,
1798        value: &std::ffi::OsStr,
1799    ) -> Result<Self::Value, crate::Error> {
1800        let value = ok!(value.to_str().ok_or_else(|| {
1801            crate::Error::invalid_utf8(
1802                cmd,
1803                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1804            )
1805        }));
1806        let value = if value.is_empty() {
1807            false
1808        } else {
1809            crate::util::str_to_bool(value).unwrap_or(true)
1810        };
1811        Ok(value)
1812    }
1813
1814    fn possible_values(
1815        &self,
1816    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1817        Some(Box::new(Self::possible_values()))
1818    }
1819}
1820
1821impl Default for FalseyValueParser {
1822    fn default() -> Self {
1823        Self::new()
1824    }
1825}
1826
1827/// Parse bool-like string values, everything else is `true`
1828///
1829/// See also:
1830/// - [`ValueParser::bool`] for different human readable bool representations
1831/// - [`FalseyValueParser`] for assuming non-false is true
1832///
1833/// # Example
1834///
1835/// Usage:
1836/// ```rust
1837/// # use clap_builder as clap;
1838/// let mut cmd = clap::Command::new("raw")
1839///     .arg(
1840///         clap::Arg::new("append")
1841///             .value_parser(clap::builder::BoolishValueParser::new())
1842///             .required(true)
1843///     );
1844///
1845/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1846/// let port: bool = *m.get_one("append")
1847///     .expect("required");
1848/// assert_eq!(port, true);
1849/// ```
1850///
1851/// Semantics:
1852/// ```rust
1853/// # use clap_builder as clap;
1854/// # use std::ffi::OsStr;
1855/// # use clap::builder::TypedValueParser;
1856/// # let cmd = clap::Command::new("test");
1857/// # let arg = None;
1858/// let value_parser = clap::builder::BoolishValueParser::new();
1859/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).is_err());
1860/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1861/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("100")).is_err());
1862/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("true")).unwrap(), true);
1863/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("Yes")).unwrap(), true);
1864/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oN")).unwrap(), true);
1865/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("1")).unwrap(), true);
1866/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("false")).unwrap(), false);
1867/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("No")).unwrap(), false);
1868/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("oFF")).unwrap(), false);
1869/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("0")).unwrap(), false);
1870/// ```
1871#[derive(Copy, Clone, Debug)]
1872#[non_exhaustive]
1873pub struct BoolishValueParser {}
1874
1875impl BoolishValueParser {
1876    /// Parse bool-like string values, everything else is an error.
1877    pub fn new() -> Self {
1878        Self {}
1879    }
1880
1881    fn possible_values() -> impl Iterator<Item = crate::builder::PossibleValue> {
1882        crate::util::TRUE_LITERALS
1883            .iter()
1884            .chain(crate::util::FALSE_LITERALS.iter())
1885            .copied()
1886            .map(|l| crate::builder::PossibleValue::new(l).hide(l != "true" && l != "false"))
1887    }
1888}
1889
1890impl TypedValueParser for BoolishValueParser {
1891    type Value = bool;
1892
1893    fn parse_ref(
1894        &self,
1895        cmd: &crate::Command,
1896        arg: Option<&crate::Arg>,
1897        value: &std::ffi::OsStr,
1898    ) -> Result<Self::Value, crate::Error> {
1899        let value = ok!(value.to_str().ok_or_else(|| {
1900            crate::Error::invalid_utf8(
1901                cmd,
1902                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1903            )
1904        }));
1905        let value = ok!(crate::util::str_to_bool(value).ok_or_else(|| {
1906            let arg = arg
1907                .map(|a| a.to_string())
1908                .unwrap_or_else(|| "...".to_owned());
1909            crate::Error::value_validation(arg, value.to_owned(), "value was not a boolean".into())
1910                .with_cmd(cmd)
1911        }));
1912        Ok(value)
1913    }
1914
1915    fn possible_values(
1916        &self,
1917    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
1918        Some(Box::new(Self::possible_values()))
1919    }
1920}
1921
1922impl Default for BoolishValueParser {
1923    fn default() -> Self {
1924        Self::new()
1925    }
1926}
1927
1928/// Parse non-empty string values
1929///
1930/// See also:
1931/// - [`ValueParser::string`]
1932///
1933/// # Example
1934///
1935/// Usage:
1936/// ```rust
1937/// # use clap_builder as clap;
1938/// let mut cmd = clap::Command::new("raw")
1939///     .arg(
1940///         clap::Arg::new("append")
1941///             .value_parser(clap::builder::NonEmptyStringValueParser::new())
1942///             .required(true)
1943///     );
1944///
1945/// let m = cmd.try_get_matches_from_mut(["cmd", "true"]).unwrap();
1946/// let port: &String = m.get_one("append")
1947///     .expect("required");
1948/// assert_eq!(port, "true");
1949/// ```
1950///
1951/// Semantics:
1952/// ```rust
1953/// # use clap_builder as clap;
1954/// # use std::ffi::OsStr;
1955/// # use clap::builder::TypedValueParser;
1956/// # let cmd = clap::Command::new("test");
1957/// # let arg = None;
1958/// let value_parser = clap::builder::NonEmptyStringValueParser::new();
1959/// assert_eq!(value_parser.parse_ref(&cmd, arg, OsStr::new("random")).unwrap(), "random");
1960/// assert!(value_parser.parse_ref(&cmd, arg, OsStr::new("")).is_err());
1961/// ```
1962#[derive(Copy, Clone, Debug)]
1963#[non_exhaustive]
1964pub struct NonEmptyStringValueParser {}
1965
1966impl NonEmptyStringValueParser {
1967    /// Parse non-empty string values
1968    pub fn new() -> Self {
1969        Self {}
1970    }
1971}
1972
1973impl TypedValueParser for NonEmptyStringValueParser {
1974    type Value = String;
1975
1976    fn parse_ref(
1977        &self,
1978        cmd: &crate::Command,
1979        arg: Option<&crate::Arg>,
1980        value: &std::ffi::OsStr,
1981    ) -> Result<Self::Value, crate::Error> {
1982        if value.is_empty() {
1983            return Err(crate::Error::empty_value(
1984                cmd,
1985                &[],
1986                arg.map(ToString::to_string)
1987                    .unwrap_or_else(|| "...".to_owned()),
1988            ));
1989        }
1990        let value = ok!(value.to_str().ok_or_else(|| {
1991            crate::Error::invalid_utf8(
1992                cmd,
1993                crate::output::Usage::new(cmd).create_usage_with_title(&[]),
1994            )
1995        }));
1996        Ok(value.to_owned())
1997    }
1998}
1999
2000impl Default for NonEmptyStringValueParser {
2001    fn default() -> Self {
2002        Self::new()
2003    }
2004}
2005
2006/// Adapt a `TypedValueParser` from one value to another
2007///
2008/// See [`TypedValueParser::map`]
2009#[derive(Clone, Debug)]
2010pub struct MapValueParser<P, F> {
2011    parser: P,
2012    func: F,
2013}
2014
2015impl<P, F, T> MapValueParser<P, F>
2016where
2017    P: TypedValueParser,
2018    P::Value: Send + Sync + Clone,
2019    F: Fn(P::Value) -> T + Clone,
2020    T: Send + Sync + Clone,
2021{
2022    fn new(parser: P, func: F) -> Self {
2023        Self { parser, func }
2024    }
2025}
2026
2027impl<P, F, T> TypedValueParser for MapValueParser<P, F>
2028where
2029    P: TypedValueParser,
2030    P::Value: Send + Sync + Clone,
2031    F: Fn(P::Value) -> T + Clone + Send + Sync + 'static,
2032    T: Send + Sync + Clone,
2033{
2034    type Value = T;
2035
2036    fn parse_ref(
2037        &self,
2038        cmd: &crate::Command,
2039        arg: Option<&crate::Arg>,
2040        value: &std::ffi::OsStr,
2041    ) -> Result<Self::Value, crate::Error> {
2042        let value = ok!(self.parser.parse_ref(cmd, arg, value));
2043        let value = (self.func)(value);
2044        Ok(value)
2045    }
2046
2047    fn parse(
2048        &self,
2049        cmd: &crate::Command,
2050        arg: Option<&crate::Arg>,
2051        value: std::ffi::OsString,
2052    ) -> Result<Self::Value, crate::Error> {
2053        let value = ok!(self.parser.parse(cmd, arg, value));
2054        let value = (self.func)(value);
2055        Ok(value)
2056    }
2057
2058    fn possible_values(
2059        &self,
2060    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
2061        self.parser.possible_values()
2062    }
2063}
2064
2065/// Adapt a `TypedValueParser` from one value to another
2066///
2067/// See [`TypedValueParser::try_map`]
2068#[derive(Clone, Debug)]
2069pub struct TryMapValueParser<P, F> {
2070    parser: P,
2071    func: F,
2072}
2073
2074impl<P, F, T, E> TryMapValueParser<P, F>
2075where
2076    P: TypedValueParser,
2077    P::Value: Send + Sync + Clone,
2078    F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
2079    T: Send + Sync + Clone,
2080    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2081{
2082    fn new(parser: P, func: F) -> Self {
2083        Self { parser, func }
2084    }
2085}
2086
2087impl<P, F, T, E> TypedValueParser for TryMapValueParser<P, F>
2088where
2089    P: TypedValueParser,
2090    P::Value: Send + Sync + Clone,
2091    F: Fn(P::Value) -> Result<T, E> + Clone + Send + Sync + 'static,
2092    T: Send + Sync + Clone,
2093    E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2094{
2095    type Value = T;
2096
2097    fn parse_ref(
2098        &self,
2099        cmd: &crate::Command,
2100        arg: Option<&crate::Arg>,
2101        value: &std::ffi::OsStr,
2102    ) -> Result<Self::Value, crate::Error> {
2103        let mid_value = ok!(self.parser.parse_ref(cmd, arg, value));
2104        let value = ok!((self.func)(mid_value).map_err(|e| {
2105            let arg = arg
2106                .map(|a| a.to_string())
2107                .unwrap_or_else(|| "...".to_owned());
2108            crate::Error::value_validation(arg, value.to_string_lossy().into_owned(), e.into())
2109                .with_cmd(cmd)
2110        }));
2111        Ok(value)
2112    }
2113
2114    fn possible_values(
2115        &self,
2116    ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> {
2117        self.parser.possible_values()
2118    }
2119}
2120
2121/// When encountered, report [`ErrorKind::UnknownArgument`][crate::error::ErrorKind::UnknownArgument]
2122///
2123/// Useful to help users migrate, either from old versions or similar tools.
2124///
2125/// # Examples
2126///
2127/// ```rust
2128/// # use clap_builder as clap;
2129/// # use clap::Command;
2130/// # use clap::Arg;
2131/// let cmd = Command::new("mycmd")
2132///     .args([
2133///         Arg::new("current-dir")
2134///             .short('C'),
2135///         Arg::new("current-dir-unknown")
2136///             .long("cwd")
2137///             .aliases(["current-dir", "directory", "working-directory", "root"])
2138///             .value_parser(clap::builder::UnknownArgumentValueParser::suggest_arg("-C"))
2139///             .hide(true),
2140///     ]);
2141///
2142/// // Use a supported version of the argument
2143/// let matches = cmd.clone().try_get_matches_from(["mycmd", "-C", ".."]).unwrap();
2144/// assert!(matches.contains_id("current-dir"));
2145/// assert_eq!(
2146///     matches.get_many::<String>("current-dir").unwrap_or_default().map(|v| v.as_str()).collect::<Vec<_>>(),
2147///     vec![".."]
2148/// );
2149///
2150/// // Use one of the invalid versions
2151/// let err = cmd.try_get_matches_from(["mycmd", "--cwd", ".."]).unwrap_err();
2152/// assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument);
2153/// ```
2154#[derive(Clone, Debug)]
2155pub struct UnknownArgumentValueParser {
2156    arg: Option<Str>,
2157    suggestions: Vec<StyledStr>,
2158}
2159
2160impl UnknownArgumentValueParser {
2161    /// Suggest an alternative argument
2162    pub fn suggest_arg(arg: impl Into<Str>) -> Self {
2163        Self {
2164            arg: Some(arg.into()),
2165            suggestions: Default::default(),
2166        }
2167    }
2168
2169    /// Provide a general suggestion
2170    pub fn suggest(text: impl Into<StyledStr>) -> Self {
2171        Self {
2172            arg: Default::default(),
2173            suggestions: vec![text.into()],
2174        }
2175    }
2176
2177    /// Extend the suggestions
2178    pub fn and_suggest(mut self, text: impl Into<StyledStr>) -> Self {
2179        self.suggestions.push(text.into());
2180        self
2181    }
2182}
2183
2184impl TypedValueParser for UnknownArgumentValueParser {
2185    type Value = String;
2186
2187    fn parse_ref(
2188        &self,
2189        cmd: &crate::Command,
2190        arg: Option<&crate::Arg>,
2191        value: &std::ffi::OsStr,
2192    ) -> Result<Self::Value, crate::Error> {
2193        TypedValueParser::parse_ref_(self, cmd, arg, value, ValueSource::CommandLine)
2194    }
2195
2196    fn parse_ref_(
2197        &self,
2198        cmd: &crate::Command,
2199        arg: Option<&crate::Arg>,
2200        _value: &std::ffi::OsStr,
2201        source: ValueSource,
2202    ) -> Result<Self::Value, crate::Error> {
2203        match source {
2204            ValueSource::DefaultValue => {
2205                TypedValueParser::parse_ref_(&StringValueParser::new(), cmd, arg, _value, source)
2206            }
2207            ValueSource::EnvVariable | ValueSource::CommandLine => {
2208                let arg = match arg {
2209                    Some(arg) => arg.to_string(),
2210                    None => "..".to_owned(),
2211                };
2212                let err = crate::Error::unknown_argument(
2213                    cmd,
2214                    arg,
2215                    self.arg.as_ref().map(|s| (s.as_str().to_owned(), None)),
2216                    false,
2217                    crate::output::Usage::new(cmd).create_usage_with_title(&[]),
2218                );
2219                #[cfg(feature = "error-context")]
2220                let err = {
2221                    debug_assert_eq!(
2222                        err.get(crate::error::ContextKind::Suggested),
2223                        None,
2224                        "Assuming `Error::unknown_argument` doesn't apply any `Suggested` so we can without caution"
2225                    );
2226                    err.insert_context_unchecked(
2227                        crate::error::ContextKind::Suggested,
2228                        crate::error::ContextValue::StyledStrs(self.suggestions.clone()),
2229                    )
2230                };
2231                Err(err)
2232            }
2233        }
2234    }
2235}
2236
2237/// Register a type with [`value_parser!`][crate::value_parser!]
2238///
2239/// # Example
2240///
2241/// ```rust
2242/// # use clap_builder as clap;
2243/// #[derive(Copy, Clone, Debug)]
2244/// pub struct Custom(u32);
2245///
2246/// impl clap::builder::ValueParserFactory for Custom {
2247///     type Parser = CustomValueParser;
2248///     fn value_parser() -> Self::Parser {
2249///         CustomValueParser
2250///     }
2251/// }
2252///
2253/// #[derive(Clone, Debug)]
2254/// pub struct CustomValueParser;
2255/// impl clap::builder::TypedValueParser for CustomValueParser {
2256///     type Value = Custom;
2257///
2258///     fn parse_ref(
2259///         &self,
2260///         cmd: &clap::Command,
2261///         arg: Option<&clap::Arg>,
2262///         value: &std::ffi::OsStr,
2263///     ) -> Result<Self::Value, clap::Error> {
2264///         let inner = clap::value_parser!(u32);
2265///         let val = inner.parse_ref(cmd, arg, value)?;
2266///         Ok(Custom(val))
2267///     }
2268/// }
2269///
2270/// let parser: CustomValueParser = clap::value_parser!(Custom);
2271/// ```
2272pub trait ValueParserFactory {
2273    /// Generated parser, usually [`ValueParser`].
2274    ///
2275    /// It should at least be a type that supports `Into<ValueParser>`.  A non-`ValueParser` type
2276    /// allows the caller to do further initialization on the parser.
2277    type Parser;
2278
2279    /// Create the specified [`Self::Parser`]
2280    fn value_parser() -> Self::Parser;
2281}
2282impl ValueParserFactory for String {
2283    type Parser = ValueParser;
2284    fn value_parser() -> Self::Parser {
2285        ValueParser::string() // Default `clap_derive` to optimized implementation
2286    }
2287}
2288impl ValueParserFactory for Box<str> {
2289    type Parser = MapValueParser<StringValueParser, fn(String) -> Box<str>>;
2290    fn value_parser() -> Self::Parser {
2291        StringValueParser::new().map(String::into_boxed_str)
2292    }
2293}
2294impl ValueParserFactory for std::ffi::OsString {
2295    type Parser = ValueParser;
2296    fn value_parser() -> Self::Parser {
2297        ValueParser::os_string() // Default `clap_derive` to optimized implementation
2298    }
2299}
2300impl ValueParserFactory for Box<std::ffi::OsStr> {
2301    type Parser =
2302        MapValueParser<OsStringValueParser, fn(std::ffi::OsString) -> Box<std::ffi::OsStr>>;
2303    fn value_parser() -> Self::Parser {
2304        OsStringValueParser::new().map(std::ffi::OsString::into_boxed_os_str)
2305    }
2306}
2307impl ValueParserFactory for std::path::PathBuf {
2308    type Parser = ValueParser;
2309    fn value_parser() -> Self::Parser {
2310        ValueParser::path_buf() // Default `clap_derive` to optimized implementation
2311    }
2312}
2313impl ValueParserFactory for Box<std::path::Path> {
2314    type Parser =
2315        MapValueParser<PathBufValueParser, fn(std::path::PathBuf) -> Box<std::path::Path>>;
2316    fn value_parser() -> Self::Parser {
2317        PathBufValueParser::new().map(std::path::PathBuf::into_boxed_path)
2318    }
2319}
2320impl ValueParserFactory for bool {
2321    type Parser = ValueParser;
2322    fn value_parser() -> Self::Parser {
2323        ValueParser::bool() // Default `clap_derive` to optimized implementation
2324    }
2325}
2326impl ValueParserFactory for u8 {
2327    type Parser = RangedI64ValueParser<u8>;
2328    fn value_parser() -> Self::Parser {
2329        let start: i64 = u8::MIN.into();
2330        let end: i64 = u8::MAX.into();
2331        RangedI64ValueParser::new().range(start..=end)
2332    }
2333}
2334impl ValueParserFactory for i8 {
2335    type Parser = RangedI64ValueParser<i8>;
2336    fn value_parser() -> Self::Parser {
2337        let start: i64 = i8::MIN.into();
2338        let end: i64 = i8::MAX.into();
2339        RangedI64ValueParser::new().range(start..=end)
2340    }
2341}
2342impl ValueParserFactory for u16 {
2343    type Parser = RangedI64ValueParser<u16>;
2344    fn value_parser() -> Self::Parser {
2345        let start: i64 = u16::MIN.into();
2346        let end: i64 = u16::MAX.into();
2347        RangedI64ValueParser::new().range(start..=end)
2348    }
2349}
2350impl ValueParserFactory for i16 {
2351    type Parser = RangedI64ValueParser<i16>;
2352    fn value_parser() -> Self::Parser {
2353        let start: i64 = i16::MIN.into();
2354        let end: i64 = i16::MAX.into();
2355        RangedI64ValueParser::new().range(start..=end)
2356    }
2357}
2358impl ValueParserFactory for u32 {
2359    type Parser = RangedI64ValueParser<u32>;
2360    fn value_parser() -> Self::Parser {
2361        let start: i64 = u32::MIN.into();
2362        let end: i64 = u32::MAX.into();
2363        RangedI64ValueParser::new().range(start..=end)
2364    }
2365}
2366impl ValueParserFactory for i32 {
2367    type Parser = RangedI64ValueParser<i32>;
2368    fn value_parser() -> Self::Parser {
2369        let start: i64 = i32::MIN.into();
2370        let end: i64 = i32::MAX.into();
2371        RangedI64ValueParser::new().range(start..=end)
2372    }
2373}
2374impl ValueParserFactory for u64 {
2375    type Parser = RangedU64ValueParser<u64>;
2376    fn value_parser() -> Self::Parser {
2377        RangedU64ValueParser::new()
2378    }
2379}
2380impl ValueParserFactory for i64 {
2381    type Parser = RangedI64ValueParser<i64>;
2382    fn value_parser() -> Self::Parser {
2383        RangedI64ValueParser::new()
2384    }
2385}
2386impl<T> ValueParserFactory for std::num::Wrapping<T>
2387where
2388    T: ValueParserFactory,
2389    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2390    T: Send + Sync + Clone,
2391{
2392    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::num::Wrapping<T>>;
2393    fn value_parser() -> Self::Parser {
2394        T::value_parser().map(std::num::Wrapping)
2395    }
2396}
2397impl<T> ValueParserFactory for Box<T>
2398where
2399    T: ValueParserFactory,
2400    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2401    T: Send + Sync + Clone,
2402{
2403    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> Box<T>>;
2404    fn value_parser() -> Self::Parser {
2405        T::value_parser().map(Box::new)
2406    }
2407}
2408impl<T> ValueParserFactory for std::sync::Arc<T>
2409where
2410    T: ValueParserFactory,
2411    <T as ValueParserFactory>::Parser: TypedValueParser<Value = T>,
2412    T: Send + Sync + Clone,
2413{
2414    type Parser = MapValueParser<<T as ValueParserFactory>::Parser, fn(T) -> std::sync::Arc<T>>;
2415    fn value_parser() -> Self::Parser {
2416        T::value_parser().map(std::sync::Arc::new)
2417    }
2418}
2419
2420#[doc(hidden)]
2421#[derive(Debug)]
2422#[allow(non_camel_case_types)]
2423pub struct _infer_ValueParser_for<T>(std::marker::PhantomData<T>);
2424
2425impl<T> _infer_ValueParser_for<T> {
2426    #[doc(hidden)]
2427    #[allow(clippy::new_without_default)]
2428    pub fn new() -> Self {
2429        Self(Default::default())
2430    }
2431}
2432
2433/// Unstable [`ValueParser`]
2434///
2435/// Implementation may change to more specific instance in the future
2436#[doc(hidden)]
2437#[derive(Debug)]
2438pub struct _AnonymousValueParser(ValueParser);
2439
2440#[doc(hidden)]
2441pub mod impl_prelude {
2442    use super::*;
2443
2444    #[doc(hidden)]
2445    #[allow(non_camel_case_types)]
2446    pub trait _impls_ValueParserFactory: private::_impls_ValueParserFactorySealed {
2447        type Parser;
2448        fn value_parser(&self) -> Self::Parser;
2449    }
2450    impl<P: ValueParserFactory> _impls_ValueParserFactory for &&&&&&_infer_ValueParser_for<P> {
2451        type Parser = P::Parser;
2452        fn value_parser(&self) -> Self::Parser {
2453            P::value_parser()
2454        }
2455    }
2456
2457    #[doc(hidden)]
2458    #[allow(non_camel_case_types)]
2459    pub trait _impls_ValueEnum: private::_impls_ValueEnumSealed {
2460        type Output;
2461
2462        fn value_parser(&self) -> Self::Output;
2463    }
2464    impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> _impls_ValueEnum
2465        for &&&&&_infer_ValueParser_for<E>
2466    {
2467        type Output = EnumValueParser<E>;
2468
2469        fn value_parser(&self) -> Self::Output {
2470            EnumValueParser::<E>::new()
2471        }
2472    }
2473
2474    #[doc(hidden)]
2475    #[allow(non_camel_case_types)]
2476    pub trait _impls_From_OsString: private::_impls_From_OsStringSealed {
2477        fn value_parser(&self) -> _AnonymousValueParser;
2478    }
2479    impl<FromOsString> _impls_From_OsString for &&&&_infer_ValueParser_for<FromOsString>
2480    where
2481        FromOsString: From<std::ffi::OsString> + std::any::Any + Clone + Send + Sync + 'static,
2482    {
2483        fn value_parser(&self) -> _AnonymousValueParser {
2484            _AnonymousValueParser(
2485                OsStringValueParser::new()
2486                    .map(|s| FromOsString::from(s))
2487                    .into(),
2488            )
2489        }
2490    }
2491
2492    #[doc(hidden)]
2493    #[allow(non_camel_case_types)]
2494    pub trait _impls_From_OsStr: private::_impls_From_OsStrSealed {
2495        fn value_parser(&self) -> _AnonymousValueParser;
2496    }
2497    impl<FromOsStr> _impls_From_OsStr for &&&_infer_ValueParser_for<FromOsStr>
2498    where
2499        FromOsStr:
2500            for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Clone + Send + Sync + 'static,
2501    {
2502        fn value_parser(&self) -> _AnonymousValueParser {
2503            _AnonymousValueParser(
2504                OsStringValueParser::new()
2505                    .map(|s| FromOsStr::from(&s))
2506                    .into(),
2507            )
2508        }
2509    }
2510
2511    #[doc(hidden)]
2512    #[allow(non_camel_case_types)]
2513    pub trait _impls_From_String: private::_impls_From_StringSealed {
2514        fn value_parser(&self) -> _AnonymousValueParser;
2515    }
2516    impl<FromString> _impls_From_String for &&_infer_ValueParser_for<FromString>
2517    where
2518        FromString: From<String> + std::any::Any + Clone + Send + Sync + 'static,
2519    {
2520        fn value_parser(&self) -> _AnonymousValueParser {
2521            _AnonymousValueParser(StringValueParser::new().map(|s| FromString::from(s)).into())
2522        }
2523    }
2524
2525    #[doc(hidden)]
2526    #[allow(non_camel_case_types)]
2527    pub trait _impls_From_str: private::_impls_From_strSealed {
2528        fn value_parser(&self) -> _AnonymousValueParser;
2529    }
2530    impl<FromStr> _impls_From_str for &_infer_ValueParser_for<FromStr>
2531    where
2532        FromStr: for<'s> From<&'s str> + std::any::Any + Clone + Send + Sync + 'static,
2533    {
2534        fn value_parser(&self) -> _AnonymousValueParser {
2535            _AnonymousValueParser(StringValueParser::new().map(|s| FromStr::from(&s)).into())
2536        }
2537    }
2538
2539    #[doc(hidden)]
2540    #[allow(non_camel_case_types)]
2541    pub trait _impls_FromStr: private::_impls_FromStrSealed {
2542        fn value_parser(&self) -> _AnonymousValueParser;
2543    }
2544    impl<Parse> _impls_FromStr for _infer_ValueParser_for<Parse>
2545    where
2546        Parse: std::str::FromStr + std::any::Any + Clone + Send + Sync + 'static,
2547        <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2548    {
2549        fn value_parser(&self) -> _AnonymousValueParser {
2550            let func: fn(&str) -> Result<Parse, <Parse as std::str::FromStr>::Err> =
2551                Parse::from_str;
2552            _AnonymousValueParser(ValueParser::new(func))
2553        }
2554    }
2555}
2556
2557/// Select a [`ValueParser`] implementation from the intended type
2558///
2559/// Supported types
2560/// - [`ValueParserFactory` types][ValueParserFactory], including
2561///   - [Native types][ValueParser]: `bool`, `String`, `OsString`, `PathBuf`
2562///   - [Ranged numeric types][RangedI64ValueParser]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`
2563/// - [`ValueEnum` types][crate::ValueEnum]
2564/// - [`From<OsString>` types][std::convert::From] and [`From<&OsStr>` types][std::convert::From]
2565/// - [`From<String>` types][std::convert::From] and [`From<&str>` types][std::convert::From]
2566/// - [`FromStr` types][std::str::FromStr], including usize, isize
2567///
2568/// # Example
2569///
2570/// Usage:
2571/// ```rust
2572/// # use clap_builder as clap;
2573/// # use std::path::PathBuf;
2574/// # use std::path::Path;
2575/// let mut cmd = clap::Command::new("raw")
2576///     .arg(
2577///         clap::Arg::new("output")
2578///             .value_parser(clap::value_parser!(PathBuf))
2579///             .required(true)
2580///     );
2581///
2582/// let m = cmd.try_get_matches_from_mut(["cmd", "file.txt"]).unwrap();
2583/// let port: &PathBuf = m.get_one("output")
2584///     .expect("required");
2585/// assert_eq!(port, Path::new("file.txt"));
2586/// ```
2587///
2588/// Example mappings:
2589/// ```rust
2590/// # use clap_builder as clap;
2591/// # use clap::ColorChoice;
2592/// // Built-in types
2593/// let parser = clap::value_parser!(String);
2594/// assert_eq!(format!("{parser:?}"), "ValueParser::string");
2595/// let parser = clap::value_parser!(std::ffi::OsString);
2596/// assert_eq!(format!("{parser:?}"), "ValueParser::os_string");
2597/// let parser = clap::value_parser!(std::path::PathBuf);
2598/// assert_eq!(format!("{parser:?}"), "ValueParser::path_buf");
2599/// clap::value_parser!(u16).range(3000..);
2600/// clap::value_parser!(u64).range(3000..);
2601///
2602/// // FromStr types
2603/// let parser = clap::value_parser!(usize);
2604/// assert_eq!(format!("{parser:?}"), "_AnonymousValueParser(ValueParser::other(usize))");
2605///
2606/// // ValueEnum types
2607/// clap::value_parser!(ColorChoice);
2608/// ```
2609#[macro_export]
2610macro_rules! value_parser {
2611    ($name:ty) => {{
2612        use $crate::builder::impl_prelude::*;
2613        let auto = $crate::builder::_infer_ValueParser_for::<$name>::new();
2614        (&&&&&&auto).value_parser()
2615    }};
2616}
2617
2618mod private {
2619    use super::*;
2620
2621    #[allow(non_camel_case_types)]
2622    pub trait _impls_ValueParserFactorySealed {}
2623    impl<P: ValueParserFactory> _impls_ValueParserFactorySealed for &&&&&&_infer_ValueParser_for<P> {}
2624
2625    #[allow(non_camel_case_types)]
2626    pub trait _impls_ValueEnumSealed {}
2627    impl<E: crate::ValueEnum> _impls_ValueEnumSealed for &&&&&_infer_ValueParser_for<E> {}
2628
2629    #[allow(non_camel_case_types)]
2630    pub trait _impls_From_OsStringSealed {}
2631    impl<FromOsString> _impls_From_OsStringSealed for &&&&_infer_ValueParser_for<FromOsString> where
2632        FromOsString: From<std::ffi::OsString> + std::any::Any + Send + Sync + 'static
2633    {
2634    }
2635
2636    #[allow(non_camel_case_types)]
2637    pub trait _impls_From_OsStrSealed {}
2638    impl<FromOsStr> _impls_From_OsStrSealed for &&&_infer_ValueParser_for<FromOsStr> where
2639        FromOsStr: for<'s> From<&'s std::ffi::OsStr> + std::any::Any + Send + Sync + 'static
2640    {
2641    }
2642
2643    #[allow(non_camel_case_types)]
2644    pub trait _impls_From_StringSealed {}
2645    impl<FromString> _impls_From_StringSealed for &&_infer_ValueParser_for<FromString> where
2646        FromString: From<String> + std::any::Any + Send + Sync + 'static
2647    {
2648    }
2649
2650    #[allow(non_camel_case_types)]
2651    pub trait _impls_From_strSealed {}
2652    impl<FromStr> _impls_From_strSealed for &_infer_ValueParser_for<FromStr> where
2653        FromStr: for<'s> From<&'s str> + std::any::Any + Send + Sync + 'static
2654    {
2655    }
2656
2657    #[allow(non_camel_case_types)]
2658    pub trait _impls_FromStrSealed {}
2659    impl<Parse> _impls_FromStrSealed for _infer_ValueParser_for<Parse>
2660    where
2661        Parse: std::str::FromStr + std::any::Any + Send + Sync + 'static,
2662        <Parse as std::str::FromStr>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
2663    {
2664    }
2665}
2666
2667#[cfg(test)]
2668mod test {
2669    use super::*;
2670
2671    #[test]
2672    fn ensure_typed_applies_to_parse() {
2673        fn parse(_: &str) -> Result<usize, std::io::Error> {
2674            Ok(10)
2675        }
2676        let cmd = crate::Command::new("cmd");
2677        let arg = None;
2678        assert_eq!(
2679            TypedValueParser::parse_ref(&parse, &cmd, arg, std::ffi::OsStr::new("foo")).unwrap(),
2680            10
2681        );
2682    }
2683}