use crate::{
codegen::{gen_string_mapping, IterableProperties},
error::GeneratorError,
rename::RenameCasing,
DocumentVariant, MappingProperty, OBJECT_TYPE, PROPERTIES_FIELD, TYPE_FIELD,
};
pub(crate) fn gen_adjacently_tagged_enum(
tag: &str,
content: &str,
variants: &[DocumentVariant],
rename_all: Option<RenameCasing>,
) -> Result<(Vec<MappingProperty>, Vec<IterableProperties>), GeneratorError> {
let mut properties = Vec::new();
let mut content_properties = Vec::new();
let mut content_iterable = Vec::new();
properties.push(MappingProperty {
name: tag.to_string(),
mapping: gen_string_mapping(),
});
for variant in variants {
match variant.fields.style {
darling::ast::Style::Tuple => {
for field in &variant.fields.fields {
let ty = &field.ty;
content_iterable.push(IterableProperties {
source: quote::quote! {
<#ty as elastic_mapping::MappingType>::fields()
},
});
}
}
darling::ast::Style::Struct => {
for field in &variant.fields.fields {
content_properties.push(field.gen_mapping(rename_all));
}
}
darling::ast::Style::Unit => {
return Err(GeneratorError::Custom(
"Unit variants are not supported in tagged enums".to_string(),
));
}
}
}
let content_prop_insertions: Vec<_> = content_properties
.into_iter()
.map(|prop| {
let name = prop.name;
let mapping = prop.mapping;
quote::quote! {
content_props.insert(#name.into(), #mapping);
}
})
.collect();
let content_iterable_insertions: Vec<_> = content_iterable
.into_iter()
.map(|it| {
let source = it.source;
quote::quote! {
for (key, field) in #source {
content_props.insert(key, field);
}
}
})
.collect();
let content_mapping = 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 content_props = elastic_mapping::serde_json::Map::default();
#(#content_prop_insertions)*
#(#content_iterable_insertions)*
content_props.into()
});
m.into()
}
};
properties.push(MappingProperty {
name: content.to_string(),
mapping: content_mapping,
});
Ok((properties, vec![]))
}