extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn defer(token_stream: TokenStream) -> TokenStream {
let expr: syn::Expr = syn::parse_macro_input!(token_stream as syn::Expr);
let uid = uuid::Uuid::new_v4();
let name = format!("__flowutils_{}", uid).replace('-', "_");
let defer_guard_type = syn::Ident::new(&name, proc_macro2::Span::call_site());
let defer_guard_var = syn::Ident::new(&format!("{}_", &name), proc_macro2::Span::call_site());
(quote::quote! {
struct #defer_guard_type;
impl Drop for #defer_guard_type {
fn drop(&mut self) {
#expr
}
}
let #defer_guard_var = #defer_guard_type;
})
.into()
}
fn parse_unwrap(input: syn::parse::ParseStream) -> syn::Result<(syn::Expr, syn::Arm)> {
let expr: syn::Expr = input.parse()?;
let _: syn::Token![,] = input.parse()?;
let arm: syn::Arm = input.parse()?;
Ok((expr, arm))
}
#[proc_macro]
pub fn unwrap_pattern(token_stream: TokenStream) -> TokenStream {
let (expr, arm) = syn::parse_macro_input!(token_stream with parse_unwrap);
(quote::quote! {
match #expr {
#arm,
_ => panic!("unwrap(..) failed"),
}
})
.into()
}
#[proc_macro]
pub fn try_pattern(token_stream: TokenStream) -> TokenStream {
let (expr, mut arm) = syn::parse_macro_input!(token_stream with parse_unwrap);
let old_body = arm.body;
arm.body = syn::parse_quote! {
Ok(#old_body)
};
(quote::quote! {
match #expr {
#arm,
_ => Err("try_pattern() failed"),
}
})
.into()
}