kimari_derive/
lib.rs

1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, Data, DeriveInput, Field};
6
7#[proc_macro_derive(Context)]
8pub fn derive_context(input: TokenStream) -> TokenStream {
9    let input = parse_macro_input!(input as DeriveInput);
10    let data = match input.data {
11        Data::Struct(s) => s,
12        _ => panic!("Deriving kimari::Context only supports a struct."),
13    };
14
15    let arms = data
16        .fields
17        .iter()
18        .map(|Field { ident, .. }| {
19            quote! {
20                stringify!(#ident) => self.#ident.get_from_context(path),
21            }
22        })
23        .collect::<Vec<_>>();
24
25    let name = &input.ident;
26    let output = quote! {
27        impl kimari::context::Context for #name {
28            fn get_from_context<'a, I>(&self, path: I) -> Result<kimari::Value, kimari::context::Error>
29            where
30                I: IntoIterator<Item = &'a str>,
31            {
32                let mut path = path.into_iter();
33                let name = path.next();
34                match name {
35                    Some(s) => match s {
36                        #(#arms)*
37                        _ => return Err(kimari::context::Error::UnexpectedPath([s].into()))
38                    },
39                    _ => unimplemented!("Value representation of structs is not supported yet."),
40                }
41            }
42        }
43    };
44
45    output.into()
46}