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)
}