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