Support for serde::Serialize
This commit is contained in:
1 parent
867b09a1fe
commit
46dac98882
6 files changed
+120
-14
No files matched your search
@@ -2,7 +2,6 @@
|
||||
//! to strings and vice-versa.
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use std::iter;
|
||||
|
||||
use proc_macro2::Ident;
|
||||
use quote::quote;
|
||||
@@ -10,7 +9,7 @@ use syn::{Data, DataEnum, DeriveInput};
|
||||
|
||||
use error::{MacroError, MacroResult};
|
||||
|
||||
use crate::enums::{Variant, VariantType, VariantConstructor};
|
||||
use crate::enums::{Variant, VariantType};
|
||||
|
||||
mod enums;
|
||||
mod attribute;
|
||||
@@ -422,6 +421,89 @@ pub fn derive_try_unscribe(input: TokenStream) -> TokenStream {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[proc_macro_derive(EnumSerialize, attributes(enumscribe))]
|
||||
pub fn derive_enum_serialize(input: TokenStream) -> TokenStream {
|
||||
let input: DeriveInput = syn::parse(input)
|
||||
.expect("failed to parse input");
|
||||
|
||||
let enum_data = proc_try!(get_enum_data(&input));
|
||||
let parsed_enum = proc_try!(enums::parse_enum(enum_data));
|
||||
|
||||
let enum_ident = &input.ident;
|
||||
let serializer_ident = quote! { __enumscribe_serializer };
|
||||
|
||||
let mut match_arms = Vec::new();
|
||||
let mut ignore_variant = false;
|
||||
|
||||
for variant in parsed_enum.variants.iter() {
|
||||
let variant_ident = &variant.data.ident;
|
||||
|
||||
match &variant.v_type {
|
||||
VariantType::Ignore => ignore_variant = true,
|
||||
|
||||
VariantType::Named { name, constructor, .. } => {
|
||||
let constructor_tokens = constructor.empty();
|
||||
match_arms.push(quote! {
|
||||
#enum_ident::#variant_ident #constructor_tokens =>
|
||||
#serializer_ident.serialize_str(#name)
|
||||
})
|
||||
},
|
||||
|
||||
VariantType::Other { field_name } => {
|
||||
match field_name {
|
||||
Some(field_name) => {
|
||||
match_arms.push(quote! {
|
||||
#enum_ident::#variant_ident { #field_name } =>
|
||||
#serializer_ident.serialize_str(&#field_name)
|
||||
})
|
||||
},
|
||||
None => {
|
||||
let field_name = quote! { __enumscribe_other_inner };
|
||||
match_arms.push(quote! {
|
||||
#enum_ident::#variant_ident(#field_name) =>
|
||||
#serializer_ident.serialize_str(&#field_name)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ignore_arm = if ignore_variant {
|
||||
let err_string = format!(
|
||||
"attempted to serialize an unserializable variant of {}",
|
||||
enum_ident
|
||||
);
|
||||
quote! {
|
||||
_ => ::std::result::Result::Err(
|
||||
::serde::ser::Error::custom(#err_string)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
(quote! {
|
||||
impl ::serde::Serialize for #enum_ident {
|
||||
fn serialize<S>(&self, #serializer_ident: S) -> ::std::result::Result<S::Ok, S::Error>
|
||||
where S: ::serde::Serializer
|
||||
{
|
||||
match self {
|
||||
#(#match_arms,)*
|
||||
#ignore_arm
|
||||
}
|
||||
}
|
||||
}
|
||||
}).into()
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[proc_macro_derive(EnumDeserialize, attributes(enumscribe))]
|
||||
pub fn derive_enum_deserialize(input: TokenStream) -> TokenStream {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_enum_data(input: &DeriveInput) -> MacroResult<&DataEnum> {
|
||||
let enum_data = match &input.data {
|
||||
Data::Enum(enum_data) => enum_data,
|
||||
|
||||
Reference in new issue
Block a user