+++ /dev/null
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "darling"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
-[[package]]
-name = "mt_data_derive"
-version = "0.1.0"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.51"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "strsim"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-
-[[package]]
-name = "syn"
-version = "1.0.107"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+use convert_case::{Case, Casing};
use darling::{FromDeriveInput, FromField, FromMeta, FromVariant};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokStr;
});
}
- if let Some(repr) = args.repr {
- out.extend(quote! {
- #[repr(#repr)]
- });
- } else if !args.custom {
- panic!("missing repr for enum");
- }
-
out.extend(quote! {
#[derive(Clone, PartialEq)]
});
#[cfg_attr(feature = #deserializer, derive(MtDeserialize))]
});
}
+
+ if let Some(repr) = args.repr {
+ if repr == parse_quote! { str } {
+ out.extend(quote! {
+ #[mt(string_repr)]
+ });
+ } else {
+ out.extend(quote! {
+ #[repr(#repr)]
+ });
+ }
+ } else if !args.custom {
+ panic!("missing repr for enum");
+ }
}
out.extend(quote! {
zlib: bool,
zstd: bool, // TODO
default: bool, // type must implement Default
+
+ string_repr: bool, // for enums
}
type Fields<'a> = Vec<(TokStr, &'a syn::Field)>;
(fields, fields_struct)
}
-fn get_repr(input: &syn::DeriveInput) -> syn::Type {
- input
- .attrs
- .iter()
- .find(|a| a.path.is_ident("repr"))
- .expect("missing repr")
- .parse_args()
- .expect("invalid repr")
+fn get_repr(input: &syn::DeriveInput, args: &MtArgs) -> syn::Type {
+ if args.string_repr {
+ parse_quote! { &str }
+ } else {
+ input
+ .attrs
+ .iter()
+ .find(|a| a.path.is_ident("repr"))
+ .expect("missing repr")
+ .parse_args()
+ .expect("invalid repr")
+ }
+}
+
+fn iter_variants(e: &syn::DataEnum, args: &MtArgs, mut f: impl FnMut(&syn::Variant, &syn::Expr)) {
+ let mut discr = parse_quote! { 0 };
+
+ for v in e.variants.iter() {
+ discr = if args.string_repr {
+ let lit = v.ident.to_string().to_case(Case::Snake);
+ parse_quote! { #lit }
+ } else {
+ v.discriminant.clone().map(|x| x.1).unwrap_or(discr)
+ };
+
+ f(&v, &discr);
+
+ discr = parse_quote! { 1 + #discr };
+ }
}
#[proc_macro_derive(MtSerialize, attributes(mt))]
let input = parse_macro_input!(input as syn::DeriveInput);
let typename = &input.ident;
- let code = serialize_args(MtArgs::from_derive_input(&input), |_| match &input.data {
- syn::Data::Enum(e) => {
- let repr = get_repr(&input);
- let variants: TokStr = e.variants
- .iter()
- .fold((parse_quote! { 0 }, TokStr::new()), |(discr, before), v| {
- let discr = v.discriminant.clone().map(|x| x.1).unwrap_or(discr);
- let (fields, fields_struct) = get_fields_struct(&v.fields);
-
- let code = serialize_args(MtArgs::from_variant(v), |_|
- serialize_fields(&fields));
- let variant = &v.ident;
-
- (
- parse_quote! { 1 + #discr },
- quote! {
- #before
- #typename::#variant #fields_struct => {
- mt_ser::MtSerialize::mt_serialize::<mt_ser::DefCfg>(&((#discr) as #repr), __writer)?;
- #code
- }
- }
- )
- }).1;
+ let code = serialize_args(MtArgs::from_derive_input(&input), |args| {
+ match &input.data {
+ syn::Data::Enum(e) => {
+ let repr = get_repr(&input, &args);
+ let mut variants = TokStr::new();
+
+ iter_variants(&e, &args, |v, discr| {
+ let (fields, fields_struct) = get_fields_struct(&v.fields);
+ let code =
+ serialize_args(MtArgs::from_variant(v), |_| serialize_fields(&fields));
+ let ident = &v.ident;
+
+ variants.extend(quote! {
+ #typename::#ident #fields_struct => {
+ mt_ser::MtSerialize::mt_serialize::<mt_ser::DefCfg>(&((#discr) as #repr), __writer)?;
+ #code
+ }
+ });
+ });
- quote! {
- match self {
- #variants
+ quote! {
+ match self {
+ #variants
+ }
}
}
- }
- syn::Data::Struct(s) => serialize_fields(&get_fields(&s.fields, |f| quote! { &self.#f })),
- _ => {
- panic!("only enum and struct supported");
+ syn::Data::Struct(s) => {
+ serialize_fields(&get_fields(&s.fields, |f| quote! { &self.#f }))
+ }
+ _ => {
+ panic!("only enum and struct supported");
+ }
}
});
let input = parse_macro_input!(input as syn::DeriveInput);
let typename = &input.ident;
- let code = deserialize_args(MtArgs::from_derive_input(&input), |_| match &input.data {
- syn::Data::Enum(e) => {
- let repr = get_repr(&input);
- let type_str = typename.to_string();
+ let code = deserialize_args(MtArgs::from_derive_input(&input), |args| {
+ match &input.data {
+ syn::Data::Enum(e) => {
+ let repr = get_repr(&input, &args);
- let mut consts = TokStr::new();
- let mut arms = TokStr::new();
- let mut discr = parse_quote! { 0 };
+ let mut consts = TokStr::new();
+ let mut arms = TokStr::new();
- for v in e.variants.iter() {
- discr = v.discriminant.clone().map(|x| x.1).unwrap_or(discr);
+ iter_variants(&e, &args, |v, discr| {
+ let ident = &v.ident;
+ let (fields, fields_struct) = get_fields_struct(&v.fields);
+ let code = deserialize_args(MtArgs::from_variant(v), |_| {
+ let fields_code = deserialize_fields(&fields);
- let ident = &v.ident;
- let (fields, fields_struct) = get_fields_struct(&v.fields);
- let code = deserialize_args(MtArgs::from_variant(v), |_| {
- let fields_code = deserialize_fields(&fields);
-
- quote! {
- #fields_code
- Ok(Self::#ident #fields_struct)
- }
- });
+ quote! {
+ #fields_code
+ Ok(Self::#ident #fields_struct)
+ }
+ });
- consts.extend(quote! {
- const #ident: #repr = #discr;
- });
+ consts.extend(quote! {
+ const #ident: #repr = #discr;
+ });
- arms.extend(quote! {
- #ident => { #code }
+ arms.extend(quote! {
+ #ident => { #code }
+ });
});
- discr = parse_quote! { 1 + #discr };
- }
+ let type_str = typename.to_string();
+ let discr_match = if args.string_repr {
+ quote! {
+ let __discr = String::mt_deserialize::<DefCfg>(__reader)?;
+ match __discr.as_str()
+ }
+ } else {
+ quote! {
+ let __discr = mt_ser::MtDeserialize::mt_deserialize::<DefCfg>(__reader)?;
+ match __discr
+ }
+ };
- quote! {
- #consts
+ quote! {
+ #consts
- match mt_ser::MtDeserialize::mt_deserialize::<DefCfg>(__reader)? {
- #arms
- x => Err(mt_ser::DeserializeError::InvalidEnumVariant(#type_str, x as u64))
+ #discr_match {
+ #arms
+ _ => Err(mt_ser::DeserializeError::InvalidEnum(#type_str, Box::new(__discr)))
+ }
}
}
- }
- syn::Data::Struct(s) => {
- let (fields, fields_struct) = get_fields_struct(&s.fields);
- let code = deserialize_fields(&fields);
+ syn::Data::Struct(s) => {
+ let (fields, fields_struct) = get_fields_struct(&s.fields);
+ let code = deserialize_fields(&fields);
- quote! {
- #code
- Ok(Self #fields_struct)
+ quote! {
+ #code
+ Ok(Self #fields_struct)
+ }
+ }
+ _ => {
+ panic!("only enum and struct supported");
}
- }
- _ => {
- panic!("only enum and struct supported");
}
});