pub struct ParseOptional<P> {
pub(crate) inner: P,
pub(crate) catch: bool,
}Expand description
Fields§
§inner: P§catch: boolImplementations§
Source§impl<P> ParseOptional<P>
impl<P> ParseOptional<P>
Sourcepub fn catch(self) -> Self
pub fn catch(self) -> Self
Handle parse failures for optional parsers
Can be useful to decide to skip parsing of some items on a command line.
When parser succeeds - catch version would return a value as usual
if it fails - catch would restore all the consumed values and return None.
There’s several structures that implement this attribute: ParseOptional, ParseMany
and ParseSome, behavior should be identical for all of them.
Those examples are very artificial and designed to show what difference catch makes, to
actually parse arguments like in examples you should parse or construct
enum with alternative branches
Combinatoric example
#[derive(Debug, Clone)]
pub struct Options {
height: Option<usize>,
height_str: Option<String>,
width: Option<usize>,
width_str: Option<String>,
}
pub fn options() -> OptionParser<Options> {
// contains catch
let height = long("height")
.help("Height of a rectangle")
.argument::<usize>("PX")
.optional()
.catch();
let height_str = long("height").argument::<String>("PX").optional().hide();
// contains no catch
let width = long("width")
.help("Width of a rectangle")
.argument::<usize>("PX")
.optional();
let width_str = long("width").argument::<String>("PX").optional().hide();
construct!(Options {
height,
height_str,
width,
width_str
})
.to_options()
}
fn main() {
println!("{:?}", options().run())
}Derive example
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
#[bpaf(long, argument("PX"), optional, catch)]
/// Height of a rectangle
height: Option<usize>,
#[bpaf(long("height"), argument("PX"), optional, hide)]
height_str: Option<String>,
#[bpaf(long, argument("PX"), optional)]
/// Width of a rectangle
width: Option<usize>,
#[bpaf(long("width"), argument("PX"), optional, hide)]
width_str: Option<String>,
}
fn main() {
println!("{:?}", options().run())
}Output
Despite parser producing a funky value - help looks like you would expect from a parser that takes two values
Usage: app [--height=PX] [--width=PX]
- --height=PX
- Height of a rectangle
- --width=PX
- Width of a rectangle
- -h, --help
- Prints help information
When executed with no parameters it produces four None values - all parsers succeed by the
nature of them being optional
Options { height: None, height_str: None, width: None, width_str: None }
When executed with expected parameters fields with usize get their values
Options { height: Some(100), height_str: None, width: Some(100), width_str: None }
With incorrect value for --height parameter inner part of height parser fails, optional
combined with catch handles this failure and produces None without consuming value from the
command line. Parser height_str runs next and consumes the value as a string
Options { height: None, height_str: Some("ten"), width: None, width_str: None }
In case of wrong --width - parser width fails, parser for optional sees this as a
“value is present but not correct” and propagates the error outside, execution never reaches
width_str parser
Error: couldn't parse ten: invalid digit found in string