]> git.proxmox.com Git - rustc.git/blob - src/vendor/serde_derive_internals/src/case.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / serde_derive_internals / src / case.rs
1 // Copyright 2017 Serde Developers
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8
9 // See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
10 #[allow(unused_imports)]
11 use std::ascii::AsciiExt;
12
13 use std::str::FromStr;
14
15 use self::RenameRule::*;
16
17 #[derive(Debug, PartialEq)]
18 pub enum RenameRule {
19 /// Don't apply a default rename rule.
20 None,
21 /// Rename direct children to "lowercase" style.
22 LowerCase,
23 /// Rename direct children to "PascalCase" style, as typically used for enum variants.
24 PascalCase,
25 /// Rename direct children to "camelCase" style.
26 CamelCase,
27 /// Rename direct children to "snake_case" style, as commonly used for fields.
28 SnakeCase,
29 /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly used for constants.
30 ScreamingSnakeCase,
31 /// Rename direct children to "kebab-case" style.
32 KebabCase,
33 /// Rename direct children to "SCREAMING-KEBAB-CASE" style.
34 ScreamingKebabCase
35 }
36
37 impl 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
88 impl 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]
106 fn 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]
126 fn 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 }