Support for serde::Serialize
This commit is contained in:
1 parent
867b09a1fe
commit
46dac98882
6 files changed
+120
-14
No files matched your search
@@ -9,3 +9,7 @@ description = "Procedural macros for converting between enums and strings"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
enumscribe_derive = { version = "0.1.0", path = "../enumscribe_derive" }
|
enumscribe_derive = { version = "0.1.0", path = "../enumscribe_derive" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["serde"]
|
||||||
|
serde = ["enumscribe_derive/serde"]
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
//! | `ignore` used? | `other` used? | Conversion to string | Conversion from string |
|
//! | `ignore` used? | `other` used? | Conversion to string | Conversion from string |
|
||||||
//! |----------------|---------------|----------------------|------------------------|
|
//! |----------------|---------------|----------------------|------------------------|
|
||||||
//! | No | No | [ScribeStaticStr] | [TryUnscribe] |
|
//! | No | No | [ScribeStaticStr] | [TryUnscribe] |
|
||||||
//! | Yes | No | [TryScribeStaticStr] | [TryUnscribe] |
|
|
||||||
//! | No | Yes | [ScribeCowStr] | [Unscribe] |
|
//! | No | Yes | [ScribeCowStr] | [Unscribe] |
|
||||||
|
//! | Yes | No | [TryScribeStaticStr] | [TryUnscribe] |
|
||||||
//! | Yes | Yes | [TryScribeCowStr] | [Unscribe] |
|
//! | Yes | Yes | [TryScribeCowStr] | [Unscribe] |
|
||||||
//!
|
//!
|
||||||
//! There are also [ScribeString] and [TryScribeString] traits which can be used in the same
|
//! There are also [ScribeString] and [TryScribeString] traits which can be used in the same
|
||||||
|
|||||||
@@ -15,6 +15,5 @@ proc-macro2 = "1.0"
|
|||||||
syn = "1.0"
|
syn = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[features]
|
||||||
serde = "1.0"
|
serde = []
|
||||||
serde_json = "1.0"
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
//! to strings and vice-versa.
|
//! to strings and vice-versa.
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
@@ -10,7 +9,7 @@ use syn::{Data, DataEnum, DeriveInput};
|
|||||||
|
|
||||||
use error::{MacroError, MacroResult};
|
use error::{MacroError, MacroResult};
|
||||||
|
|
||||||
use crate::enums::{Variant, VariantType, VariantConstructor};
|
use crate::enums::{Variant, VariantType};
|
||||||
|
|
||||||
mod enums;
|
mod enums;
|
||||||
mod attribute;
|
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> {
|
fn get_enum_data(input: &DeriveInput) -> MacroResult<&DataEnum> {
|
||||||
let enum_data = match &input.data {
|
let enum_data = match &input.data {
|
||||||
Data::Enum(enum_data) => enum_data,
|
Data::Enum(enum_data) => enum_data,
|
||||||
|
|||||||
@@ -8,3 +8,5 @@ license = "MIT"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
enumscribe = { path = "../enumscribe" }
|
enumscribe = { path = "../enumscribe" }
|
||||||
enumscribe_derive = { path = "../enumscribe_derive" }
|
enumscribe_derive = { path = "../enumscribe_derive" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use enumscribe::*;
|
use enumscribe::*;
|
||||||
|
|
||||||
#[derive(TryScribeCowStr, TryUnscribe, Eq, PartialEq, Debug)]
|
#[derive(TryScribeCowStr, Unscribe, EnumSerialize, Eq, PartialEq, Debug)]
|
||||||
enum Airport {
|
enum Airport {
|
||||||
#[enumscribe(str = "LHR")]
|
#[enumscribe(str = "LHR")]
|
||||||
Heathrow,
|
Heathrow,
|
||||||
@@ -10,18 +12,35 @@ enum Airport {
|
|||||||
Luton {},
|
Luton {},
|
||||||
#[enumscribe(str = "BHX", case_insensitive, ignore)]
|
#[enumscribe(str = "BHX", case_insensitive, ignore)]
|
||||||
BirminghamInternational,
|
BirminghamInternational,
|
||||||
// #[enumscribe(other)]
|
#[enumscribe(other)]
|
||||||
// Other(String),
|
Other(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Eq, PartialEq, Debug)]
|
||||||
|
struct AirportInfo {
|
||||||
|
airport: Airport,
|
||||||
|
info: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let luton = Airport::Luton {};
|
let luton = Airport::Luton {};
|
||||||
println!("Hello, {:?}!", luton.try_scribe());
|
println!("Hello, {:?}!", luton.try_scribe());
|
||||||
|
|
||||||
// let other = Airport::Other("Dedicated EasyJet-only airport".to_owned());
|
let other = Airport::Other("Dedicated EasyJet-only airport".to_owned());
|
||||||
// println!("Hello, {:?}!", other.try_scribe());
|
println!("Hello, {:?}!", other.try_scribe());
|
||||||
|
|
||||||
println!("{:?}", Airport::try_unscribe("LHR"));
|
println!();
|
||||||
println!("{:?}", Airport::try_unscribe("lhr"));
|
|
||||||
println!("{:?}", Airport::try_unscribe("lgw"));
|
println!("{:?}", Airport::unscribe("LHR"));
|
||||||
|
println!("{:?}", Airport::unscribe("lhr"));
|
||||||
|
println!("{:?}", Airport::unscribe("lgw"));
|
||||||
|
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let info = AirportInfo {
|
||||||
|
airport: Airport::Gatwick(),
|
||||||
|
info: "It's somewhere in London, innit".to_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{}", serde_json::to_string(&info).unwrap());
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user