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