Skip to main content

break_block_macro/
lib.rs

1use quote::quote;
2
3/// Behaves like the `?` operator, unwrapping a [Result] or [Option] but will break out of a
4/// scope labeled with the `'block` label if a [None] or [Err] is encountered.  This can be used
5/// to achieve something that resembles try-catch.
6///
7/// ```
8/// use break_block_macro::bb;
9///
10/// let result = 'block: {
11///     let one = bb!(Ok("one"));
12///     assert_eq!(one, "one");
13///
14///     let _two = bb!(Err("two"));
15///     Ok("three")
16/// };
17/// assert_eq!(result, Err("two"));
18/// ```
19//
20// NOTE: This is a proc macro to get around scoping hygene for declarative macros that doesn't
21//  allow labels to cross scope bounds
22#[proc_macro]
23pub fn bb(arg: proc_macro::TokenStream) -> proc_macro::TokenStream {
24    let arg: proc_macro2::TokenStream = arg.into();
25    quote! {
26        {
27            let result = #arg;
28            if someok::IsSuccess::is_success(&result) {
29                result.unwrap()
30            } else {
31                break 'block result
32            }
33        }
34    }.into()
35}