Macro fn_block::fn_try [−][src]
macro_rules! fn_try { ($body:expr => catch { $($err_pat:pat => $pat_bod:expr),+ }) => { ... }; }
This macro wraps a given rust code expression into a closure and
directly calls the closure. The result type of the expression is expected
to be an "unwrapped" sucess value (not a Result
type).
The error case (a failing case of a ?
operator) must be handled
(and recovered to a success type value) by a following => catch
block.
- Note 1: Under the hood the result value of the expression will automatically wrapped
into a
Result::Ok
, which is different from how thefn_expr
andfn_block
macros work! - Note 2: This macro is an unstable API to make use of it, enable the crate feature "unproven".
Example:
use std::num::ParseIntError; use std::str::Utf8Error; use std::str::from_utf8; enum ConvertErr { StrParseErr, IntParseErr } impl From<Utf8Error> for ConvertErr { fn from(_: Utf8Error) -> ConvertErr { ConvertErr::StrParseErr } } impl From<ParseIntError> for ConvertErr { fn from(_: ParseIntError) -> ConvertErr { ConvertErr::IntParseErr } } let s: &[u8] = &[0x0020, 0x0034, 0x0032]; let i = fn_try! { from_utf8(s)?.trim().parse::<u32>()? => catch { ConvertErr::StrParseErr => 0u32, ConvertErr::IntParseErr => u32::max_value() } }; assert_eq!(42, i);
Depending on the error type used in the catch block the type is inferred
which error type the errors raised in the closure are converted into. This
is part of the ?
operator semantics. Note that this also implies, that
the _
pattern cannot be used as the only catch pattern for the error,
since in this case the error type cannot be inferred.
It is advised to use a crate like failure
for error management/conversion.
Note of Caution
Note that this API may be subject of change! The names may change, and the automatic wrapping of result value may disappear. This functionality may be controversial and feedback is welcome if this functionality should stay.
Internal workings
The returned Result
from the closure will be matched. If an Ok
is
wrapped return value will be returned from the fn_try
. If the returned
result wrapps an error, the error type must be handled by the => catch
block
Following the expression given by the user. This is basically a match block where
the user has to define recovery cases matching error types to the success return type.
Design descisions
The name of the macro and the => catch
block are chosen to be similar to the ones
chosen for RFC 2388 and should still work with the "Rust 2018 Edition".
Unfortunately the macro name may confuse users of the deprecated try!
macro, but it looks similar to try
/catch
blocks in other languages. The automatic
wrapping of the sucessful result value into a Result::Ok
may also be controversial
and even the author is not entirely sure if this is the best way to model the API.
However, RFC 2388 already seems to settle on the automatic wrapping and the resulting
code may look more familiar to people comming from other languages.