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 /// .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 /// ``` 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 /// 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 /// ``` new<P>(other: P) -> Self where P: TypedValueParser,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 /// ``` bool() -> Self137 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 /// ``` string() -> Self161 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 /// ``` os_string() -> Self191 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 /// ``` path_buf() -> Self216 pub const fn path_buf() -> Self { 217 Self(ValueParserInner::PathBuf) 218 } 219 } 220 221 impl ValueParser { 222 /// Parse into a `AnyValue` 223 /// 224 /// 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>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` type_id(&self) -> AnyValueId235 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. possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 any_value_parser(&self) -> &dyn AnyValueParser249 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 /// ``` 282 impl<P> From<P> for ValueParser 283 where 284 P: TypedValueParser + Send + Sync + 'static, 285 { from(p: P) -> Self286 fn from(p: P) -> Self { 287 Self::new(p) 288 } 289 } 290 291 impl From<_AnonymousValueParser> for ValueParser { from(p: _AnonymousValueParser) -> Self292 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 /// ``` 320 impl From<std::ops::Range<i64>> for ValueParser { from(value: std::ops::Range<i64>) -> Self321 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 /// ``` 350 impl From<std::ops::RangeInclusive<i64>> for ValueParser { from(value: std::ops::RangeInclusive<i64>) -> Self351 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 /// ``` 380 impl From<std::ops::RangeFrom<i64>> for ValueParser { from(value: std::ops::RangeFrom<i64>) -> Self381 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 /// ``` 410 impl From<std::ops::RangeTo<i64>> for ValueParser { from(value: std::ops::RangeTo<i64>) -> Self411 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 /// ``` 440 impl From<std::ops::RangeToInclusive<i64>> for ValueParser { from(value: std::ops::RangeToInclusive<i64>) -> Self441 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 /// ``` 470 impl From<std::ops::RangeFull> for ValueParser { from(value: std::ops::RangeFull) -> Self471 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 /// ``` 501 impl<P, const C: usize> From<[P; C]> for ValueParser 502 where 503 P: Into<super::PossibleValue>, 504 { from(values: [P; C]) -> Self505 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 /// ``` 536 impl<P> From<Vec<P>> for ValueParser 537 where 538 P: Into<super::PossibleValue>, 539 { from(values: Vec<P>) -> Self540 fn from(values: Vec<P>) -> Self { 541 let inner = PossibleValuesParser::from(values); 542 Self::from(inner) 543 } 544 } 545 546 impl std::fmt::Debug for ValueParser { fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>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 558 impl Clone for ValueParser { clone(&self) -> Self559 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`]. 571 trait AnyValueParser: Send + Sync + 'static { parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<AnyValue, crate::Error>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 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 586 /// Describes the content of `AnyValue` type_id(&self) -> AnyValueId587 fn type_id(&self) -> AnyValueId; 588 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>589 fn possible_values( 590 &self, 591 ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>; 592 clone_any(&self) -> Box<dyn AnyValueParser>593 fn clone_any(&self) -> Box<dyn AnyValueParser>; 594 } 595 596 impl<T, P> AnyValueParser for P 597 where 598 T: std::any::Any + Clone + Send + Sync + 'static, 599 P: TypedValueParser<Value = T>, 600 { parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<AnyValue, crate::Error>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 parse( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<AnyValue, crate::Error>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 type_id(&self) -> AnyValueId621 fn type_id(&self) -> AnyValueId { 622 AnyValueId::of::<T>() 623 } 624 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>625 fn possible_values( 626 &self, 627 ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>> { 628 P::possible_values(self) 629 } 630 clone_any(&self) -> Box<dyn AnyValueParser>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 /// ``` 685 pub 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. parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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. parse( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<Self::Value, crate::Error>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. possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 /// ``` map<T, F>(self, func: F) -> MapValueParser<Self, F> where T: Send + Sync + Clone, F: Fn(Self::Value) -> T + Clone,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 /// ``` try_map<T, E, F>(self, func: F) -> TryMapValueParser<Self, F> where F: Fn(Self::Value) -> Result<T, E> + Clone + Send + Sync + 'static, T: Send + Sync + Clone, E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,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 816 impl<F, T, E> TypedValueParser for F 817 where 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 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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] 851 pub struct StringValueParser {} 852 853 impl StringValueParser { 854 /// Implementation for [`ValueParser::string`] new() -> Self855 pub fn new() -> Self { 856 Self {} 857 } 858 } 859 860 impl TypedValueParser for StringValueParser { 861 type Value = String; 862 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 parse( &self, cmd: &crate::Command, _arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<Self::Value, crate::Error>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 888 impl Default for StringValueParser { default() -> Self889 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] 899 pub struct OsStringValueParser {} 900 901 impl OsStringValueParser { 902 /// Implementation for [`ValueParser::os_string`] new() -> Self903 pub fn new() -> Self { 904 Self {} 905 } 906 } 907 908 impl TypedValueParser for OsStringValueParser { 909 type Value = std::ffi::OsString; 910 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 parse( &self, _cmd: &crate::Command, _arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<Self::Value, crate::Error>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 930 impl Default for OsStringValueParser { default() -> Self931 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] 941 pub struct PathBufValueParser {} 942 943 impl PathBufValueParser { 944 /// Implementation for [`ValueParser::path_buf`] new() -> Self945 pub fn new() -> Self { 946 Self {} 947 } 948 } 949 950 impl TypedValueParser for PathBufValueParser { 951 type Value = std::path::PathBuf; 952 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 parse( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<Self::Value, crate::Error>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 980 impl Default for PathBufValueParser { default() -> Self981 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)] 1024 pub struct EnumValueParser<E: crate::ValueEnum + Clone + Send + Sync + 'static>( 1025 std::marker::PhantomData<E>, 1026 ); 1027 1028 impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> EnumValueParser<E> { 1029 /// Parse an [`ValueEnum`][crate::ValueEnum] new() -> Self1030 pub fn new() -> Self { 1031 let phantom: std::marker::PhantomData<E> = Default::default(); 1032 Self(phantom) 1033 } 1034 } 1035 1036 impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> TypedValueParser for EnumValueParser<E> { 1037 type Value = E; 1038 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 1095 impl<E: crate::ValueEnum + Clone + Send + Sync + 'static> Default for EnumValueParser<E> { default() -> Self1096 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)] 1139 pub struct PossibleValuesParser(Vec<super::PossibleValue>); 1140 1141 impl PossibleValuesParser { 1142 /// Verify the value is from an enumerated set pf [`PossibleValue`][crate::builder::PossibleValue]. new(values: impl Into<PossibleValuesParser>) -> Self1143 pub fn new(values: impl Into<PossibleValuesParser>) -> Self { 1144 values.into() 1145 } 1146 } 1147 1148 impl TypedValueParser for PossibleValuesParser { 1149 type Value = String; 1150 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 parse( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<String, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 1201 impl<I, T> From<I> for PossibleValuesParser 1202 where 1203 I: IntoIterator<Item = T>, 1204 T: Into<super::PossibleValue>, 1205 { from(values: I) -> Self1206 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)] 1252 pub 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 1257 impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> RangedI64ValueParser<T> { 1258 /// Select full range of `i64` new() -> Self1259 pub fn new() -> Self { 1260 Self::from(..) 1261 } 1262 1263 /// Narrow the supported range range<B: RangeBounds<i64>>(mut self, range: B) -> Self1264 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 format_bounds(&self) -> String1314 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 1337 impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync + 'static> TypedValueParser 1338 for RangedI64ValueParser<T> 1339 where 1340 <T as std::convert::TryFrom<i64>>::Error: Send + Sync + 'static + std::error::Error + ToString, 1341 { 1342 type Value = T; 1343 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, raw_value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 1396 impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync, B: RangeBounds<i64>> From<B> 1397 for RangedI64ValueParser<T> 1398 { from(range: B) -> Self1399 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 1407 impl<T: std::convert::TryFrom<i64> + Clone + Send + Sync> Default for RangedI64ValueParser<T> { default() -> Self1408 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)] 1450 pub 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 1455 impl<T: std::convert::TryFrom<u64>> RangedU64ValueParser<T> { 1456 /// Select full range of `u64` new() -> Self1457 pub fn new() -> Self { 1458 Self::from(..) 1459 } 1460 1461 /// Narrow the supported range range<B: RangeBounds<u64>>(mut self, range: B) -> Self1462 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 format_bounds(&self) -> String1512 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 1535 impl<T: std::convert::TryFrom<u64> + Clone + Send + Sync + 'static> TypedValueParser 1536 for RangedU64ValueParser<T> 1537 where 1538 <T as std::convert::TryFrom<u64>>::Error: Send + Sync + 'static + std::error::Error + ToString, 1539 { 1540 type Value = T; 1541 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, raw_value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 1594 impl<T: std::convert::TryFrom<u64>, B: RangeBounds<u64>> From<B> for RangedU64ValueParser<T> { from(range: B) -> Self1595 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 1603 impl<T: std::convert::TryFrom<u64>> Default for RangedU64ValueParser<T> { default() -> Self1604 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] 1614 pub struct BoolValueParser {} 1615 1616 impl BoolValueParser { 1617 /// Implementation for [`ValueParser::bool`] new() -> Self1618 pub fn new() -> Self { 1619 Self {} 1620 } 1621 possible_values() -> impl Iterator<Item = crate::builder::PossibleValue>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 1630 impl TypedValueParser for BoolValueParser { 1631 type Value = bool; 1632 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 1667 impl Default for BoolValueParser { default() -> Self1668 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] 1713 pub struct FalseyValueParser {} 1714 1715 impl FalseyValueParser { 1716 /// Parse false-like string values, everything else is `true` new() -> Self1717 pub fn new() -> Self { 1718 Self {} 1719 } 1720 possible_values() -> impl Iterator<Item = crate::builder::PossibleValue>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 1730 impl TypedValueParser for FalseyValueParser { 1731 type Value = bool; 1732 parse_ref( &self, cmd: &crate::Command, _arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 1760 impl Default for FalseyValueParser { default() -> Self1761 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] 1810 pub struct BoolishValueParser {} 1811 1812 impl BoolishValueParser { 1813 /// Parse bool-like string values, everything else is `true` new() -> Self1814 pub fn new() -> Self { 1815 Self {} 1816 } 1817 possible_values() -> impl Iterator<Item = crate::builder::PossibleValue>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 1827 impl TypedValueParser for BoolishValueParser { 1828 type Value = bool; 1829 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 1859 impl Default for BoolishValueParser { default() -> Self1860 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] 1899 pub struct NonEmptyStringValueParser {} 1900 1901 impl NonEmptyStringValueParser { 1902 /// Parse non-empty string values new() -> Self1903 pub fn new() -> Self { 1904 Self {} 1905 } 1906 } 1907 1908 impl TypedValueParser for NonEmptyStringValueParser { 1909 type Value = String; 1910 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 1935 impl Default for NonEmptyStringValueParser { default() -> Self1936 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)] 1945 pub struct MapValueParser<P, F> { 1946 parser: P, 1947 func: F, 1948 } 1949 1950 impl<P, F, T> MapValueParser<P, F> 1951 where 1952 P: TypedValueParser, 1953 P::Value: Send + Sync + Clone, 1954 F: Fn(P::Value) -> T + Clone, 1955 T: Send + Sync + Clone, 1956 { new(parser: P, func: F) -> Self1957 fn new(parser: P, func: F) -> Self { 1958 Self { parser, func } 1959 } 1960 } 1961 1962 impl<P, F, T> TypedValueParser for MapValueParser<P, F> 1963 where 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 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 parse( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: std::ffi::OsString, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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)] 2004 pub struct TryMapValueParser<P, F> { 2005 parser: P, 2006 func: F, 2007 } 2008 2009 impl<P, F, T, E> TryMapValueParser<P, F> 2010 where 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 { new(parser: P, func: F) -> Self2017 fn new(parser: P, func: F) -> Self { 2018 Self { parser, func } 2019 } 2020 } 2021 2022 impl<P, F, T, E> TypedValueParser for TryMapValueParser<P, F> 2023 where 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 parse_ref( &self, cmd: &crate::Command, arg: Option<&crate::Arg>, value: &std::ffi::OsStr, ) -> Result<Self::Value, crate::Error>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 possible_values( &self, ) -> Option<Box<dyn Iterator<Item = crate::builder::PossibleValue> + '_>>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 /// ``` 2090 pub 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`] value_parser() -> Self::Parser2098 fn value_parser() -> Self::Parser; 2099 } 2100 impl ValueParserFactory for String { 2101 type Parser = ValueParser; value_parser() -> Self::Parser2102 fn value_parser() -> Self::Parser { 2103 ValueParser::string() // Default `clap_derive` to optimized implementation 2104 } 2105 } 2106 impl ValueParserFactory for std::ffi::OsString { 2107 type Parser = ValueParser; value_parser() -> Self::Parser2108 fn value_parser() -> Self::Parser { 2109 ValueParser::os_string() // Default `clap_derive` to optimized implementation 2110 } 2111 } 2112 impl ValueParserFactory for std::path::PathBuf { 2113 type Parser = ValueParser; value_parser() -> Self::Parser2114 fn value_parser() -> Self::Parser { 2115 ValueParser::path_buf() // Default `clap_derive` to optimized implementation 2116 } 2117 } 2118 impl ValueParserFactory for bool { 2119 type Parser = ValueParser; value_parser() -> Self::Parser2120 fn value_parser() -> Self::Parser { 2121 ValueParser::bool() // Default `clap_derive` to optimized implementation 2122 } 2123 } 2124 impl ValueParserFactory for u8 { 2125 type Parser = RangedI64ValueParser<u8>; value_parser() -> Self::Parser2126 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 } 2132 impl ValueParserFactory for i8 { 2133 type Parser = RangedI64ValueParser<i8>; value_parser() -> Self::Parser2134 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 } 2140 impl ValueParserFactory for u16 { 2141 type Parser = RangedI64ValueParser<u16>; value_parser() -> Self::Parser2142 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 } 2148 impl ValueParserFactory for i16 { 2149 type Parser = RangedI64ValueParser<i16>; value_parser() -> Self::Parser2150 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 } 2156 impl ValueParserFactory for u32 { 2157 type Parser = RangedI64ValueParser<u32>; value_parser() -> Self::Parser2158 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 } 2164 impl ValueParserFactory for i32 { 2165 type Parser = RangedI64ValueParser<i32>; value_parser() -> Self::Parser2166 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 } 2172 impl ValueParserFactory for i64 { 2173 type Parser = RangedI64ValueParser<i64>; value_parser() -> Self::Parser2174 fn value_parser() -> Self::Parser { 2175 RangedI64ValueParser::new() 2176 } 2177 } 2178 impl ValueParserFactory for u64 { 2179 type Parser = RangedU64ValueParser<u64>; value_parser() -> Self::Parser2180 fn value_parser() -> Self::Parser { 2181 RangedU64ValueParser::new() 2182 } 2183 } 2184 2185 #[doc(hidden)] 2186 #[derive(Debug)] 2187 pub struct _AutoValueParser<T>(std::marker::PhantomData<T>); 2188 2189 impl<T> _AutoValueParser<T> { 2190 #[doc(hidden)] 2191 #[allow(clippy::new_without_default)] new() -> Self2192 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)] 2202 pub struct _AnonymousValueParser(ValueParser); 2203 2204 #[doc(hidden)] 2205 pub mod via_prelude { 2206 use super::*; 2207 2208 #[doc(hidden)] 2209 pub trait _ValueParserViaFactory: private::_ValueParserViaFactorySealed { 2210 type Parser; value_parser(&self) -> Self::Parser2211 fn value_parser(&self) -> Self::Parser; 2212 } 2213 impl<P: ValueParserFactory> _ValueParserViaFactory for &&&&&&_AutoValueParser<P> { 2214 type Parser = P::Parser; value_parser(&self) -> Self::Parser2215 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 value_parser(&self) -> Self::Output2224 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 value_parser(&self) -> Self::Output2231 fn value_parser(&self) -> Self::Output { 2232 EnumValueParser::<E>::new() 2233 } 2234 } 2235 2236 #[doc(hidden)] 2237 pub trait _ValueParserViaFromOsString: private::_ValueParserViaFromOsStringSealed { value_parser(&self) -> _AnonymousValueParser2238 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 { value_parser(&self) -> _AnonymousValueParser2244 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 { value_parser(&self) -> _AnonymousValueParser2255 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 { value_parser(&self) -> _AnonymousValueParser2262 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 { value_parser(&self) -> _AnonymousValueParser2273 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 { value_parser(&self) -> _AnonymousValueParser2279 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 { value_parser(&self) -> _AnonymousValueParser2286 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 { value_parser(&self) -> _AnonymousValueParser2292 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 { value_parser(&self) -> _AnonymousValueParser2299 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 { value_parser(&self) -> _AnonymousValueParser2306 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] 2365 macro_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 2373 mod 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)] 2420 mod test { 2421 use super::*; 2422 2423 #[test] ensure_typed_applies_to_parse()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