conservator_macro 0.1.6

conservator macro
Documentation
use darling::FromDeriveInput;
use itertools::Itertools;
use proc_macro_error::abort;
use quote::quote;
use syn::{parse2, Data, DeriveInput};

#[derive(Debug, FromDeriveInput)]
#[darling(attributes(crud))]
struct CreatableOpts {
    ident: syn::Ident,
}

pub(crate) fn handle_creatable(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
    let x1 = parse2::<DeriveInput>(input).unwrap();
    let creatable_opts: CreatableOpts = CreatableOpts::from_derive_input(&x1).unwrap();

    let ident = creatable_opts.ident;

    if let Data::Struct(ref body) = x1.data {
        let fields = body.fields.iter().map(|it| &it.ident).collect::<Vec<_>>();

        let field_list = fields
            .iter()
            .map(|it| format!("{}", it.as_ref().map(|ident| ident.to_string()).expect("ident not found")))
            .join(",");
        let param_list = fields.iter().enumerate().map(|it| it.0).map(|it| format!("${}", it + 1)).join(",");
        let insert_sql = format!("({}) VALUES ({})", field_list, param_list);

        let bind_list = fields.iter().map(|it| {
            quote! { .bind(self. #it)}
        });

        quote! {
            impl ::conservator::Creatable for #ident {
                fn get_insert_sql(&self) -> &str {
                    #insert_sql
                }
                fn build<'q, O>(
                    self,
                    e: ::sqlx::query::QueryAs<'q, ::sqlx::Postgres, O, <::sqlx::Postgres as ::sqlx::database::HasArguments<'q>>::Arguments,>,
                ) -> ::sqlx::query::QueryAs<'q, ::sqlx::Postgres, O, <::sqlx::Postgres as ::sqlx::database::HasArguments<'q>>::Arguments,> {
                    e
                    #(#bind_list)*
                }
            }
        }
    } else {
        abort! { x1,
            "enum does not support"
        }
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn compile_fail() {
        let t = trybuild::TestCases::new();
        t.compile_fail("tests/fail/*.rs");
    }
}