leveldb_orm_derive/
lib.rs1use proc_macro::TokenStream;
29use quote::quote;
30use syn::{parse_macro_input, spanned::Spanned, Data, DeriveInput, Error, Result};
31
32#[proc_macro_derive(LeveldbOrm, attributes(leveldb_key))]
33pub fn derive(input: TokenStream) -> TokenStream {
34 let input = parse_macro_input!(input as DeriveInput);
35 derive_orm(input).map_or_else(|e| TokenStream::from(e.to_compile_error()), |r| r)
36}
37
38fn derive_orm(input: DeriveInput) -> Result<TokenStream> {
39 let span = input.span();
40 let fields = if let Data::Struct(data_struct) = input.data {
41 data_struct.fields
42 } else {
43 return Err(Error::new(span, "LeveldbOrm macro for Struct only"));
44 };
45
46 let mut keys = parse::parse_leveldb_key(&input.attrs)
47 .ok_or_else(|| Error::new(span, "Need attributr: `#[leveldb_key(key1, key2, ...)]`"))?;
48 let mut key_types = parse::parse_key_types(&keys, &fields)?;
49
50 let (keys, key_types, key_types_ref) = if key_types.len() == 1 {
51 let key = keys.pop().unwrap();
52 let key_type = key_types.pop().unwrap();
53 (
54 quote! { &self.#key },
55 quote! {#key_type},
56 quote! {&'a #key_type},
57 )
58 } else {
59 (
60 quote! { (#(&self.#keys,)*) },
61 quote! {(#(#key_types,)*)},
62 quote! {(#(&'a #key_types,)*)},
63 )
64 };
65 let ident = input.ident;
66
67 let res = quote! {
68 impl<'a> leveldb_orm::KeyOrm<'a> for #ident {
69 type KeyType = #key_types;
70 type KeyTypeRef = #key_types_ref;
71
72 #[inline]
73 fn key(&self) -> leveldb_orm::Result<leveldb_orm::EncodedKey<Self>> {
74 Self::encode_key(#keys)
75 }
76 }
77 };
78 Ok(res.into())
79}
80
81mod parse {
82 use syn::{Attribute, Error, Fields, Ident, Result, Type};
83
84 pub fn parse_leveldb_key(attrs: &[Attribute]) -> Option<Vec<Ident>> {
85 attrs.iter().find_map(|attr| {
86 if attr.path().is_ident("leveldb_key") {
87 let mut keys = vec![];
88 attr.parse_nested_meta(|meta| {
89 if let Some(key) = meta.path.get_ident() {
90 keys.push(key.clone());
91 }
92 Ok(())
93 })
94 .unwrap();
95 (!keys.is_empty()).then_some(keys)
96 } else {
97 None
98 }
99 })
100 }
101
102 pub fn parse_key_types(keys: &[Ident], fields: &Fields) -> Result<Vec<Type>> {
103 let mut res = vec![];
104 for key in keys {
105 let ty = fields
106 .iter()
107 .find_map(|field| {
108 field
109 .ident
110 .as_ref()
111 .filter(|ident| ident == &key)
112 .map(|_| field.ty.clone())
113 })
114 .ok_or_else(|| {
115 Error::new(
116 key.span(),
117 format!("leveldb_key: \"{key}\" not found in struct.",),
118 )
119 })?;
120 res.push(ty);
121 }
122 Ok(res)
123 }
124}