optional_command/
optional_command.rsuse std::fmt;
use docopt::Docopt;
use serde::{Deserialize, de::{Deserializer, Error, Visitor}};
const USAGE: &'static str = "
Rust's package manager
Usage:
mycli [<command>]
Options:
-h, --help Display this message
";
#[derive(Debug, Deserialize)]
struct Args {
arg_command: Command,
}
struct CommandVisitor;
impl<'de> Visitor<'de> for CommandVisitor {
type Value = Command;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string A, B or C")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where E: Error
{
Ok(match s {
"" => Command::None,
"A" => Command::A,
"B" => Command::B,
"C" => Command::C,
s => Command::Unknown(s.to_string()),
})
}
}
impl<'de> Deserialize<'de> for Command {
fn deserialize<D>(d: D) -> Result<Command, D::Error>
where D: Deserializer<'de>
{
d.deserialize_str(CommandVisitor)
}
}
#[derive(Debug)]
enum Command {
A,
B,
C,
Unknown(String),
None,
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.deserialize())
.unwrap_or_else(|e| e.exit());
println!("{:?}", args);
}