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