use proc_macro2::TokenStream;
use syn::{Generics, Ident};
use crate::{MappingProperty, OBJECT_TYPE, PROPERTIES_FIELD, TYPE_FIELD};
pub(crate) struct IterableProperties {
pub(crate) source: TokenStream,
}
pub(crate) fn gen_field_type_fn(ty: &str) -> TokenStream {
quote::quote! {
fn field_type() -> &'static str {
#ty
}
}
}
pub(crate) fn gen_properties_insertions(properties: Vec<MappingProperty>) -> Vec<TokenStream> {
properties
.into_iter()
.map(|prop| {
let name = prop.name;
let mapping = prop.mapping;
quote::quote! {
acc.insert(#name.into(), #mapping);
}
})
.collect()
}
pub(crate) fn gen_iterable_insertions(iterable: Vec<IterableProperties>) -> Vec<TokenStream> {
iterable
.into_iter()
.map(|it| {
let source = it.source;
quote::quote! {
for (key, field) in #source {
acc.insert(key, field);
}
}
})
.collect()
}
pub(crate) fn gen_mapping_impl(
ident: &Ident,
generics: &Generics,
field_type: &str,
properties: Vec<MappingProperty>,
iterable: Vec<IterableProperties>,
) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let field_type_fn = gen_field_type_fn(field_type);
let property_insertions = gen_properties_insertions(properties);
let iterable_insertions = gen_iterable_insertions(iterable);
quote::quote! {
impl #impl_generics elastic_mapping::MappingType for #ident #ty_generics #where_clause {
#field_type_fn
fn fields() -> elastic_mapping::serde_json::Map<String, elastic_mapping::serde_json::Value> {
let mut acc = elastic_mapping::serde_json::Map::new();
#(#property_insertions)*
#(#iterable_insertions)*
acc
}
}
impl #impl_generics elastic_mapping::MappingObject for #ident #ty_generics #where_clause { }
}
}
pub(crate) fn gen_simple_mapping_impl(
ident: &Ident,
generics: &Generics,
field_type: &str,
) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let field_type_fn = gen_field_type_fn(field_type);
quote::quote! {
impl #impl_generics elastic_mapping::MappingType for #ident #ty_generics #where_clause {
#field_type_fn
}
}
}
pub(crate) fn gen_object_mapping(properties: Vec<TokenStream>) -> TokenStream {
quote::quote! {{
let mut m = elastic_mapping::serde_json::Map::default();
m.insert(#TYPE_FIELD.into(), #OBJECT_TYPE.into());
m.insert(#PROPERTIES_FIELD.into(), {
let mut prop = elastic_mapping::serde_json::Map::default();
#(#properties;)*
prop.into()
});
m.into()
}}
}
pub(crate) fn gen_string_mapping() -> TokenStream {
quote::quote! {
<::std::string::String as elastic_mapping::MappingType>::mapping().into()
}
}