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}