1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
#![recursion_limit="128"] extern crate proc_macro; use quote::{quote, quote_spanned}; use syn::{parse_macro_input, DeriveInput}; use syn::spanned::Spanned; use deriving::struct_fields; use proc_macro::TokenStream; #[proc_macro_derive(IntoTree, attributes(bm))] pub fn into_tree_derive(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident; let fields = struct_fields(&input.data) .expect("Not supported derive type") .iter() .map(|f| { let name = &f.ident; quote_spanned! { f.span() => { vector.push(bm_le::IntoTree::into_tree(&self.#name, db)?); } } }); let expanded = quote! { impl<DB> bm_le::IntoTree<DB> for #name where DB: bm_le::Backend<Intermediate=bm_le::Intermediate, End=bm_le::End> { fn into_tree(&self, db: &mut DB) -> Result<bm_le::ValueOf<DB>, bm_le::Error<DB::Error>> { let mut vector = Vec::new(); #(#fields)* bm_le::utils::vector_tree(&vector, db, None) } } }; proc_macro::TokenStream::from(expanded) } #[proc_macro_derive(FromTree, attributes(bm))] pub fn from_tree_derive(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); let name = input.ident; let fields = struct_fields(&input.data) .expect("Not supported derive type") .iter() .enumerate() .map(|(i, f)| { let name = &f.ident; quote_spanned! { f.span() => #name: bm_le::FromTree::from_tree( &vector.get(db, #i)?, db, )?, } }); let fields_count = struct_fields(&input.data) .expect("Not supported derive type") .iter() .count(); let expanded = quote! { impl<DB> bm_le::FromTree<DB> for #name where DB: bm_le::Backend<Intermediate=bm_le::Intermediate, End=bm_le::End> { fn from_tree( root: &bm_le::ValueOf<DB>, db: &DB, ) -> Result<Self, bm_le::Error<DB::Error>> { use bm_le::Leak; let vector = bm_le::DanglingVector::<DB>::from_leaked( (root.clone(), #fields_count, None) ); Ok(Self { #(#fields)* }) } } }; proc_macro::TokenStream::from(expanded) }