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 the fn_expr and fn_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.