integrationos_domain/algebra/
string.rs

1pub trait StringExt {
2    fn capitalize(&self) -> String;
3    fn snake_case(&self) -> String;
4    fn camel_case(&self) -> String;
5    fn pascal_case(&self) -> String;
6    fn kebab_case(&self) -> String {
7        self.snake_case().replace('_', "-")
8    }
9}
10
11impl StringExt for String {
12    fn capitalize(&self) -> String {
13        if let Some(first_char) = self.chars().next() {
14            let capitalized = first_char
15                .to_uppercase()
16                .chain(self.chars().skip(1))
17                .collect();
18            capitalized
19        } else {
20            String::new()
21        }
22    }
23
24    fn snake_case(&self) -> String {
25        let mut snake_case = String::new();
26
27        for (i, c) in self.chars().enumerate() {
28            if c.is_ascii_uppercase() && i > 0 {
29                snake_case.push('_');
30                snake_case.push(c.to_ascii_lowercase());
31            } else {
32                snake_case.push(c.to_ascii_lowercase());
33            }
34        }
35
36        snake_case
37    }
38
39    fn camel_case(&self) -> String {
40        let mut camel_case = String::new();
41        let mut capitalize_next = false;
42
43        for c in self.chars() {
44            if c.is_alphanumeric() {
45                if capitalize_next {
46                    camel_case.push(c.to_uppercase().next().unwrap());
47                    capitalize_next = false;
48                } else {
49                    camel_case.push(c);
50                }
51            } else {
52                capitalize_next = true;
53            }
54        }
55
56        camel_case
57    }
58
59    fn pascal_case(&self) -> String {
60        let mut pascal_case = String::new();
61        let mut capitalize_next = true;
62
63        for c in self.chars() {
64            if c.is_alphanumeric() {
65                if capitalize_next {
66                    pascal_case.push(c.to_uppercase().next().unwrap());
67                    capitalize_next = false;
68                } else {
69                    pascal_case.push(c);
70                }
71            } else {
72                capitalize_next = true;
73            }
74        }
75
76        pascal_case
77    }
78}
79
80impl<'a> StringExt for &'a str {
81    fn capitalize(&self) -> String {
82        self.to_string().capitalize()
83    }
84
85    fn snake_case(&self) -> String {
86        self.to_string().snake_case()
87    }
88
89    fn camel_case(&self) -> String {
90        self.to_string().camel_case()
91    }
92
93    fn pascal_case(&self) -> String {
94        self.to_string().pascal_case()
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_capitalize() {
104        assert_eq!("".capitalize(), "");
105        assert_eq!("a".capitalize(), "A");
106        assert_eq!("A".capitalize(), "A");
107        assert_eq!("hello".capitalize(), "Hello");
108        assert_eq!("Hello".capitalize(), "Hello");
109        assert_eq!(
110            "really complicated and long string".capitalize(),
111            "Really complicated and long string"
112        );
113    }
114
115    #[test]
116    fn test_to_snake_case() {
117        assert_eq!("".snake_case(), "");
118        assert_eq!("a".snake_case(), "a");
119        assert_eq!("A".snake_case(), "a");
120        assert_eq!("hello".snake_case(), "hello");
121        assert_eq!("Hello".snake_case(), "hello");
122        assert_eq!("HelloWorld".snake_case(), "hello_world");
123        assert_eq!("HelloWorldAgain".snake_case(), "hello_world_again");
124        assert_eq!(
125            "ReallyComplicatedAndLongString".snake_case(),
126            "really_complicated_and_long_string"
127        );
128    }
129
130    #[test]
131    fn test_to_camel_case() {
132        assert_eq!("".camel_case(), "");
133        assert_eq!("a".camel_case(), "a");
134        assert_eq!("A".camel_case(), "A");
135        assert_eq!("hello".camel_case(), "hello");
136        assert_eq!("Hello".camel_case(), "Hello");
137        assert_eq!("hello_world".camel_case(), "helloWorld");
138        assert_eq!("hello_world_again".camel_case(), "helloWorldAgain");
139        assert_eq!(
140            "really_complicated_and_long_string".camel_case(),
141            "reallyComplicatedAndLongString"
142        );
143    }
144
145    #[test]
146    fn test_to_pascal_case() {
147        assert_eq!("".pascal_case(), "");
148        assert_eq!("a".pascal_case(), "A");
149        assert_eq!("A".pascal_case(), "A");
150        assert_eq!("hello".pascal_case(), "Hello");
151        assert_eq!("Hello".pascal_case(), "Hello");
152        assert_eq!("hello_world".pascal_case(), "HelloWorld");
153        assert_eq!("hello_world_again".pascal_case(), "HelloWorldAgain");
154        assert_eq!(
155            "really_complicated_and_long_string".pascal_case(),
156            "ReallyComplicatedAndLongString"
157        );
158    }
159
160    #[test]
161    fn test_to_kebab_case() {
162        assert_eq!("".kebab_case(), "");
163        assert_eq!("a".kebab_case(), "a");
164        assert_eq!("A".kebab_case(), "a");
165        assert_eq!("hello".kebab_case(), "hello");
166        assert_eq!("Hello".kebab_case(), "hello");
167        assert_eq!("hello_world".kebab_case(), "hello-world");
168        assert_eq!("hello_world_again".kebab_case(), "hello-world-again");
169        assert_eq!(
170            "really_complicated_and_long_string".kebab_case(),
171            "really-complicated-and-long-string"
172        );
173    }
174}