optional_command/
optional_command.rs1use std::fmt;
8
9use docopt::Docopt;
10use serde::{Deserialize, de::{Deserializer, Error, Visitor}};
11
12const USAGE: &'static str = "
14Rust's package manager
15
16Usage:
17 mycli [<command>]
18
19Options:
20 -h, --help Display this message
21";
22
23#[derive(Debug, Deserialize)]
24struct Args {
25 arg_command: Command,
26}
27
28struct CommandVisitor;
29
30impl<'de> Visitor<'de> for CommandVisitor {
31 type Value = Command;
32
33 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
34 formatter.write_str("a string A, B or C")
35 }
36
37 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
38 where E: Error
39 {
40 Ok(match s {
41 "" => Command::None,
42 "A" => Command::A,
43 "B" => Command::B,
44 "C" => Command::C,
45 s => Command::Unknown(s.to_string()),
46 })
47 }
48}
49
50impl<'de> Deserialize<'de> for Command {
51 fn deserialize<D>(d: D) -> Result<Command, D::Error>
52 where D: Deserializer<'de>
53 {
54 d.deserialize_str(CommandVisitor)
55 }
56}
57
58#[derive(Debug)]
59enum Command {
60 A,
61 B,
62 C,
63 Unknown(String),
64 None,
65}
66
67fn main() {
68 let args: Args = Docopt::new(USAGE)
69 .and_then(|d| d.deserialize())
70 .unwrap_or_else(|e| e.exit());
71 println!("{:?}", args);
72}