voca_rs/
case.rs

1//! Converts the `subject` to a selected case.
2
3/// Converts the `subject` to camel case.
4///
5/// # Arguments
6///
7/// * `subject` - The string to convert to camel case.
8///
9/// # Example
10/// ```
11/// use voca_rs::*;
12/// case::camel_case("bird flight");
13/// // => "birdFlight"
14/// case::camel_case("BirdFlight");
15/// // => "birdFlight"
16/// case::camel_case("-BIRD-FLIGHT-");
17/// // => "birdFlight"
18/// use voca_rs::Voca;
19/// "bird flight"._camel_case();
20/// // => "birdFlight"
21/// ```
22pub fn camel_case(subject: &str) -> String {
23    camel_and_pascal_case(subject, TitleMode::Normal)
24}
25
26#[derive(Clone, Copy, PartialEq)]
27enum TitleMode {
28    Normal,
29    Caps,
30}
31
32fn camel_and_pascal_case(subject: &str, title_mode: TitleMode) -> String {
33    return match subject.len() {
34        0 => subject.to_string(),
35        _ => return_string(subject, title_mode),
36    };
37
38    fn return_string(subject: &str, title_mode: TitleMode) -> String {
39        let mut res = String::with_capacity(subject.len());
40        for (i, c) in crate::split::words(subject).iter().enumerate() {
41            let s = if i == 0 && title_mode == TitleMode::Normal {
42                lower_case(c)
43            } else {
44                capitalize(c, true)
45            };
46            res.push_str(&s);
47        }
48
49        res
50    }
51}
52
53/// Converts the first character of `subject` to upper case. If `restToLower` is `true`, convert the rest of `subject` to lower case.
54///
55/// # Arguments
56///
57/// * `subject` - The string to capitalize.
58/// * `rest_to_lower` - Convert the rest of `subject` to lower case.
59///
60/// # Example
61///
62/// ```
63/// use voca_rs::*;
64/// case::capitalize("green", true);
65/// // => "Green"
66/// case::capitalize("Say Hello to ME", true);
67/// // => "Say hello to me"
68/// use voca_rs::Voca;
69/// "green"._capitalize(true);
70/// // => "Green"
71/// ```
72pub fn capitalize(subject: &str, rest_to_lower: bool) -> String {
73    let rest_to_lower_mode = if rest_to_lower {
74        RestMode::Lower
75    } else {
76        RestMode::Normal
77    };
78    capitalize_decapitalize(subject, rest_to_lower_mode, CapsMode::Caps)
79}
80
81#[derive(Clone, Copy, PartialEq)]
82enum RestMode {
83    Lower,
84    Normal,
85}
86#[derive(Clone, Copy, PartialEq)]
87enum CapsMode {
88    Caps,
89    Small,
90}
91
92fn capitalize_decapitalize(subject: &str, rest_mode: RestMode, caps_mode: CapsMode) -> String {
93    return match subject.len() {
94        0 => subject.to_string(),
95        _ => return_string(subject, rest_mode, caps_mode),
96    };
97
98    fn return_string(subject: &str, rest_mode: RestMode, caps_mode: CapsMode) -> String {
99        let mut res = String::with_capacity(subject.len());
100
101        for (i, c) in crate::split::chars(subject).iter().enumerate() {
102            let s = if i == 0 {
103                match caps_mode {
104                    CapsMode::Caps => c.to_uppercase(),
105                    CapsMode::Small => c.to_lowercase(),
106                }
107            } else {
108                match rest_mode {
109                    RestMode::Lower => c.to_lowercase(),
110                    RestMode::Normal => (*c).to_string(),
111                }
112            };
113            res.push_str(&s);
114        }
115
116        res
117    }
118}
119/// Converts the first character of `subject` to lower case. If `restToLower` is `true`, convert the rest of `subject` to lower case.
120///
121/// # Arguments
122///
123/// * `subject` - The string to decapitalize.
124/// * `rest_to_lower` - Convert the rest of `subject` to lower case.
125/// # Example
126///
127/// ```
128/// use voca_rs::*;
129/// case::decapitalize("Green", true);
130/// // => "green"
131/// case::decapitalize("Say Hello to ME", false);
132/// // => "say Hello to ME"
133/// use voca_rs::Voca;
134/// "Green"._decapitalize(true);
135/// // => "green"
136/// ```
137pub fn decapitalize(subject: &str, rest_to_lower: bool) -> String {
138    let rest_to_lower_mode = if rest_to_lower {
139        RestMode::Lower
140    } else {
141        RestMode::Normal
142    };
143    capitalize_decapitalize(subject, rest_to_lower_mode, CapsMode::Small)
144}
145
146/// Converts the `subject` to kebab case.
147///
148/// # Arguments
149///
150/// * `subject` - The string to convert to kebab case.
151///
152/// # Example
153/// ```
154/// use voca_rs::*;
155/// case::kebab_case("goodbye blue sky");
156/// // => "goodbye-blue-sky"
157/// case::kebab_case("GoodbyeBlueSky");
158/// // => "goodbye-blue-sky"
159/// case::kebab_case("-Goodbye-Blue-Sky-");
160/// // => "goodbye-blue-sky"
161/// use voca_rs::Voca;
162/// "goodbye blue sky"._kebab_case();
163/// // => "goodbye-blue-sky"
164/// ```
165pub fn kebab_case(subject: &str) -> String {
166    kebab_and_shouty_kebab_and_train_case(subject, KebabMode::Normal)
167}
168
169/// Converts the `subject` to SHOUTY kebab case.
170///
171/// # Arguments
172///
173/// * `subject` - The string to convert to SHOUTY kebab case.
174///
175/// # Example
176/// ```
177/// use voca_rs::*;
178/// case::shouty_kebab_case("goodbye blue sky");
179/// // => "GOODBYE-BLUE-SKY"
180/// case::shouty_kebab_case("GoodbyeBlueSky");
181/// // => "GOODBYE-BLUE-SKY"
182/// case::shouty_kebab_case("-Goodbye-Blue-Sky-");
183/// // => "GOODBYE-BLUE-SKY"
184/// use voca_rs::Voca;
185/// "goodbye blue sky"._shouty_kebab_case();
186/// // => "GOODBYE-BLUE-SKY"
187/// ```
188pub fn shouty_kebab_case(subject: &str) -> String {
189    kebab_and_shouty_kebab_and_train_case(subject, KebabMode::Shouty)
190}
191
192#[derive(Clone, Copy, PartialEq)]
193enum KebabMode {
194    Normal,
195    Shouty,
196    Train,
197}
198
199fn kebab_and_shouty_kebab_and_train_case(subject: &str, kebab_mode: KebabMode) -> String {
200    match subject.len() {
201        0 => subject.to_string(),
202        _ => crate::split::words(subject)
203            .into_iter()
204            .map(|c| match kebab_mode {
205                KebabMode::Normal => lower_case(c),
206                KebabMode::Shouty => upper_case(c),
207                KebabMode::Train => capitalize(c, true),
208            })
209            .collect::<Vec<String>>()
210            .join("-"),
211    }
212}
213
214/// Converts the `subject` to lower case.
215///
216/// # Arguments
217///
218/// * `subject` - The string to convert to lower case.
219///
220/// # Example
221///
222/// ```
223/// use voca_rs::*;
224/// case::lower_case("Green");
225/// // => "green"
226/// case::lower_case("Say Hello to ME");
227/// // => "say hello to me"
228/// use voca_rs::Voca;
229/// "Green"._lower_case();
230/// // => "green"
231/// ```
232pub fn lower_case(subject: &str) -> String {
233    match subject.len() {
234        0 => subject.to_string(),
235        _ => {
236            let mut res = String::with_capacity(subject.len());
237            for c in crate::split::chars(subject).iter() {
238                res.push_str(&c.to_lowercase());
239            }
240            res
241        }
242    }
243}
244
245/// Converts the `subject` to pascal case.
246///
247/// # Arguments
248///
249/// * `subject` - The string to convert to pascal case.
250///
251/// # Example
252/// ```
253/// use voca_rs::*;
254/// case::pascal_case("bird flight");
255/// // => "BirdFlight"
256/// case::pascal_case("BirdFlight");
257/// // => "BirdFlight"
258/// case::pascal_case("-BIRD-FLIGHT-");
259/// // => "BirdFlight"
260/// use voca_rs::Voca;
261/// "bird flight"._pascal_case();
262/// // => "BirdFlight"
263/// ```
264pub fn pascal_case(subject: &str) -> String {
265    camel_and_pascal_case(subject, TitleMode::Caps)
266}
267
268/// Converts the `subject` to snake case.
269///
270/// # Arguments
271///
272/// * `subject` - The string to convert to snake case.
273///
274/// # Example
275/// ```
276/// use voca_rs::*;
277/// case::snake_case("learning to fly");
278/// // => "learning_to_fly"
279/// case::snake_case("LearningToFly");
280/// // => "learning_to_fly"
281/// case::snake_case("-Learning-To-Fly-");
282/// // => "learning_to_fly"
283/// use voca_rs::Voca;
284/// "learning to fly"._snake_case();
285/// // => "learning_to_fly"
286/// ```
287pub fn snake_case(subject: &str) -> String {
288    snake_and_shouty_snake_case(subject, false)
289}
290
291/// Converts the `subject` to SHOUTY snake case.
292///
293/// # Arguments
294///
295/// * `subject` - The string to convert to shouty snake case.
296///
297/// # Example
298/// ```
299/// use voca_rs::*;
300/// case::shouty_snake_case("learning to fly");
301/// // => "LEARNING_TO_FLY"
302/// case::shouty_snake_case("LearningToFly");
303/// // => "LEARNING_TO_FLY"
304/// case::shouty_snake_case("-Learning-To-Fly-");
305/// // => "LEARNING_TO_FLY"
306/// use voca_rs::Voca;
307/// "learning to fly"._shouty_snake_case();
308/// // => "LEARNING_TO_FLY"
309/// ```
310pub fn shouty_snake_case(subject: &str) -> String {
311    snake_and_shouty_snake_case(subject, true)
312}
313
314fn snake_and_shouty_snake_case(subject: &str, shouty: bool) -> String {
315    match subject.len() {
316        0 => subject.to_string(),
317        _ => crate::split::words(subject)
318            .into_iter()
319            .map(|c| {
320                if shouty {
321                    upper_case(c)
322                } else {
323                    lower_case(c)
324                }
325            })
326            .collect::<Vec<String>>()
327            .join("_"),
328    }
329}
330
331/// Converts the uppercase alpha characters of `subject` to lowercase and lowercase characters to uppercase.
332///
333/// # Arguments
334///
335/// * `subject` - The string to swap the case.
336///
337/// # Example
338/// ```
339/// use voca_rs::*;
340/// case::swap_case("League of Shadows");
341/// // => "lEAGUE OF sHADOWS"
342/// case::swap_case("2 üBer Bees");
343/// // => "2 ÜbER bEES"
344/// use voca_rs::Voca;
345/// "League of Shadows"._swap_case();
346/// // => "lEAGUE OF sHADOWS"
347/// ```
348pub fn swap_case(subject: &str) -> String {
349    match subject.len() {
350        0 => subject.to_string(),
351        _ => crate::split::chars(subject)
352            .into_iter()
353            .map(|s| {
354                s.chars()
355                    .filter_map(|c| {
356                        if c.is_lowercase() {
357                            c.to_uppercase().next()
358                        } else {
359                            c.to_lowercase().next()
360                        }
361                    })
362                    .collect()
363            })
364            .collect::<Vec<String>>()
365            .join(""),
366    }
367}
368
369/// Converts the `subject` to title case.
370///
371/// # Arguments
372///
373/// * `subject` - The string to convert to title case.
374///
375/// # Example
376/// ```
377/// use voca_rs::*;
378/// case::title_case("bird flight");
379/// // => "Bird Flight"
380/// case::title_case("BirdFlight");
381/// // => "Bird Flight"
382/// case::title_case("-BIRD-FLIGHT-");
383/// // => "Bird Flight"
384/// use voca_rs::Voca;
385/// "bird flight"._title_case();
386/// // => "Bird Flight"
387/// ```
388pub fn title_case(subject: &str) -> String {
389    match subject.len() {
390        0 => subject.to_string(),
391        _ => crate::split::words(subject)
392            .into_iter()
393            .map(|c| capitalize(c, true))
394            .collect::<Vec<String>>()
395            .join(" "),
396    }
397}
398
399/// Converts the `subject` to train case.
400///
401/// # Arguments
402///
403/// * `subject` - The string to convert to train case.
404///
405/// # Example
406/// ```
407/// use voca_rs::*;
408/// case::train_case("goodbye blue sky");
409/// // => "Goodbye-Blue-Sky"
410/// case::train_case("GoodbyeBlueSky");
411/// // => "Goodbye-Blue-Sky"
412/// case::train_case("-Goodbye-Blue-Sky-");
413/// // => "Goodbye-Blue-Sky"
414/// use voca_rs::Voca;
415/// "goodbye blue sky"._train_case();
416/// // => "Goodbye-Blue-Sky"
417/// ```
418pub fn train_case(subject: &str) -> String {
419    kebab_and_shouty_kebab_and_train_case(subject, KebabMode::Train)
420}
421
422/// Converts the `subject` to upper case.
423///
424/// # Arguments
425///
426/// * `subject` - The string to convert to upper case.
427///
428/// # Example
429///
430/// ```
431/// use voca_rs::*;
432/// case::upper_case("Green");
433/// // => "GREEN"
434/// case::upper_case("Say Hello to ME");
435/// // => "SAY HELLO TO ME"
436/// use voca_rs::Voca;
437/// "Green"._upper_case();
438/// // => "GREEN"
439/// ```
440pub fn upper_case(subject: &str) -> String {
441    match subject.len() {
442        0 => subject.to_string(),
443        _ => {
444            let mut res = String::with_capacity(subject.len());
445            for c in crate::split::chars(subject).iter() {
446                res.push_str(&c.to_uppercase());
447            }
448            res
449        }
450    }
451}
452
453/// Converts the first character of the `subject` to lower case.
454///
455/// # Arguments
456///
457/// * `subject` - The string to convert.
458///
459/// # Example
460///
461/// ```
462/// use voca_rs::*;
463/// case::lower_first("Fred");
464/// // => "fred"
465/// case::lower_first("FRED");
466/// // => "fRED"
467/// use voca_rs::Voca;
468/// "Fred"._lower_first();
469/// // => "fred"
470/// ```
471pub fn lower_first(subject: &str) -> String {
472    decapitalize(subject, false)
473}
474
475/// Converts the first character of the `subject` to upper case.
476///
477/// # Arguments
478///
479/// * `subject` - The string to convert.
480///
481/// # Example
482///
483/// ```
484/// use voca_rs::*;
485/// case::upper_first("fred");
486/// // => "Fred"
487/// case::upper_first("FRED");
488/// // => "FRED"
489/// use voca_rs::Voca;
490/// "fred"._upper_first();
491/// // => "Fred"
492/// ```
493pub fn upper_first(subject: &str) -> String {
494    capitalize(subject, false)
495}