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