rusqlite-struct-derive 0.1.1

Derive crate for rusqlite-struct
Documentation
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Data, Fields};

#[proc_macro_derive(RusqliteStruct)]
pub fn rusqlite_struct(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    // The name of the struct.
    let name = input.ident;

    let field_names: Vec<String> = match input.data {
        Data::Struct(ref data_struct) => match &data_struct.fields {
            Fields::Named(fields_named) => fields_named
                .named
                .iter()
                .map(|f| f.ident.as_ref().unwrap().to_string())
                .collect(),
            _ => panic!("RusqliteStruct only supports structs with named fields."),
        },
        _ => panic!("RustqliteStruct can only be derived for structs."),
    };

    let field_names_lit: Vec<proc_macro2::TokenStream> = field_names
        .iter()
        .map(|f| quote! { #f })
        .collect();

    let expanded = quote! {
        const _: () = {
            // Fail if Serialize and Deserialize are not derived.
            trait _Check: serde::Serialize + for<'de> serde::Deserialize<'de> {}
            impl _Check for #name {}
        };

        impl rusqlite_struct::RusqliteStruct for #name {
            fn struct_name() -> &'static str {
                stringify!(#name)
            }

            fn field_names() -> &'static [&'static str] {
                &[#(#field_names_lit),*]
            }
        }
    };

    TokenStream::from(expanded)
}