1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::MethodKind;
pub fn method_to_snake(camel: &str, kind: MethodKind) -> String {
debug_assert!(!camel.is_empty());
let mut snake = String::with_capacity(camel.len());
match kind {
MethodKind::Set => snake.push_str("set_"),
MethodKind::Remove => snake.push_str("remove_"),
_ => {}
};
append_to_snake(snake, camel)
}
pub fn to_snake(camel: &str) -> String {
debug_assert!(!camel.is_empty());
let snake = String::with_capacity(camel.len());
append_to_snake(snake, camel)
}
fn append_to_snake(mut snake: String, camel: &str) -> String {
if camel == "WinRT" {
return "winrt".to_string();
}
let mut since_last_underscore = 0;
let mut chars = camel.chars();
for c in chars.next().unwrap().to_lowercase() {
since_last_underscore += 1;
snake.push(c);
}
for (previous, next) in camel.chars().zip(camel.chars().skip(2)) {
let current = chars.next().unwrap();
if !current.is_uppercase() {
since_last_underscore += 1;
snake.push(current);
continue;
}
if previous.is_lowercase() || next.is_lowercase() && since_last_underscore > 1 {
since_last_underscore = 0;
if previous != '_' {
snake.push('_');
}
}
for c in current.to_lowercase() {
since_last_underscore += 1;
snake.push(c);
}
}
if let Some(last) = chars.next() {
snake.extend(last.to_lowercase());
}
snake
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn to_snake_works() {
assert_eq!(to_snake("Windows"), "windows".to_owned());
assert_eq!(to_snake("ApplicationModel"), "application_model".to_owned());
assert_eq!(method_to_snake("foo", MethodKind::Normal), "foo".to_owned());
assert_eq!(
method_to_snake("UIProgramming", MethodKind::Normal),
"ui_programming".to_owned()
);
assert_eq!(
method_to_snake("UIProgramming", MethodKind::Set),
"set_ui_programming".to_owned()
);
assert_eq!(
method_to_snake("CreateUInt8Array", MethodKind::Normal),
"create_uint8_array".to_owned()
);
assert_eq!(
method_to_snake("Socks", MethodKind::Remove),
"remove_socks".to_owned()
);
assert_eq!(to_snake("appointmentId"), "appointment_id".to_owned());
assert_eq!(method_to_snake("a", MethodKind::Normal), "a".to_owned());
assert_eq!(
method_to_snake("CreateField_Default", MethodKind::Normal),
"create_field_default".to_owned()
);
assert!(to_snake("WinRT") == "winrt");
}
}