serde_derive_state_internals/
case.rs1#[allow(unused_imports)]
11use std::ascii::AsciiExt;
12
13use std::str::FromStr;
14
15use self::RenameRule::*;
16
17#[derive(Debug, PartialEq)]
18pub enum RenameRule {
19 None,
21 LowerCase,
23 PascalCase,
25 CamelCase,
27 SnakeCase,
29 ScreamingSnakeCase,
31 KebabCase,
33 ScreamingKebabCase
35}
36
37impl RenameRule {
38 pub fn apply_to_variant(&self, variant: &str) -> String {
39 match *self {
40 None | PascalCase => variant.to_owned(),
41 LowerCase => variant.to_ascii_lowercase(),
42 CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
43 SnakeCase => {
44 let mut snake = String::new();
45 for (i, ch) in variant.char_indices() {
46 if i > 0 && ch.is_uppercase() {
47 snake.push('_');
48 }
49 snake.push(ch.to_ascii_lowercase());
50 }
51 snake
52 }
53 ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
54 KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
55 ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-")
56 }
57 }
58
59 pub fn apply_to_field(&self, field: &str) -> String {
60 match *self {
61 None | LowerCase | SnakeCase => field.to_owned(),
62 PascalCase => {
63 let mut pascal = String::new();
64 let mut capitalize = true;
65 for ch in field.chars() {
66 if ch == '_' {
67 capitalize = true;
68 } else if capitalize {
69 pascal.push(ch.to_ascii_uppercase());
70 capitalize = false;
71 } else {
72 pascal.push(ch);
73 }
74 }
75 pascal
76 }
77 CamelCase => {
78 let pascal = PascalCase.apply_to_field(field);
79 pascal[..1].to_ascii_lowercase() + &pascal[1..]
80 }
81 ScreamingSnakeCase => field.to_ascii_uppercase(),
82 KebabCase => field.replace('_', "-"),
83 ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
84 }
85 }
86}
87
88impl FromStr for RenameRule {
89 type Err = ();
90
91 fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
92 match rename_all_str {
93 "lowercase" => Ok(LowerCase),
94 "PascalCase" => Ok(PascalCase),
95 "camelCase" => Ok(CamelCase),
96 "snake_case" => Ok(SnakeCase),
97 "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
98 "kebab-case" => Ok(KebabCase),
99 "SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
100 _ => Err(()),
101 }
102 }
103}
104
105#[test]
106fn rename_variants() {
107 for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
108 &[
109 ("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
110 ("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
111 ("A", "a", "a", "a", "A", "a", "A"),
112 ("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
113 ] {
114 assert_eq!(None.apply_to_variant(original), original);
115 assert_eq!(LowerCase.apply_to_variant(original), lower);
116 assert_eq!(PascalCase.apply_to_variant(original), original);
117 assert_eq!(CamelCase.apply_to_variant(original), camel);
118 assert_eq!(SnakeCase.apply_to_variant(original), snake);
119 assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
120 assert_eq!(KebabCase.apply_to_variant(original), kebab);
121 assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
122 }
123}
124
125#[test]
126fn rename_fields() {
127 for &(original, pascal, camel, screaming, kebab, screaming_kebab) in
128 &[
129 ("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
130 ("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
131 ("a", "A", "a", "A", "a", "A"),
132 ("z42", "Z42", "z42", "Z42", "z42", "Z42"),
133 ] {
134 assert_eq!(None.apply_to_field(original), original);
135 assert_eq!(PascalCase.apply_to_field(original), pascal);
136 assert_eq!(CamelCase.apply_to_field(original), camel);
137 assert_eq!(SnakeCase.apply_to_field(original), original);
138 assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
139 assert_eq!(KebabCase.apply_to_field(original), kebab);
140 assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
141 }
142}