J'aimerais que StructOpt fonctionne avec des énumérations de telle sorte que chaque fois qu'un utilisateur passe -d dimanche , il soit analysé comme un Day :: Sunday :
fn parse_day(day: &str) -> Result<Day, ParseError> {
match day {
"sunday" => Ok(Day::Sunday),
_ => Ok(Day::Monday)
}
Err("Could not parse a day")
}
Ma meilleure solution actuelle consiste à utiliser Option comme type et à passer un parse_day () :
#[macro_use]
extern crate structopt;
use std::path::PathBuf;
use structopt::StructOpt;
// My enum
enum Day {
Sunday, Monday
}
#[derive(Debug, StructOpt)]
#[structopt(name = "example", about = "An example of StructOpt usage.")]
struct Opt {
/// Set speed
#[structopt(short = "s", long = "speed", default_value = "42")]
speed: f64,
/// Input file
#[structopt(parse(from_os_str))]
input: PathBuf,
/// Day of the week
#[structopt(short = "d", long = "day", default_value = Day::Monday)]
day: Day,
}
fn main() {
let opt = Opt::from_args();
println!("{:?}", opt);
}
3 Réponses :
Struct-opt accepte tout type qui implémente FromStr code> , qui n'est pas loin de votre fonction parse_day :
#[structopt(short = "d", long = "day", default_value = "monday")] day: Day,
De plus, la default_value doit être une chaîne , qui sera interprété en un Jour en utilisant from_str.
use std::str::FromStr;
impl FromStr for Day {
type Err = ParseError;
fn from_str(day: &str) -> Result<Self, Self::Err> {
match day {
"sunday" => Ok(Day::Sunday),
"monday" => Ok(Day::Monday),
_ => Err("Could not parse a day"),
}
}
}
Au moins avec Rust 1.46, ParseError ne semble pas exister (?).
Le message d'erreur est:
/// Day of the week #[structopt(short = "d", long = "day", parse(try_from_str = "parse_day"), default_value = "monday")] day: Day,
Vous pouvez résoudre ce problème en implémentant FromStr pour Day (voir réponse de kennytm ), comme le suggère le message, ou en définissant une fonction d'analyse pour Day :
fn parse_day(src: &str) -> Result<Day, String> {
match src {
"sunday" => Ok(Day::Sunday),
"monday" => Ok(Day::Monday),
_ => Err(format!("Invalid day: {}", src))
}
}
Et en le spécifiant avec l'attribut try_from_str :
error[E0277]: the trait bound `Day: std::str::FromStr` is not satisfied --> src/main.rs:22:17 | 22 | #[derive(Debug, StructOpt)] | ^^^^^^^^^ the trait `std::str::FromStr` is not implemented for `Day` | = note: required by `std::str::FromStr::from_str`
La meilleure réponse de toutes! Manque juste insensible à la casse :)
L'insensibilité à la casse @decades n'a pas été mentionnée dans la question et ce n'est qu'un attribut supplémentaire pour l'activer.
Je l'ai résolu comme ceci: match src.to_lowercase (). As_ref () {...
l'approche de @ kennytm fonctionne, mais la macro arg_enum! est une manière plus concise de le faire, comme démontré dans cet exemple de structopt :
arg_enum! {
#[derive(Debug)]
enum Day {
Sunday,
Monday
}
}
#[derive(StructOpt, Debug)]
struct Opt {
/// Important argument.
#[structopt(possible_values = &Day::variants(), case_insensitive = true)]
i: Day,
}
fn main() {
let opt = Opt::from_args();
println!("{:?}", opt);
}
Cela vous permettra d'analyser les jours de la semaine comme dimanche ou dimanche.