sky_derive/
lib.rs

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}