1#[must_use]
14pub fn to_snake_case(s: &str) -> String {
15 let mut result = String::new();
16 for (i, c) in s.chars().enumerate() {
17 if c.is_uppercase() && i > 0 {
18 result.push('_');
19 }
20 result.push(c.to_lowercase().next().unwrap());
21 }
22 result
23}
24
25#[must_use]
32pub fn to_pascal_case(s: &str) -> String {
33 let mut result = String::new();
34 let mut capitalize_next = true;
35 for c in s.chars() {
36 if c == '_' {
37 capitalize_next = true;
38 } else if capitalize_next {
39 result.push(c.to_uppercase().next().unwrap());
40 capitalize_next = false;
41 } else {
42 result.push(c);
43 }
44 }
45 result
46}
47
48#[must_use]
50pub fn to_camel_case(s: &str) -> String {
51 let pascal = to_pascal_case(s);
52 let mut chars = pascal.chars();
53 match chars.next() {
54 Some(c) => c.to_lowercase().collect::<String>() + chars.as_str(),
55 None => String::new(),
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_to_snake_case() {
65 assert_eq!(to_snake_case("User"), "user");
66 assert_eq!(to_snake_case("PostTag"), "post_tag");
67 assert_eq!(to_snake_case("createdAt"), "created_at");
68 assert_eq!(to_snake_case("HTMLParser"), "h_t_m_l_parser");
69 }
70
71 #[test]
72 fn test_to_pascal_case() {
73 assert_eq!(to_pascal_case("user"), "User");
74 assert_eq!(to_pascal_case("post_tag"), "PostTag");
75 assert_eq!(to_pascal_case("created_at"), "CreatedAt");
76 }
77
78 #[test]
79 fn test_to_camel_case() {
80 assert_eq!(to_camel_case("user_name"), "userName");
81 assert_eq!(to_camel_case("created_at"), "createdAt");
82 assert_eq!(to_camel_case("id"), "id");
83 }
84}