lazy_borink_derive/
lib.rs1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, Data, DeriveInput, Fields};
6
7#[proc_macro_derive(UnwrapLazy)]
8pub fn unwrap_lazy_derive(input: TokenStream) -> TokenStream {
9 let input = parse_macro_input!(input as DeriveInput);
10
11 let name = &input.ident;
12 let generics = &input.generics;
13 let unwrap_lazy_impl = generate_unwrap_lazy_impl(&input.data, name);
14
15 let expanded = quote! {
16 const _: () = {
17 use rmp_serde::decode::Error as UnwrapLazyError;
18 #[automatically_derived]
19 impl #generics UnwrapLazy for #name #generics {
20 fn try_unwrap_lazy(self) -> Result<Self, UnwrapLazyError> {
21 Ok(#unwrap_lazy_impl)
22 }
23 }
24 };
25 };
26
27 TokenStream::from(expanded)
28}
29
30fn generate_unwrap_lazy_impl(data: &Data, name: &syn::Ident) -> proc_macro2::TokenStream {
31 match data {
32 Data::Struct(data_struct) => {
33 let fields = match &data_struct.fields {
34 Fields::Named(fields) => &fields.named,
35 _ => panic!("UnwrapLazy can only be derived for structs with named fields"),
36 };
37
38 let field_unwraps = fields.iter().map(|field| {
39 let field_name = &field.ident;
40 quote! {
41 #field_name: self.#field_name.try_unwrap_lazy()?,
42 }
43 });
44
45 quote! {
46 #name {
47 #(#field_unwraps)*
48 }
49 }
50 }
51 _ => panic!("UnwrapLazy can only be derived for structs"),
52 }
53}