1 use std::collections::HashMap; 2 use std::error::Error as StdError; 3 use std::fmt::{self, Debug}; 4 use std::io::{self, Write}; 5 use std::str::FromStr; 6 use std::result; 7 8 use lazy_static::lazy_static; 9 use regex::{Captures, Regex}; 10 use serde::de; 11 use serde::de::IntoDeserializer; 12 13 use crate::parse::Parser; 14 use crate::synonym::SynonymMap; 15 16 use self::Value::{Switch, Counted, Plain, List}; 17 use self::Error::{Usage, Argv, NoMatch, Deserialize, WithProgramUsage, Help, Version}; 18 19 use crate::cap_or_empty; 20 21 /// Represents the different types of Docopt errors. 22 /// 23 /// This error type has a lot of variants. In the common case, you probably 24 /// don't care why Docopt has failed, and would rather just quit the program 25 /// and show an error message instead. The `exit` method defined on the `Error` 26 /// type will do just that. It will also set the exit code appropriately 27 /// (no error for `--help` or `--version`, but an error code for bad usage, 28 /// bad argv, no match or bad decode). 29 /// 30 /// ### Example 31 /// 32 /// Generally, you want to parse the usage string, try to match the argv 33 /// and then quit the program if there was an error reported at any point 34 /// in that process. This can be achieved like so: 35 /// 36 /// ```no_run 37 /// use docopt::Docopt; 38 /// 39 /// const USAGE: &'static str = " 40 /// Usage: ... 41 /// "; 42 /// 43 /// let args = Docopt::new(USAGE) 44 /// .and_then(|d| d.parse()) 45 /// .unwrap_or_else(|e| e.exit()); 46 /// ``` 47 #[derive(Debug)] 48 pub enum Error { 49 /// Parsing the usage string failed. 50 /// 51 /// This error can only be triggered by the programmer, i.e., the writer 52 /// of the Docopt usage string. This error is usually indicative of a bug 53 /// in your program. 54 Usage(String), 55 56 /// Parsing the argv specified failed. 57 /// 58 /// The payload is a string describing why the arguments provided could not 59 /// be parsed. 60 /// 61 /// This is distinct from `NoMatch` because it will catch errors like 62 /// using flags that aren't defined in the usage string. 63 Argv(String), 64 65 /// The given argv parsed successfully, but it did not match any example 66 /// usage of the program. 67 /// 68 /// Regrettably, there is no descriptive message describing *why* the 69 /// given argv didn't match any of the usage strings. 70 NoMatch, 71 72 /// This indicates a problem deserializing a successful argv match into a 73 /// deserializable value. 74 Deserialize(String), 75 76 /// Parsing failed, and the program usage should be printed next to the 77 /// failure message. Typically this wraps `Argv` and `NoMatch` errors. 78 WithProgramUsage(Box<Error>, String), 79 80 /// Decoding or parsing failed because the command line specified that the 81 /// help message should be printed. 82 Help, 83 84 /// Decoding or parsing failed because the command line specified that the 85 /// version should be printed 86 /// 87 /// The version is included as a payload to this variant. 88 Version(String), 89 } 90 91 impl Error { 92 /// Return whether this was a fatal error or not. 93 /// 94 /// Non-fatal errors include requests to print the help or version 95 /// information of a program, while fatal errors include those such as 96 /// failing to decode or parse. fatal(&self) -> bool97 pub fn fatal(&self) -> bool { 98 match *self { 99 Help | Version(..) => false, 100 Usage(..) | Argv(..) | NoMatch | Deserialize(..) => true, 101 WithProgramUsage(ref b, _) => b.fatal(), 102 } 103 } 104 105 /// Print this error and immediately exit the program. 106 /// 107 /// If the error is non-fatal (e.g., `Help` or `Version`), then the 108 /// error is printed to stdout and the exit status will be `0`. Otherwise, 109 /// when the error is fatal, the error is printed to stderr and the 110 /// exit status will be `1`. exit(&self) -> !111 pub fn exit(&self) -> ! { 112 if self.fatal() { 113 werr!("{}\n", self); 114 ::std::process::exit(1) 115 } else { 116 let _ = writeln!(&mut io::stdout(), "{}", self); 117 ::std::process::exit(0) 118 } 119 } 120 } 121 122 type Result<T> = result::Result<T, Error>; 123 124 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 126 match *self { 127 WithProgramUsage(ref other, ref usage) => { 128 let other = other.to_string(); 129 if other.is_empty() { 130 write!(f, "{}", usage) 131 } else { 132 write!(f, "{}\n\n{}", other, usage) 133 } 134 } 135 Help => write!(f, ""), 136 NoMatch => write!(f, "Invalid arguments."), 137 Usage(ref s) | 138 Argv(ref s) | 139 Deserialize(ref s) | 140 Version(ref s) => write!(f, "{}", s), 141 } 142 } 143 } 144 145 impl StdError for Error { source(&self) -> Option<&(dyn StdError + 'static)>146 fn source(&self) -> Option<&(dyn StdError + 'static)> { 147 match *self { 148 WithProgramUsage(ref cause, _) => Some(&**cause), 149 _ => None, 150 } 151 } 152 } 153 154 impl de::Error for Error { custom<T: fmt::Display>(msg: T) -> Self155 fn custom<T: fmt::Display>(msg: T) -> Self { 156 Error::Deserialize(msg.to_string()) 157 } 158 } 159 160 /// The main Docopt type, which is constructed with a Docopt usage string. 161 /// 162 /// This can be used to match command line arguments to produce a `ArgvMap`. 163 #[derive(Clone, Debug)] 164 pub struct Docopt { 165 p: Parser, 166 argv: Option<Vec<String>>, 167 options_first: bool, 168 help: bool, 169 version: Option<String>, 170 } 171 172 impl Docopt { 173 /// Parse the Docopt usage string given. 174 /// 175 /// The `Docopt` value returned may be used immediately to parse command 176 /// line arguments with a default configuration. 177 /// 178 /// If there was a problem parsing the usage string, a `Usage` error 179 /// is returned. new<S>(usage: S) -> Result<Docopt> where S: ::std::ops::Deref<Target=str>180 pub fn new<S>(usage: S) -> Result<Docopt> 181 where S: ::std::ops::Deref<Target=str> { 182 Parser::new(usage.deref()) 183 .map_err(Usage) 184 .map(|p| Docopt { 185 p: p, 186 argv: None, 187 options_first: false, 188 help: true, 189 version: None, 190 }) 191 } 192 193 /// Parse and deserialize the given argv. 194 /// 195 /// This is a convenience method for 196 /// `parse().and_then(|vals| vals.deserialize())`. 197 /// 198 /// For details on how decoding works, please see the documentation for 199 /// `ArgvMap`. deserialize<'a, 'de: 'a, D>(&'a self) -> Result<D> where D: de::Deserialize<'de>200 pub fn deserialize<'a, 'de: 'a, D>(&'a self) -> Result<D> 201 where D: de::Deserialize<'de> 202 { 203 self.parse().and_then(|vals| vals.deserialize()) 204 } 205 206 /// Parse command line arguments and try to match them against a usage 207 /// pattern specified in the Docopt string. 208 /// 209 /// If there is a match, then an `ArgvMap` is returned, which maps 210 /// flags, commands and arguments to values. 211 /// 212 /// If parsing the command line arguments fails, then an `Argv` error is 213 /// returned. If parsing succeeds but there is no match, then a `NoMatch` 214 /// error is returned. Both of these errors are always returned inside a 215 /// `WithProgramUsage` error. 216 /// 217 /// If special handling of `help` or `version` is enabled (the former is 218 /// enabled by default), then `Help` or `Version` errors are returned 219 /// if `--help` or `--version` is present. parse(&self) -> Result<ArgvMap>220 pub fn parse(&self) -> Result<ArgvMap> { 221 let argv = self.argv.clone().unwrap_or_else(Docopt::get_argv); 222 let vals = 223 self.p.parse_argv(argv, self.options_first) 224 .map_err(|s| self.err_with_usage(Argv(s))) 225 .and_then(|argv| 226 match self.p.matches(&argv) { 227 Some(m) => Ok(ArgvMap { map: m }), 228 None => Err(self.err_with_usage(NoMatch)), 229 })?; 230 if self.help && vals.get_bool("--help") { 231 return Err(self.err_with_full_doc(Help)); 232 } 233 match self.version { 234 Some(ref v) if vals.get_bool("--version") => { 235 return Err(Version(v.clone())) 236 } 237 _ => {}, 238 } 239 Ok(vals) 240 } 241 242 /// Set the argv to be used for Docopt parsing. 243 /// 244 /// By default, when no argv is set, and it is automatically taken from 245 /// `std::env::args()`. 246 /// 247 /// The `argv` given *must* be the full set of `argv` passed to the 248 /// program. e.g., `["cp", "src", "dest"]` is right while `["src", "dest"]` 249 /// is wrong. argv<I, S>(mut self, argv: I) -> Docopt where I: IntoIterator<Item=S>, S: AsRef<str>250 pub fn argv<I, S>(mut self, argv: I) -> Docopt 251 where I: IntoIterator<Item=S>, S: AsRef<str> { 252 self.argv = Some( 253 argv.into_iter().skip(1).map(|s| s.as_ref().to_owned()).collect() 254 ); 255 self 256 } 257 258 /// Enables the "options first" Docopt behavior. 259 /// 260 /// The options first behavior means that all flags *must* appear before 261 /// position arguments. That is, after the first position argument is 262 /// seen, all proceeding arguments are interpreted as positional 263 /// arguments unconditionally. options_first(mut self, yes: bool) -> Docopt264 pub fn options_first(mut self, yes: bool) -> Docopt { 265 self.options_first = yes; 266 self 267 } 268 269 /// Enables automatic handling of `--help`. 270 /// 271 /// When this is enabled and `--help` appears anywhere in the arguments, 272 /// then a `Help` error will be returned. You may then use the `exit` 273 /// method on the error value to conveniently quit the program (which will 274 /// print the full usage string to stdout). 275 /// 276 /// Note that for this to work, `--help` must be a valid pattern. 277 /// 278 /// When disabled, there is no special handling of `--help`. help(mut self, yes: bool) -> Docopt279 pub fn help(mut self, yes: bool) -> Docopt { 280 self.help = yes; 281 self 282 } 283 284 /// Enables automatic handling of `--version`. 285 /// 286 /// When this is enabled and `--version` appears anywhere in the arguments, 287 /// then a `Version(s)` error will be returned, where `s` is the string 288 /// given here. You may then use the `exit` method on the error value to 289 /// convenient quit the program (which will print the version to stdout). 290 /// 291 /// When disabled (a `None` value), there is no special handling of 292 /// `--version`. version(mut self, version: Option<String>) -> Docopt293 pub fn version(mut self, version: Option<String>) -> Docopt { 294 self.version = version; 295 self 296 } 297 298 #[doc(hidden)] parser(&self) -> &Parser299 pub fn parser(&self) -> &Parser { 300 &self.p 301 } 302 err_with_usage(&self, e: Error) -> Error303 fn err_with_usage(&self, e: Error) -> Error { 304 WithProgramUsage( 305 Box::new(e), self.p.usage.trim().into()) 306 } 307 err_with_full_doc(&self, e: Error) -> Error308 fn err_with_full_doc(&self, e: Error) -> Error { 309 WithProgramUsage( 310 Box::new(e), self.p.full_doc.trim().into()) 311 } 312 get_argv() -> Vec<String>313 fn get_argv() -> Vec<String> { 314 // Hmm, we should probably handle a Unicode decode error here... ---AG 315 ::std::env::args().skip(1).collect() 316 } 317 } 318 319 /// A map containing matched values from command line arguments. 320 /// 321 /// The keys are just as specified in Docopt: `--flag` for a long flag or 322 /// `-f` for a short flag. (If `-f` is a synonym for `--flag`, then either 323 /// key will work.) `ARG` or `<arg>` specify a positional argument and `cmd` 324 /// specifies a command. 325 #[derive(Clone)] 326 pub struct ArgvMap { 327 #[doc(hidden)] 328 pub map: SynonymMap<String, Value>, 329 } 330 331 impl ArgvMap { 332 /// Tries to deserialize the map of values into a struct. 333 /// 334 /// This method should always be called to deserialize a `ArgvMap` into 335 /// a struct. All fields of the struct must map to a corresponding key 336 /// in the `ArgvMap`. To this end, each member must have a special prefix 337 /// corresponding to the different kinds of patterns in Docopt. There are 338 /// three prefixes: `flag_`, `arg_` and `cmd_` which respectively 339 /// correspond to short/long flags, positional arguments and commands. 340 /// 341 /// If a Docopt item has a `-` in its name, then it is converted to an `_`. 342 /// 343 /// # Example 344 /// 345 /// ```rust 346 /// # fn main() { 347 /// use serde::Deserialize; 348 /// 349 /// use docopt::Docopt; 350 /// 351 /// const USAGE: &'static str = " 352 /// Usage: cargo [options] (build | test) 353 /// cargo --help 354 /// 355 /// Options: -v, --verbose 356 /// -h, --help 357 /// "; 358 /// 359 /// #[derive(Deserialize)] 360 /// struct Args { 361 /// cmd_build: bool, 362 /// cmd_test: bool, 363 /// flag_verbose: bool, 364 /// flag_h: bool, 365 /// } 366 /// 367 /// let argv = || vec!["cargo", "build", "-v"].into_iter(); 368 /// let args: Args = Docopt::new(USAGE) 369 /// .and_then(|d| d.argv(argv()).deserialize()) 370 /// .unwrap_or_else(|e| e.exit()); 371 /// assert!(args.cmd_build && !args.cmd_test 372 /// && args.flag_verbose && !args.flag_h); 373 /// # } 374 /// ``` 375 /// 376 /// Note that in the above example, `flag_h` is used but `flag_help` 377 /// could also be used. (In fact, both could be used at the same time.) 378 /// 379 /// In this example, only the `bool` type was used, but any type satisfying 380 /// the `Deserialize` trait is valid. deserialize<'de, T: de::Deserialize<'de>>(self) -> Result<T>381 pub fn deserialize<'de, T: de::Deserialize<'de>>(self) -> Result<T> { 382 de::Deserialize::deserialize(&mut Deserializer { 383 vals: self, 384 stack: vec![], 385 }) 386 } 387 388 /// Finds the value corresponding to `key` and calls `as_bool()` on it. 389 /// If the key does not exist, `false` is returned. get_bool(&self, key: &str) -> bool390 pub fn get_bool(&self, key: &str) -> bool { 391 self.find(key).map_or(false, |v| v.as_bool()) 392 } 393 394 /// Finds the value corresponding to `key` and calls `as_count()` on it. 395 /// If the key does not exist, `0` is returned. get_count(&self, key: &str) -> u64396 pub fn get_count(&self, key: &str) -> u64 { 397 self.find(key).map_or(0, |v| v.as_count()) 398 } 399 400 /// Finds the value corresponding to `key` and calls `as_str()` on it. 401 /// If the key does not exist, `""` is returned. get_str(&self, key: &str) -> &str402 pub fn get_str(&self, key: &str) -> &str { 403 self.find(key).map_or("", |v| v.as_str()) 404 } 405 406 /// Finds the value corresponding to `key` and calls `as_vec()` on it. 407 /// If the key does not exist, `vec!()` is returned. get_vec(&self, key: &str) -> Vec<&str>408 pub fn get_vec(&self, key: &str) -> Vec<&str> { 409 self.find(key).map(|v| v.as_vec()).unwrap_or(vec!()) 410 } 411 412 /// Return the raw value corresponding to some `key`. 413 /// 414 /// `key` should be a string in the traditional Docopt format. e.g., 415 /// `<arg>` or `--flag`. find(&self, key: &str) -> Option<&Value>416 pub fn find(&self, key: &str) -> Option<&Value> { 417 self.map.find(&key.into()) 418 } 419 420 /// Return the number of values, not including synonyms. len(&self) -> usize421 pub fn len(&self) -> usize { 422 self.map.len() 423 } 424 425 /// Converts a Docopt key to a struct field name. 426 /// This makes a half-hearted attempt at making the key a valid struct 427 /// field name (like replacing `-` with `_`), but it does not otherwise 428 /// guarantee that the result is a valid struct field name. 429 #[doc(hidden)] key_to_struct_field(name: &str) -> String430 pub fn key_to_struct_field(name: &str) -> String { 431 lazy_static! { 432 static ref RE: Regex = regex!( 433 r"^(?:--?(?P<flag>\S+)|(?:(?P<argu>\p{Lu}+)|<(?P<argb>[^>]+)>)|(?P<cmd>\S+))$" 434 ); 435 } 436 fn sanitize(name: &str) -> String { 437 name.replace("-", "_") 438 } 439 440 RE.replace(name, |cap: &Captures<'_>| { 441 let (flag, cmd) = ( 442 cap_or_empty(cap, "flag"), 443 cap_or_empty(cap, "cmd"), 444 ); 445 let (argu, argb) = ( 446 cap_or_empty(cap, "argu"), 447 cap_or_empty(cap, "argb"), 448 ); 449 let (prefix, name) = 450 if !flag.is_empty() { 451 ("flag_", flag) 452 } else if !argu.is_empty() { 453 ("arg_", argu) 454 } else if !argb.is_empty() { 455 ("arg_", argb) 456 } else if !cmd.is_empty() { 457 ("cmd_", cmd) 458 } else { 459 panic!("Unknown ArgvMap key: '{}'", name) 460 }; 461 let mut prefix = prefix.to_owned(); 462 prefix.push_str(&sanitize(name)); 463 prefix 464 }).into_owned() 465 } 466 467 /// Converts a struct field name to a Docopt key. 468 #[doc(hidden)] struct_field_to_key(field: &str) -> String469 pub fn struct_field_to_key(field: &str) -> String { 470 lazy_static! { 471 static ref FLAG: Regex = regex!(r"^flag_"); 472 static ref ARG: Regex = regex!(r"^arg_"); 473 static ref LETTERS: Regex = regex!(r"^\p{Lu}+$"); 474 static ref CMD: Regex = regex!(r"^cmd_"); 475 } 476 fn desanitize(name: &str) -> String { 477 name.replace("_", "-") 478 } 479 let name = 480 if field.starts_with("flag_") { 481 let name = FLAG.replace(field, ""); 482 let mut pre_name = (if name.len() == 1 { "-" } else { "--" }) 483 .to_owned(); 484 pre_name.push_str(&*name); 485 pre_name 486 } else if field.starts_with("arg_") { 487 let name = ARG.replace(field, "").into_owned(); 488 if LETTERS.is_match(&name) { 489 name 490 } else { 491 let mut pre_name = "<".to_owned(); 492 pre_name.push_str(&*name); 493 pre_name.push('>'); 494 pre_name 495 } 496 } else if field.starts_with("cmd_") { 497 CMD.replace(field, "").into_owned() 498 } else { 499 panic!("Unrecognized struct field: '{}'", field) 500 }; 501 desanitize(&*name) 502 } 503 } 504 505 impl fmt::Debug for ArgvMap { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 507 if self.len() == 0 { 508 return write!(f, "{{EMPTY}}"); 509 } 510 511 // This is a little crazy, but we want to group synonyms with 512 // their keys and sort them for predictable output. 513 let reverse: HashMap<&String, &String> = 514 self.map.synonyms().map(|(from, to)| (to, from)).collect(); 515 let mut keys: Vec<&String> = self.map.keys().collect(); 516 keys.sort(); 517 let mut first = true; 518 for &k in &keys { 519 if !first { write!(f, "\n")?; } else { first = false; } 520 match reverse.get(&k) { 521 None => { 522 write!(f, "{} => {:?}", k, self.map.get(k))? 523 } 524 Some(s) => { 525 write!(f, "{}, {} => {:?}", s, k, self.map.get(k))? 526 } 527 } 528 } 529 Ok(()) 530 } 531 } 532 533 /// A matched command line value. 534 /// 535 /// The value can be a boolean, counted repetition, a plain string or a list 536 /// of strings. 537 /// 538 /// The various `as_{bool,count,str,vec}` methods provide convenient access 539 /// to values without destructuring manually. 540 #[derive(Clone, Debug, PartialEq)] 541 pub enum Value { 542 /// A boolean value from a flag that has no argument. 543 /// 544 /// The presence of a flag means `true` and the absence of a flag 545 /// means `false`. 546 Switch(bool), 547 548 /// The number of occurrences of a repeated flag. 549 Counted(u64), 550 551 /// A positional or flag argument. 552 /// 553 /// This is `None` when the positional argument or flag is not present. 554 /// Note that it is possible to have `Some("")` for a present but empty 555 /// argument. 556 Plain(Option<String>), 557 558 /// A List of positional or flag arguments. 559 /// 560 /// This list may be empty when no arguments or flags are present. 561 List(Vec<String>), 562 } 563 564 impl Value { 565 /// Returns the value as a bool. 566 /// 567 /// Counted repetitions are `false` if `0` and `true` otherwise. 568 /// Plain strings are `true` if present and `false` otherwise. 569 /// Lists are `true` if non-empty and `false` otherwise. as_bool(&self) -> bool570 pub fn as_bool(&self) -> bool { 571 match *self { 572 Switch(b) => b, 573 Counted(n) => n > 0, 574 Plain(None) => false, 575 Plain(Some(_)) => true, 576 List(ref vs) => !vs.is_empty(), 577 } 578 } 579 580 /// Returns the value as a count of the number of times it occurred. 581 /// 582 /// Booleans are `1` if `true` and `0` otherwise. 583 /// Plain strings are `1` if present and `0` otherwise. 584 /// Lists correspond to its length. as_count(&self) -> u64585 pub fn as_count(&self) -> u64 { 586 match *self { 587 Switch(b) => if b { 1 } else { 0 }, 588 Counted(n) => n, 589 Plain(None) => 0, 590 Plain(Some(_)) => 1, 591 List(ref vs) => vs.len() as u64, 592 } 593 } 594 595 /// Returns the value as a string. 596 /// 597 /// All values return an empty string except for a non-empty plain string. as_str(&self) -> &str598 pub fn as_str(&self) -> &str { 599 match *self { 600 Switch(_) | Counted(_) | Plain(None) | List(_) => "", 601 Plain(Some(ref s)) => &**s, 602 } 603 } 604 605 /// Returns the value as a list of strings. 606 /// 607 /// Booleans, repetitions and empty strings correspond to an empty list. 608 /// Plain strings correspond to a list of length `1`. as_vec(&self) -> Vec<&str>609 pub fn as_vec(&self) -> Vec<&str> { 610 match *self { 611 Switch(_) | Counted(_) | Plain(None) => vec![], 612 Plain(Some(ref s)) => vec![&**s], 613 List(ref vs) => vs.iter().map(|s| &**s).collect(), 614 } 615 } 616 } 617 618 /// Deserializer for `ArgvMap` into your own `Deserialize`able types. 619 /// 620 /// In general, you shouldn't have to use this type directly. It is exposed 621 /// in case you want to write a generic function that produces a deserializable 622 /// value. For example, here's a function that takes a usage string, an argv 623 /// and produces a deserializable value: 624 /// 625 /// ```rust 626 /// # extern crate docopt; 627 /// extern crate serde; 628 /// # fn main() { 629 /// use docopt::Docopt; 630 /// use serde::de::Deserialize; 631 /// 632 /// fn deserialize<'de, D: Deserialize<'de>>(usage: &str, argv: &[&str]) 633 /// -> Result<D, docopt::Error> { 634 /// Docopt::new(usage) 635 /// .and_then(|d| d.argv(argv.iter()).deserialize()) 636 /// } 637 /// # } 638 pub struct Deserializer<'de> { 639 vals: ArgvMap, 640 stack: Vec<DeserializerItem<'de>>, 641 } 642 643 #[derive(Debug)] 644 struct DeserializerItem<'de> { 645 key: String, 646 struct_field: &'de str, 647 val: Option<Value>, 648 } 649 650 macro_rules! derr( 651 ($($arg:tt)*) => (return Err(Deserialize(format!($($arg)*)))) 652 ); 653 654 impl<'de> Deserializer<'de> { push(&mut self, struct_field: &'de str)655 fn push(&mut self, struct_field: &'de str) { 656 let key = ArgvMap::struct_field_to_key(struct_field); 657 self.stack 658 .push(DeserializerItem { 659 key: key.clone(), 660 struct_field: struct_field, 661 val: self.vals.find(&*key).cloned(), 662 }); 663 } 664 pop(&mut self) -> Result<DeserializerItem<'_>>665 fn pop(&mut self) -> Result<DeserializerItem<'_>> { 666 match self.stack.pop() { 667 None => derr!("Could not deserialize value into unknown key."), 668 Some(it) => Ok(it), 669 } 670 } 671 pop_key_val(&mut self) -> Result<(String, Value)>672 fn pop_key_val(&mut self) -> Result<(String, Value)> { 673 let it = self.pop()?; 674 match it.val { 675 None => { 676 derr!("Could not find argument '{}' (from struct field '{}'). 677 Note that each struct field must have the right key prefix, which must 678 be one of `cmd_`, `flag_` or `arg_`.", 679 it.key, 680 it.struct_field) 681 } 682 Some(v) => Ok((it.key, v)), 683 } 684 } 685 pop_val(&mut self) -> Result<Value>686 fn pop_val(&mut self) -> Result<Value> { 687 let (_, v) = self.pop_key_val()?; 688 Ok(v) 689 } 690 to_number<T>(&mut self, expect: &str) -> Result<T> where T: FromStr + ToString, <T as FromStr>::Err: Debug691 fn to_number<T>(&mut self, expect: &str) -> Result<T> 692 where T: FromStr + ToString, 693 <T as FromStr>::Err: Debug 694 { 695 let (k, v) = self.pop_key_val()?; 696 match v { 697 Counted(n) => Ok(n.to_string().parse().unwrap()), // lol 698 _ => { 699 if v.as_str().trim().is_empty() { 700 Ok("0".parse().unwrap()) // lol 701 } else { 702 match v.as_str().parse() { 703 Err(_) => { 704 derr!("Could not deserialize '{}' to {} for '{}'.", 705 v.as_str(), 706 expect, 707 k) 708 } 709 Ok(v) => Ok(v), 710 } 711 } 712 } 713 } 714 } 715 to_float(&mut self, expect: &str) -> Result<f64>716 fn to_float(&mut self, expect: &str) -> Result<f64> { 717 let (k, v) = self.pop_key_val()?; 718 match v { 719 Counted(n) => Ok(n as f64), 720 _ => { 721 match v.as_str().parse() { 722 Err(_) => { 723 derr!("Could not deserialize '{}' to {} for '{}'.", 724 v.as_str(), 725 expect, 726 k) 727 } 728 Ok(v) => Ok(v), 729 } 730 } 731 } 732 } 733 } 734 735 macro_rules! deserialize_num { 736 ($name:ident, $method:ident, $ty:ty) => ( 737 fn $name<V>(self, visitor: V) -> Result<V::Value> 738 where V: de::Visitor<'de> 739 { 740 visitor.$method(self.to_number::<$ty>(stringify!($ty)).map(|n| n as $ty)?) 741 } 742 ); 743 } 744 745 impl<'a, 'de> ::serde::Deserializer<'de> for &'a mut Deserializer<'de> { 746 type Error = Error; 747 deserialize_any<V>(self, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>748 fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value> 749 where V: de::Visitor<'de> 750 { 751 unimplemented!() 752 } 753 deserialize_bool<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>754 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value> 755 where V: de::Visitor<'de> 756 { 757 visitor.visit_bool(self.pop_val().map(|v| v.as_bool())?) 758 } 759 760 // wish for stable macro concat_idents! 761 deserialize_num!(deserialize_i8, visit_i8, i8); 762 deserialize_num!(deserialize_i16, visit_i16, i16); 763 deserialize_num!(deserialize_i32, visit_i32, i32); 764 deserialize_num!(deserialize_i64, visit_i64, i64); 765 deserialize_num!(deserialize_u8, visit_u8, u8); 766 deserialize_num!(deserialize_u16, visit_u16, u16); 767 deserialize_num!(deserialize_u32, visit_u32, u32); 768 deserialize_num!(deserialize_u64, visit_u64, u64); 769 deserialize_f32<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>770 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value> 771 where V: de::Visitor<'de> 772 { 773 visitor.visit_f32(self.to_float("f32").map(|n| n as f32)?) 774 } 775 deserialize_f64<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>776 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value> 777 where V: de::Visitor<'de> 778 { 779 visitor.visit_f64(self.to_float("f64")?) 780 } 781 deserialize_char<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>782 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value> 783 where V: de::Visitor<'de> 784 { 785 let (k, v) = self.pop_key_val()?; 786 let vstr = v.as_str(); 787 match vstr.chars().count() { 788 1 => visitor.visit_char(vstr.chars().next().unwrap()), 789 _ => derr!("Could not deserialize '{}' into char for '{}'.", vstr, k), 790 } 791 } 792 deserialize_str<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>793 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value> 794 where V: de::Visitor<'de> 795 { 796 let s = self.pop_val()?; 797 visitor.visit_str(s.as_str()) 798 } 799 deserialize_string<V>(self, visitor:V) -> Result<V::Value> where V: de::Visitor<'de>800 fn deserialize_string<V>(self, visitor:V) -> Result<V::Value> 801 where V: de::Visitor<'de> 802 { 803 self.deserialize_str(visitor) 804 } 805 deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>806 fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> 807 where V: de::Visitor<'de> 808 { 809 unimplemented!() 810 } 811 deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>812 fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value> 813 where V: de::Visitor<'de> 814 { 815 unimplemented!() 816 } 817 deserialize_option<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>818 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> 819 where V: de::Visitor<'de> 820 { 821 let is_some = match self.stack.last() { 822 None => derr!("Could not deserialize value into unknown key."), 823 Some(it) => it.val.as_ref().map_or(false, |v| v.as_bool()), 824 }; 825 if is_some { 826 visitor.visit_some(self) 827 } else { 828 visitor.visit_none() 829 } 830 } 831 deserialize_unit<V>(self, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>832 fn deserialize_unit<V>(self, _visitor: V) -> Result<V::Value> 833 where V: de::Visitor<'de> 834 { 835 // I don't know what the right thing is here, so just fail for now. 836 panic!("I don't know how to read into a nil value.") 837 } 838 deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>839 fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> 840 where V: de::Visitor<'de> 841 { 842 visitor.visit_unit() 843 } 844 deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>845 fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> 846 where V: de::Visitor<'de> 847 { 848 visitor.visit_newtype_struct(self) 849 } 850 deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>851 fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value> 852 where V: de::Visitor<'de> 853 { 854 unimplemented!() 855 } 856 deserialize_tuple_struct<V>(self, _name: &'static str, _len: usize, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>857 fn deserialize_tuple_struct<V>(self, 858 _name: &'static str, 859 _len: usize, 860 _visitor: V) 861 -> Result<V::Value> 862 where V: de::Visitor<'de> 863 { 864 unimplemented!() 865 } 866 deserialize_map<V>(self, _visitor: V) -> Result<V::Value> where V: de::Visitor<'de>867 fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value> 868 where V: de::Visitor<'de> 869 { 870 unimplemented!() 871 } 872 deserialize_seq<V>(mut self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>873 fn deserialize_seq<V>(mut self, visitor: V) -> Result<V::Value> 874 where V: de::Visitor<'de> 875 { 876 let (key, struct_field, val) = match self.stack.pop() { 877 None => derr!("Could not deserialize value into unknown key."), 878 Some(DeserializerItem {key, struct_field, val}) => (key, struct_field, val), 879 }; 880 let list = val.unwrap_or(List(vec![])); 881 let vals = list.as_vec(); 882 for val in vals.iter().rev() { 883 self.stack 884 .push(DeserializerItem { 885 key: key.clone(), 886 struct_field: struct_field, 887 val: Some(Plain(Some((*val).into()))), 888 }); 889 } 890 visitor.visit_seq(SeqDeserializer::new(&mut self, vals.len())) 891 } 892 deserialize_struct<V>(mut self, _: &str, fields: &'static [&'static str], visitor: V) -> Result<V::Value> where V: de::Visitor<'de>893 fn deserialize_struct<V>(mut self, 894 _: &str, 895 fields: &'static [&'static str], 896 visitor: V) 897 -> Result<V::Value> 898 where V: de::Visitor<'de> 899 { 900 visitor.visit_seq(StructDeserializer::new(&mut self, fields)) 901 } 902 deserialize_enum<V>(self, _name: &str, variants: &[&str], visitor: V) -> Result<V::Value> where V: de::Visitor<'de>903 fn deserialize_enum<V>(self, _name: &str, variants: &[&str], visitor: V) -> Result<V::Value> 904 where V: de::Visitor<'de> 905 { 906 let v = self.pop_val()?.as_str().to_lowercase(); 907 let s = match variants.iter().find(|&n| n.to_lowercase() == v) { 908 Some(s) => s, 909 None => { 910 derr!("Could not match '{}' with any of \ 911 the allowed variants: {:?}", 912 v, 913 variants) 914 } 915 }; 916 visitor.visit_enum(s.into_deserializer()) 917 } 918 deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>919 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> 920 where V: de::Visitor<'de> 921 { 922 self.deserialize_str(visitor) 923 } 924 deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value> where V: de::Visitor<'de>925 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value> 926 where V: de::Visitor<'de> 927 { 928 self.deserialize_any(visitor) 929 } 930 } 931 932 struct SeqDeserializer<'a, 'de: 'a> { 933 de: &'a mut Deserializer<'de>, 934 len: usize, 935 } 936 937 impl<'a, 'de> SeqDeserializer<'a, 'de> { new(de: &'a mut Deserializer<'de>, len: usize) -> Self938 fn new(de: &'a mut Deserializer<'de>, len: usize) -> Self { 939 SeqDeserializer { de: de, len: len } 940 } 941 } 942 943 impl<'a, 'de> de::SeqAccess<'de> for SeqDeserializer<'a, 'de> { 944 type Error = Error; 945 next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> where T: de::DeserializeSeed<'de>946 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> 947 where T: de::DeserializeSeed<'de> 948 { 949 if self.len == 0 { 950 return Ok(None); 951 } 952 self.len -= 1; 953 seed.deserialize(&mut *self.de).map(Some) 954 } 955 size_hint(&self) -> Option<usize>956 fn size_hint(&self) -> Option<usize> { 957 return Some(self.len); 958 } 959 } 960 961 struct StructDeserializer<'a, 'de: 'a> { 962 de: &'a mut Deserializer<'de>, 963 fields: &'static [&'static str], 964 } 965 966 impl<'a, 'de> StructDeserializer<'a, 'de> { new(de: &'a mut Deserializer<'de>, fields: &'static [&'static str]) -> Self967 fn new(de: &'a mut Deserializer<'de>, fields: &'static [&'static str]) -> Self { 968 StructDeserializer { 969 de: de, 970 fields: fields, 971 } 972 } 973 } 974 975 impl<'a, 'de> de::SeqAccess<'de> for StructDeserializer<'a, 'de> { 976 type Error = Error; 977 next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> where T: de::DeserializeSeed<'de>978 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> 979 where T: de::DeserializeSeed<'de> 980 { 981 if self.fields.len() == 0 { 982 return Ok(None); 983 } 984 self.de.push(self.fields[0]); 985 self.fields = &self.fields[1..]; 986 seed.deserialize(&mut *self.de).map(Some) 987 } 988 size_hint(&self) -> Option<usize>989 fn size_hint(&self) -> Option<usize> { 990 return Some(self.fields.len()); 991 } 992 } 993