1
+ //! Functions for string case manipulation, such as detecting the identifier case,
2
+ //! and converting it into appropriate form.
3
+
1
4
#[ derive( Debug ) ]
2
5
enum DetectedCase {
3
6
LowerCamelCase ,
@@ -44,6 +47,8 @@ fn detect_case(ident: &str) -> DetectedCase {
44
47
}
45
48
}
46
49
50
+ /// Converts an identifier to an UpperCamelCase form.
51
+ /// Returns `None` if the string is already is UpperCamelCase.
47
52
pub fn to_camel_case ( ident : & str ) -> Option < String > {
48
53
let detected_case = detect_case ( ident) ;
49
54
@@ -87,9 +92,17 @@ pub fn to_camel_case(ident: &str) -> Option<String> {
87
92
}
88
93
}
89
94
90
- Some ( output)
95
+ if output == ident {
96
+ // While we didn't detect the correct case at the beginning, there
97
+ // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
98
+ None
99
+ } else {
100
+ Some ( output)
101
+ }
91
102
}
92
103
104
+ /// Converts an identifier to a lower_snake_case form.
105
+ /// Returns `None` if the string is already is lower_snake_case.
93
106
pub fn to_lower_snake_case ( ident : & str ) -> Option < String > {
94
107
// First, assume that it's UPPER_SNAKE_CASE.
95
108
match detect_case ( ident) {
@@ -102,9 +115,18 @@ pub fn to_lower_snake_case(ident: &str) -> Option<String> {
102
115
103
116
// Otherwise, assume that it's CamelCase.
104
117
let lower_snake_case = stdx:: to_lower_snake_case ( ident) ;
105
- Some ( lower_snake_case)
118
+
119
+ if lower_snake_case == ident {
120
+ // While we didn't detect the correct case at the beginning, there
121
+ // may be special cases: e.g. `a` is both valid camelCase and snake_case.
122
+ None
123
+ } else {
124
+ Some ( lower_snake_case)
125
+ }
106
126
}
107
127
128
+ /// Converts an identifier to an UPPER_SNAKE_CASE form.
129
+ /// Returns `None` if the string is already is UPPER_SNAKE_CASE.
108
130
pub fn to_upper_snake_case ( ident : & str ) -> Option < String > {
109
131
match detect_case ( ident) {
110
132
DetectedCase :: UpperSnakeCase => return None ,
@@ -117,7 +139,14 @@ pub fn to_upper_snake_case(ident: &str) -> Option<String> {
117
139
// Normalize the string from whatever form it's in currently, and then just make it uppercase.
118
140
let upper_snake_case =
119
141
stdx:: to_lower_snake_case ( ident) . chars ( ) . map ( |c| c. to_ascii_uppercase ( ) ) . collect ( ) ;
120
- Some ( upper_snake_case)
142
+
143
+ if upper_snake_case == ident {
144
+ // While we didn't detect the correct case at the beginning, there
145
+ // may be special cases: e.g. `A` is both valid CamelCase and UPPER_SNAKE_CASE.
146
+ None
147
+ } else {
148
+ Some ( upper_snake_case)
149
+ }
121
150
}
122
151
123
152
#[ cfg( test) ]
@@ -139,6 +168,7 @@ mod tests {
139
168
check ( to_lower_snake_case, "Weird_Case" , expect ! [ [ "weird_case" ] ] ) ;
140
169
check ( to_lower_snake_case, "CamelCase" , expect ! [ [ "camel_case" ] ] ) ;
141
170
check ( to_lower_snake_case, "lowerCamelCase" , expect ! [ [ "lower_camel_case" ] ] ) ;
171
+ check ( to_lower_snake_case, "a" , expect ! [ [ "" ] ] ) ;
142
172
}
143
173
144
174
#[ test]
@@ -151,6 +181,7 @@ mod tests {
151
181
check ( to_camel_case, "UPPER_SNAKE_CASE" , expect ! [ [ "UpperSnakeCase" ] ] ) ;
152
182
check ( to_camel_case, "Weird_Case" , expect ! [ [ "WeirdCase" ] ] ) ;
153
183
check ( to_camel_case, "name" , expect ! [ [ "Name" ] ] ) ;
184
+ check ( to_camel_case, "A" , expect ! [ [ "" ] ] ) ;
154
185
}
155
186
156
187
#[ test]
@@ -160,5 +191,6 @@ mod tests {
160
191
check ( to_upper_snake_case, "Weird_Case" , expect ! [ [ "WEIRD_CASE" ] ] ) ;
161
192
check ( to_upper_snake_case, "CamelCase" , expect ! [ [ "CAMEL_CASE" ] ] ) ;
162
193
check ( to_upper_snake_case, "lowerCamelCase" , expect ! [ [ "LOWER_CAMEL_CASE" ] ] ) ;
194
+ check ( to_upper_snake_case, "A" , expect ! [ [ "" ] ] ) ;
163
195
}
164
196
}
0 commit comments