Skip to content

Commit

Permalink
Implement serialize_all=UPPERCASE (#48)
Browse files Browse the repository at this point in the history
* Implement serialize_all=UPPERCASE

* applying rustfmt 1.2.2-stable

* handling of all options listed in serde docs for compatibility

See https://serde.rs/container-attrs.html#container-attributes
  • Loading branch information
Dushistov authored and Peternator7 committed Jul 29, 2019
1 parent 96daaf4 commit 640c0bb
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 30 deletions.
19 changes: 15 additions & 4 deletions strum_macros/src/case_style.rs
Expand Up @@ -6,17 +6,27 @@ pub enum CaseStyle {
ShoutySnakeCase,
SnakeCase,
TitleCase,
UpperCase,
LowerCase,
ScreamingKebabCase,
PascalCase,
}

impl<'s> From<&'s str> for CaseStyle {
fn from(text: &'s str) -> CaseStyle {
match text {
"camel_case" => CaseStyle::CamelCase,
"kebab_case" => CaseStyle::KebabCase,
"lowercase" => CaseStyle::LowerCase,
"camel_case" | "PascalCase" => CaseStyle::PascalCase,
"kebab_case" | "kebab-case" => CaseStyle::KebabCase,
"mixed_case" => CaseStyle::MixedCase,
"shouty_snake_case" | "shouty_snek_case" => CaseStyle::ShoutySnakeCase,
"shouty_snake_case" | "shouty_snek_case" | "SCREAMING_SNAKE_CASE" => {
CaseStyle::ShoutySnakeCase
}
"snake_case" | "snek_case" => CaseStyle::SnakeCase,
"title_case" => CaseStyle::TitleCase,
"UPPERCASE" => CaseStyle::UpperCase,
"camelCase" => CaseStyle::CamelCase,
"SCREAMING-KEBAB-CASE" => CaseStyle::ScreamingKebabCase,
_ => panic!(
"Unexpected case style for serialize_all: `{}`. Valid values are: `{:?}`",
text,
Expand All @@ -26,7 +36,8 @@ impl<'s> From<&'s str> for CaseStyle {
"mixed_case",
"shouty_snake_case",
"snake_case",
"title_case"
"title_case",
"UPPERCASE",
]
),
}
Expand Down
22 changes: 21 additions & 1 deletion strum_macros/src/helpers.rs
Expand Up @@ -149,14 +149,34 @@ pub fn convert_case(ident: &Ident, case_style: Option<CaseStyle>) -> String {
let ident_string = ident.to_string();
if let Some(case_style) = case_style {
match case_style {
CaseStyle::CamelCase => ident_string.to_camel_case(),
CaseStyle::PascalCase => ident_string.to_camel_case(),
CaseStyle::KebabCase => ident_string.to_kebab_case(),
CaseStyle::MixedCase => ident_string.to_mixed_case(),
CaseStyle::ShoutySnakeCase => ident_string.to_shouty_snake_case(),
CaseStyle::SnakeCase => ident_string.to_snake_case(),
CaseStyle::TitleCase => ident_string.to_title_case(),
CaseStyle::UpperCase => ident_string.to_uppercase(),
CaseStyle::LowerCase => ident_string.to_lowercase(),
CaseStyle::ScreamingKebabCase => ident_string.to_kebab_case().to_uppercase(),
CaseStyle::CamelCase => {
let camel_case = ident_string.to_camel_case();
let mut pascal = String::with_capacity(camel_case.len());
let mut it = camel_case.chars();
if let Some(ch) = it.next() {
pascal.extend(ch.to_lowercase());
}
pascal.extend(it);
pascal
}
}
} else {
ident_string
}
}

#[test]
fn test_convert_case() {
let id = Ident::new("test_me", proc_macro2::Span::call_site());
assert_eq!("testMe", convert_case(&id, Some(CaseStyle::CamelCase)));
assert_eq!("TestMe", convert_case(&id, Some(CaseStyle::PascalCase)));
}
122 changes: 97 additions & 25 deletions strum_macros/src/lib.rs
Expand Up @@ -22,10 +22,10 @@ mod case_style;
mod display;
mod enum_count;
mod enum_discriminants;
mod enum_variant_names;
mod enum_iter;
mod enum_messages;
mod enum_properties;
mod enum_variant_names;
mod from_string;
mod helpers;
mod to_string;
Expand All @@ -46,8 +46,14 @@ fn debug_print_generated(ast: &syn::DeriveInput, toks: &TokenStream) {
}
}

#[cfg_attr(not(feature = "verbose-enumstring-name"), proc_macro_derive(EnumString, attributes(strum)))]
#[cfg_attr(feature = "verbose-enumstring-name", proc_macro_derive(StrumEnumString, attributes(strum)))]
#[cfg_attr(
not(feature = "verbose-enumstring-name"),
proc_macro_derive(EnumString, attributes(strum))
)]
#[cfg_attr(
feature = "verbose-enumstring-name",
proc_macro_derive(StrumEnumString, attributes(strum))
)]
pub fn from_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -56,8 +62,14 @@ pub fn from_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[cfg_attr(not(feature = "verbose-asrefstr-name"), proc_macro_derive(AsRefStr, attributes(strum)))]
#[cfg_attr(feature = "verbose-asrefstr-name", proc_macro_derive(StrumAsRefStr, attributes(strum)))]
#[cfg_attr(
not(feature = "verbose-asrefstr-name"),
proc_macro_derive(AsRefStr, attributes(strum))
)]
#[cfg_attr(
feature = "verbose-asrefstr-name",
proc_macro_derive(StrumAsRefStr, attributes(strum))
)]
pub fn as_ref_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -66,8 +78,14 @@ pub fn as_ref_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[cfg_attr(not(feature = "verbose-variant-names"), proc_macro_derive(EnumVariantNames, attributes(strum)))]
#[cfg_attr(feature = "verbose-variant-names", proc_macro_derive(StrumEnumVariantNames, attributes(strum)))]
#[cfg_attr(
not(feature = "verbose-variant-names"),
proc_macro_derive(EnumVariantNames, attributes(strum))
)]
#[cfg_attr(
feature = "verbose-variant-names",
proc_macro_derive(StrumEnumVariantNames, attributes(strum))
)]
pub fn variant_names(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -76,8 +94,14 @@ pub fn variant_names(input: proc_macro::TokenStream) -> proc_macro::TokenStream
toks.into()
}

#[cfg_attr(feature = "verbose-asstaticstr-name", proc_macro_derive(StrumAsStaticStr, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-asstaticstr-name"), proc_macro_derive(AsStaticStr, attributes(strum)))]
#[cfg_attr(
feature = "verbose-asstaticstr-name",
proc_macro_derive(StrumAsStaticStr, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-asstaticstr-name"),
proc_macro_derive(AsStaticStr, attributes(strum))
)]
pub fn as_static_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -86,8 +110,14 @@ pub fn as_static_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream
toks.into()
}

#[cfg_attr(feature = "verbose-intostaticstr-name", proc_macro_derive(StrumIntoStaticStr, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-intostaticstr-name"), proc_macro_derive(IntoStaticStr, attributes(strum)))]
#[cfg_attr(
feature = "verbose-intostaticstr-name",
proc_macro_derive(StrumIntoStaticStr, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-intostaticstr-name"),
proc_macro_derive(IntoStaticStr, attributes(strum))
)]
pub fn into_static_str(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -96,8 +126,14 @@ pub fn into_static_str(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
toks.into()
}

#[cfg_attr(feature = "verbose-tostring-name", proc_macro_derive(StrumToString, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-tostring-name"), proc_macro_derive(ToString, attributes(strum)))]
#[cfg_attr(
feature = "verbose-tostring-name",
proc_macro_derive(StrumToString, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-tostring-name"),
proc_macro_derive(ToString, attributes(strum))
)]
pub fn to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -106,8 +142,14 @@ pub fn to_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[cfg_attr(feature = "verbose-display-name", proc_macro_derive(StrumDisplay, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-display-name"), proc_macro_derive(Display, attributes(strum)))]
#[cfg_attr(
feature = "verbose-display-name",
proc_macro_derive(StrumDisplay, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-display-name"),
proc_macro_derive(Display, attributes(strum))
)]
pub fn display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -116,8 +158,14 @@ pub fn display(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[cfg_attr(feature = "verbose-enumiter-name", proc_macro_derive(StrumEnumIter, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-enumiter-name"), proc_macro_derive(EnumIter, attributes(strum)))]
#[cfg_attr(
feature = "verbose-enumiter-name",
proc_macro_derive(StrumEnumIter, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-enumiter-name"),
proc_macro_derive(EnumIter, attributes(strum))
)]
pub fn enum_iter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -126,8 +174,14 @@ pub fn enum_iter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
toks.into()
}

#[cfg_attr(feature = "verbose-enummessage-name", proc_macro_derive(StrumEnumMessage, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-enummessage-name"), proc_macro_derive(EnumMessage, attributes(strum)))]
#[cfg_attr(
feature = "verbose-enummessage-name",
proc_macro_derive(StrumEnumMessage, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-enummessage-name"),
proc_macro_derive(EnumMessage, attributes(strum))
)]
pub fn enum_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -136,8 +190,14 @@ pub fn enum_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream
toks.into()
}

#[cfg_attr(feature = "verbose-enumproperty-name", proc_macro_derive(StrumEnumProperty, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-enumproperty-name"), proc_macro_derive(EnumProperty, attributes(strum)))]
#[cfg_attr(
feature = "verbose-enumproperty-name",
proc_macro_derive(StrumEnumProperty, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-enumproperty-name"),
proc_macro_derive(EnumProperty, attributes(strum))
)]
pub fn enum_properties(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -146,8 +206,14 @@ pub fn enum_properties(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
toks.into()
}

#[cfg_attr(feature = "verbose-enumdiscriminants-name", proc_macro_derive(StrumEnumDiscriminants, attributes(strum, strum_discriminants)))]
#[cfg_attr(not(feature = "verbose-enumdiscriminants-name"), proc_macro_derive(EnumDiscriminants, attributes(strum, strum_discriminants)))]
#[cfg_attr(
feature = "verbose-enumdiscriminants-name",
proc_macro_derive(StrumEnumDiscriminants, attributes(strum, strum_discriminants))
)]
#[cfg_attr(
not(feature = "verbose-enumdiscriminants-name"),
proc_macro_derive(EnumDiscriminants, attributes(strum, strum_discriminants))
)]
pub fn enum_discriminants(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();

Expand All @@ -156,8 +222,14 @@ pub fn enum_discriminants(input: proc_macro::TokenStream) -> proc_macro::TokenSt
toks.into()
}

#[cfg_attr(feature = "verbose-enumcount-name", proc_macro_derive(StrumEnumCount, attributes(strum)))]
#[cfg_attr(not(feature = "verbose-enumcount-name"), proc_macro_derive(EnumCount, attributes(strum)))]
#[cfg_attr(
feature = "verbose-enumcount-name",
proc_macro_derive(StrumEnumCount, attributes(strum))
)]
#[cfg_attr(
not(feature = "verbose-enumcount-name"),
proc_macro_derive(EnumCount, attributes(strum))
)]
pub fn enum_count(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = syn::parse(input).unwrap();
let toks = enum_count::enum_count_inner(&ast);
Expand Down
37 changes: 37 additions & 0 deletions strum_tests/tests/serialize_all.rs
@@ -0,0 +1,37 @@
/// test serialize_all cooperation with other macroses
extern crate strum;
#[macro_use]
extern crate strum_macros;

use std::str::FromStr;
use std::string::ToString;

#[derive(Debug, Eq, PartialEq, EnumString, ToString, IntoStaticStr)]
#[strum(serialize_all = "title_case")]
enum Foo1 {
DarkBlack,
Dim { glow: usize },
BrightWhite,
}

#[test]
fn test_serialize_all_title_case() {
assert_eq!("Dark Black", Foo1::DarkBlack.to_string());
assert_eq!(Foo1::DarkBlack, Foo1::from_str("Dark Black").unwrap());
assert_eq!("Dark Black", <&'static str>::from(Foo1::DarkBlack));
}

#[derive(Debug, Eq, PartialEq, EnumString, ToString, IntoStaticStr)]
#[strum(serialize_all = "UPPERCASE")]
enum Foo2 {
DarkBlack,
Dim { glow: usize },
BrightWhite,
}

#[test]
fn test_serialize_all_upper_case() {
assert_eq!("DARKBLACK", Foo2::DarkBlack.to_string());
assert_eq!(Foo2::DarkBlack, Foo2::from_str("DARKBLACK").unwrap());
assert_eq!("DARKBLACK", <&'static str>::from(Foo2::DarkBlack));
}

0 comments on commit 640c0bb

Please sign in to comment.