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