option!() { /* proc-macro */ }
Expand description
a macro for making debugging more ergonomic when handling Option<T>
results
§Anotomy of the option!
macro
The option!
macro consists of a @when
section and one to three optional evaluation
sections @some
, @debug
and/or @none
, at least one must be defined.
When the option!
macro is used in place of an expression and the intention is to
assign the Some(T)
value, the @when
section can be skipped and replaced with a
simplified @some
section, which behaves as the @when
section, * see below for
more details
* code block <expr>
s, can not be terminated with a
;
, i.e. { ... }
;
§@when
The @when
section is defined as [@when] <expr>[?][;]
@when
- optional, section identifier<expr>
- an expression that must evaluate to anOption<T>
value[?]
- optional, try operator, returnsNone
after completing@debug
and/or@none
[;]
- optional, section terminator
Example A:
@when foo();
Example B:
@when foo()?;
§@some
The @some
section is defined as @some <[[(identifier) =>]<message|expr>[;]|[<expr>[?][;]]]
@some
- required section identifier- In Success Mode
[(identifier) =>]
- optional, custom defined identifier which maps to theSome(T)
value<message|expr>
message
- outputs tostdout
with aprintln!
statement, therefore has the sameargs
expr
- any expression to evaluate
* can accessSome(T)
value with thesome
keyword or custom identifier
[;]
- optional, section terminator
* only evaluates if the result of the@when
expression isOption::Some
Example A:
@some "success: {}", some;
Example B:
@some (foo) => "success: {}", foo;
Example C:
@some (foo) => { success(foo); }
- In Expression Mode
<expr>
- an expression that must evaluate to anOption<T>
value[?]
- optional, try operator, returnsNone
after completing@debug
and/or@none
[;]
- optional, section terminator
Example A:
@some foo();
Example B:
@some foo()?;
§@debug
The @debug
section is defined as @debug <message>[;]
* only evaluates if the result of the @when
expression is Option::None
@debug
- required section identifiermessage
- outputs tostdout
with aprintln!
statement, therefore has the sameargs
[;]
- optional, section terminator
Example:
@debug "dbg: foo failed!";
§@none
The @none
section is defined as @none [<message>[;]][<expr>][;]
, must
provide at least a message
and/or expr
* only evaluates if the result of the @when
expression is Option::None
@none
- required section identifier[message][;]
- optional, outputs to_stderr
with aeprintln!
statement, therefore accepts the sameargs
* requires the;
terminator if an<expr>[;]
is also defined[<expr>]
- optional, any expression to evaluate[;]
- optional, section terminator
Example A:
@none { on_fail_baz(); }
Example B:
@none "err: foo failed!"
Example C:
@none "err: foo failed!"; { on_fail_baz(); }
§Example
- Success Mode
use macrofied_toolbox::option;
fn main() {
let file_name = "foo.txt";
if let None = example(file_name) {
eprintln!("failed to create {:?} file!", file_name);
exit(-1);
}
}
fn example(file_name: &str) -> Option<()> {
option! {
@when File::create(file_name).ok()?;
@some (file) => {
let mut out = BufWriter::new(file);
writeln!(out, "some content").ok()?;
writeln!(out, "some more content").ok()?;
}
@debug "problem creating file: {:?}", file_name;
@none "{:?} failed; attempting recovery ...", file_name;
recovery_from_fail(file_name);
}
Some(())
}
fn recovery_from_fail(_: &str) {
// some very import recovery logic
}
- Expression Mode
use macrofied_toolbox::option;
let result = option! {
@some computed_value(21)
@debug "Invalid input"
@none 0
};
assert_eq!(42, result);
fn computed_value(input: usize) -> Option<usize> {
if input == 21 {
Some(input * 2)
} else {
None
}
}