1use std::str::FromStr;
9
10use self::RenameRule::*;
11
12#[derive(Copy, Clone, PartialEq)]
14pub enum RenameRule {
15 None,
17 LowerCase,
19 Uppercase,
21 PascalCase,
24 CamelCase,
26 SnakeCase,
29 ScreamingSnakeCase,
32 KebabCase,
34 ScreamingKebabCase,
36 MatrixErrorCase,
39 MatrixLowerCase,
41 MatrixSnakeCase,
43 MatrixDottedCase,
45 MatrixRuleSnakeCase,
47 MatrixRoleSnakeCase,
49}
50
51impl RenameRule {
52 pub fn apply_to_variant(&self, variant: &str) -> String {
54 match *self {
55 None | PascalCase => variant.to_owned(),
56 LowerCase => variant.to_ascii_lowercase(),
57 Uppercase => variant.to_ascii_uppercase(),
58 CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
59 SnakeCase => {
60 let mut snake = String::new();
61 for (i, ch) in variant.char_indices() {
62 if i > 0 && ch.is_uppercase() {
63 snake.push('_');
64 }
65 snake.push(ch.to_ascii_lowercase());
66 }
67 snake
68 }
69 ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
70 KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
71 ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-"),
72 MatrixErrorCase => String::from("M_") + &ScreamingSnakeCase.apply_to_variant(variant),
73 MatrixLowerCase => String::from("m.") + &LowerCase.apply_to_variant(variant),
74 MatrixSnakeCase => String::from("m.") + &SnakeCase.apply_to_variant(variant),
75 MatrixDottedCase => {
76 String::from("m.") + &SnakeCase.apply_to_variant(variant).replace('_', ".")
77 }
78 MatrixRuleSnakeCase => String::from(".m.rule.") + &SnakeCase.apply_to_variant(variant),
79 MatrixRoleSnakeCase => String::from("m.role.") + &SnakeCase.apply_to_variant(variant),
80 }
81 }
82
83 #[allow(dead_code)]
85 pub fn apply_to_field(&self, field: &str) -> String {
86 match *self {
87 None | LowerCase | SnakeCase => field.to_owned(),
88 Uppercase => field.to_ascii_uppercase(),
89 PascalCase => {
90 let mut pascal = String::new();
91 let mut capitalize = true;
92 for ch in field.chars() {
93 if ch == '_' {
94 capitalize = true;
95 } else if capitalize {
96 pascal.push(ch.to_ascii_uppercase());
97 capitalize = false;
98 } else {
99 pascal.push(ch);
100 }
101 }
102 pascal
103 }
104 CamelCase => {
105 let pascal = PascalCase.apply_to_field(field);
106 pascal[..1].to_ascii_lowercase() + &pascal[1..]
107 }
108 ScreamingSnakeCase => field.to_ascii_uppercase(),
109 KebabCase => field.replace('_', "-"),
110 ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
111 MatrixErrorCase => String::from("M_") + &ScreamingSnakeCase.apply_to_field(field),
112 MatrixLowerCase => String::from("m.") + field,
113 MatrixSnakeCase => String::from("m.") + field,
114 MatrixDottedCase => String::from("m.") + &field.replace('_', "."),
115 MatrixRuleSnakeCase => String::from(".m.rule.") + field,
116 MatrixRoleSnakeCase => String::from("m.role.") + field,
117 }
118 }
119}
120
121impl FromStr for RenameRule {
122 type Err = ();
123
124 fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
125 match rename_all_str {
126 "lowercase" => Ok(LowerCase),
127 "UPPERCASE" => Ok(Uppercase),
128 "PascalCase" => Ok(PascalCase),
129 "camelCase" => Ok(CamelCase),
130 "snake_case" => Ok(SnakeCase),
131 "SCREAMING_SNAKE_CASE" => Ok(ScreamingSnakeCase),
132 "kebab-case" => Ok(KebabCase),
133 "SCREAMING-KEBAB-CASE" => Ok(ScreamingKebabCase),
134 "M_MATRIX_ERROR_CASE" => Ok(MatrixErrorCase),
135 "m.snake_case" => Ok(MatrixSnakeCase),
136 "m.lowercase" => Ok(MatrixLowerCase),
137 "m.dotted.case" => Ok(MatrixDottedCase),
138 ".m.rule.snake_case" => Ok(MatrixRuleSnakeCase),
139 "m.role.snake_case" => Ok(MatrixRoleSnakeCase),
140 _ => Err(()),
141 }
142 }
143}
144
145#[test]
146fn rename_variants() {
147 for &(
148 original,
149 lower,
150 upper,
151 camel,
152 snake,
153 screaming,
154 kebab,
155 screaming_kebab,
156 matrix_error,
157 m_lower,
158 m_snake,
159 m_dotted,
160 m_rule_snake,
161 m_role_snake,
162 ) in &[
163 (
164 "Outcome",
165 "outcome",
166 "OUTCOME",
167 "outcome",
168 "outcome",
169 "OUTCOME",
170 "outcome",
171 "OUTCOME",
172 "M_OUTCOME",
173 "m.outcome",
174 "m.outcome",
175 "m.outcome",
176 ".m.rule.outcome",
177 "m.role.outcome",
178 ),
179 (
180 "VeryTasty",
181 "verytasty",
182 "VERYTASTY",
183 "veryTasty",
184 "very_tasty",
185 "VERY_TASTY",
186 "very-tasty",
187 "VERY-TASTY",
188 "M_VERY_TASTY",
189 "m.verytasty",
190 "m.very_tasty",
191 "m.very.tasty",
192 ".m.rule.very_tasty",
193 "m.role.very_tasty",
194 ),
195 (
196 "A",
197 "a",
198 "A",
199 "a",
200 "a",
201 "A",
202 "a",
203 "A",
204 "M_A",
205 "m.a",
206 "m.a",
207 "m.a",
208 ".m.rule.a",
209 "m.role.a",
210 ),
211 (
212 "Z42",
213 "z42",
214 "Z42",
215 "z42",
216 "z42",
217 "Z42",
218 "z42",
219 "Z42",
220 "M_Z42",
221 "m.z42",
222 "m.z42",
223 "m.z42",
224 ".m.rule.z42",
225 "m.role.z42",
226 ),
227 ] {
228 assert_eq!(None.apply_to_variant(original), original);
229 assert_eq!(LowerCase.apply_to_variant(original), lower);
230 assert_eq!(Uppercase.apply_to_variant(original), upper);
231 assert_eq!(PascalCase.apply_to_variant(original), original);
232 assert_eq!(CamelCase.apply_to_variant(original), camel);
233 assert_eq!(SnakeCase.apply_to_variant(original), snake);
234 assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
235 assert_eq!(KebabCase.apply_to_variant(original), kebab);
236 assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
237 assert_eq!(MatrixErrorCase.apply_to_variant(original), matrix_error);
238 assert_eq!(MatrixLowerCase.apply_to_variant(original), m_lower);
239 assert_eq!(MatrixSnakeCase.apply_to_variant(original), m_snake);
240 assert_eq!(MatrixDottedCase.apply_to_variant(original), m_dotted);
241 assert_eq!(MatrixRuleSnakeCase.apply_to_variant(original), m_rule_snake);
242 assert_eq!(MatrixRoleSnakeCase.apply_to_variant(original), m_role_snake);
243 }
244}
245
246#[test]
247fn rename_fields() {
248 for &(
249 original,
250 upper,
251 pascal,
252 camel,
253 screaming,
254 kebab,
255 screaming_kebab,
256 matrix_error,
257 m_lower,
258 m_snake,
259 m_dotted,
260 m_rule_snake,
261 m_role_snake,
262 ) in &[
263 (
264 "outcome",
265 "OUTCOME",
266 "Outcome",
267 "outcome",
268 "OUTCOME",
269 "outcome",
270 "OUTCOME",
271 "M_OUTCOME",
272 "m.outcome",
273 "m.outcome",
274 "m.outcome",
275 ".m.rule.outcome",
276 "m.role.outcome",
277 ),
278 (
279 "very_tasty",
280 "VERY_TASTY",
281 "VeryTasty",
282 "veryTasty",
283 "VERY_TASTY",
284 "very-tasty",
285 "VERY-TASTY",
286 "M_VERY_TASTY",
287 "m.very_tasty",
288 "m.very_tasty",
289 "m.very.tasty",
290 ".m.rule.very_tasty",
291 "m.role.very_tasty",
292 ),
293 ("a", "A", "A", "a", "A", "a", "A", "M_A", "m.a", "m.a", "m.a", ".m.rule.a", "m.role.a"),
294 (
295 "z42",
296 "Z42",
297 "Z42",
298 "z42",
299 "Z42",
300 "z42",
301 "Z42",
302 "M_Z42",
303 "m.z42",
304 "m.z42",
305 "m.z42",
306 ".m.rule.z42",
307 "m.role.z42",
308 ),
309 ] {
310 assert_eq!(None.apply_to_field(original), original);
311 assert_eq!(Uppercase.apply_to_field(original), upper);
312 assert_eq!(PascalCase.apply_to_field(original), pascal);
313 assert_eq!(CamelCase.apply_to_field(original), camel);
314 assert_eq!(SnakeCase.apply_to_field(original), original);
315 assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming);
316 assert_eq!(KebabCase.apply_to_field(original), kebab);
317 assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab);
318 assert_eq!(MatrixErrorCase.apply_to_field(original), matrix_error);
319 assert_eq!(MatrixLowerCase.apply_to_field(original), m_lower);
320 assert_eq!(MatrixSnakeCase.apply_to_field(original), m_snake);
321 assert_eq!(MatrixDottedCase.apply_to_field(original), m_dotted);
322 assert_eq!(MatrixRuleSnakeCase.apply_to_field(original), m_rule_snake);
323 assert_eq!(MatrixRoleSnakeCase.apply_to_field(original), m_role_snake);
324 }
325}