1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{parse_macro_input, Data, DeriveInput, Fields};
6
7#[proc_macro_derive(Query)]
8pub fn derive_query(input: TokenStream) -> TokenStream {
9 let input = parse_macro_input!(input as DeriveInput);
10 let name = input.ident;
11 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
12 let ret = match input.data {
13 Data::Struct(data_struct) => match data_struct.fields {
14 Fields::Named(fields) => {
15 let field_names: Vec<_> = fields.named.iter().map(|f| &f.ident).collect();
16 assert!(!field_names.is_empty(), "can't derive on empty field");
17 quote! {
18 impl #impl_generics ::skytable::query::SQParam for #name #ty_generics #where_clause {
19 fn append_param(&self, q: &mut Vec<u8>) -> usize {
20 let mut size = 0;
21 #(size += ::skytable::query::SQParam::append_param(&self.#field_names, q);)*
22 size
23 }
24 }
25 }
26 }
27 _ => unimplemented!(),
28 },
29 _ => unimplemented!(),
30 };
31 TokenStream::from(ret)
32}
33
34#[proc_macro_derive(Response)]
35pub fn derive_response(input: TokenStream) -> TokenStream {
36 let input = parse_macro_input!(input as DeriveInput);
37 let name = input.ident;
38 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
39 let ret = match input.data {
40 Data::Struct(data_struct) => match data_struct.fields {
41 Fields::Named(fields) => {
42 let field_names: Vec<_> = fields.named.iter().map(|f| &f.ident).collect();
43 assert!(!field_names.is_empty(), "can't derive on empty field");
44 let tuple_pattern = if field_names.len() == 1 {
45 quote! { (#(#field_names),*,) }
46 } else {
47 quote! { (#(#field_names),*) }
48 };
49 let struct_instantiation = quote! { Self { #(#field_names),* } };
50 quote! {
51 impl #impl_generics skytable::response::FromResponse for #name #ty_generics #where_clause {
52 fn from_response(resp: skytable::response::Response) -> skytable::ClientResult<Self> {
53 let #tuple_pattern = skytable::response::FromResponse::from_response(resp)?;
54 Ok(#struct_instantiation)
55 }
56 }
57 impl #impl_generics skytable::response::FromRow for #name #ty_generics #where_clause {
58 fn from_row(row: skytable::response::Row) -> skytable::ClientResult<Self> {
59 let #tuple_pattern = skytable::response::FromRow::from_row(row)?;
60 Ok(#struct_instantiation)
61 }
62 }
63 }
64 }
65 _ => unimplemented!(),
66 },
67 _ => unimplemented!(),
68 };
69 TokenStream::from(ret)
70}