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