use common::{Descriptor, GenericDescriptor};
use fields::enum_variant::*;
use helpers::compute_version;
use quote::quote;
pub(crate) type EnumDescriptor = GenericDescriptor<EnumVariant>;
impl Descriptor for EnumDescriptor {
fn generate_serializer(&self) -> proc_macro2::TokenStream {
let mut versioned_serializers = proc_macro2::TokenStream::new();
for i in 1..=self.version {
let mut versioned_serializer = proc_macro2::TokenStream::new();
for field in &self.fields {
versioned_serializer.extend(field.generate_serializer(i));
}
versioned_serializers.extend(quote! {
#i => {
match self {
#versioned_serializer
}
}
});
}
versioned_serializers
}
fn generate_deserializer(&self) -> proc_macro2::TokenStream {
let mut versioned_deserializers = proc_macro2::TokenStream::new();
for field in &self.fields {
versioned_deserializers.extend(field.generate_deserializer());
}
quote! {
let variant_index = <u32 as Versionize>::deserialize(&mut reader, version_map, app_version)?;
match variant_index {
#versioned_deserializers
x => return Err(VersionizeError::Deserialize(format!("Unknown variant_index {}", x)))
}
}
}
fn version(&self) -> u16 {
self.version
}
fn ty(&self) -> String {
self.ty.to_string()
}
}
impl EnumDescriptor {
pub fn new(input: &syn::DataEnum, ident: syn::Ident) -> Self {
let mut descriptor = EnumDescriptor {
ty: ident,
version: 1,
fields: vec![],
};
descriptor.parse_enum_variants(&input.variants);
descriptor.version = compute_version(&descriptor.fields);
descriptor
}
fn parse_enum_variants(
&mut self,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) {
for (index, variant) in variants.iter().enumerate() {
self.fields
.push(EnumVariant::new(self.version, variant, index as u32));
}
}
}