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
93
94
95
96
97
98
99
use std::convert::TryFrom;
use attr::FieldAttr;
use proc_macro::TokenStream;
use quote::ToTokens;
use syn::{parse_macro_input, parse_quote, spanned::Spanned, DeriveInput};
#[macro_use]
extern crate derive_builder;
mod attr;
mod convert;
mod key;
mod query;
mod split_by;
type Parser = fn(vis: syn::Visibility, name: syn::Ident, generics: syn::Generics, attrs: Vec<syn::Attribute>, fields: syn::FieldsNamed) -> syn::Result<proc_macro2::TokenStream>;
fn derive(input: TokenStream, parser: Parser) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let span = input.span();
let DeriveInput { attrs, vis, ident, generics, data } = input;
match data {
syn::Data::Struct(s) => match s.fields {
syn::Fields::Named(fields) => match parser(vis, ident, generics, attrs, fields) {
Ok(t) => t.into_token_stream(),
Err(e) => e.to_compile_error(),
},
syn::Fields::Unnamed(_) => syn::Error::new(span, "tuple structs not supported").into_compile_error(),
syn::Fields::Unit => syn::Error::new(span, "unit structs not supported").into_compile_error(),
},
syn::Data::Enum(_) => syn::Error::new(span, "enums not supported").into_compile_error(),
syn::Data::Union(_) => syn::Error::new(span, "unions not supported").into_compile_error(),
}
.into()
}
#[proc_macro_derive(Key, attributes(nitro))]
pub fn derive_key(input: TokenStream) -> TokenStream {
derive(input, key::derive)
}
#[proc_macro_derive(Query, attributes(nitro))]
pub fn derive_query(input: TokenStream) -> TokenStream {
derive(input, query::derive)
}
#[proc_macro_derive(Attributes, attributes(nitro))]
pub fn derive_convert(input: TokenStream) -> TokenStream {
derive(input, convert::derive)
}
#[derive(Clone, Copy)]
struct D;
impl From<D> for syn::Ident {
fn from(_: D) -> Self {
parse_quote!(__NitroglycerinDynamoDBClient)
}
}
impl quote::ToTokens for D {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
syn::Ident::from(*self).to_tokens(tokens);
}
}
#[derive(Clone)]
struct NamedField {
pub attrs: FieldAttr,
pub name: syn::Ident,
pub ty: syn::Type,
}
impl TryFrom<syn::Field> for NamedField {
type Error = syn::Error;
fn try_from(field: syn::Field) -> syn::Result<Self> {
let syn::Field { ident, attrs, ty, .. } = field;
let attrs = FieldAttr::parse_attrs(attrs)?;
Ok(Self { attrs, name: ident.unwrap(), ty })
}
}
#[derive(Clone)]
struct Column {
pub ident: syn::Ident,
pub name: String,
pub ty: syn::Type,
}
impl From<NamedField> for Column {
fn from(f: NamedField) -> Self {
Self {
name: f.attrs.rename.as_ref().map(|l| l.value()).unwrap_or_else(|| f.name.to_string()),
ident: f.name,
ty: f.ty,
}
}
}