iron_ingot/str/
pascal_case_str.rs1use crate::{
2 camel_case_str::ToCamelCase, lower_case_str::ToLowerCase, screaming_case_str::ToScreamingCase,
3 snake_case_str::ToSnakeCase, title_case_str::ToTitleCase, to_words::ToWords,
4 upper_case_str::ToUpperCase,
5};
6
7use std::borrow::Cow;
8
9#[derive(Copy, Clone, Debug)]
10pub struct PascalCaseStr<'a>(&'a str);
11
12impl<'a> PascalCaseStr<'a> {
13 pub fn new(value: &'a str) -> Self {
14 debug_assert!(
15 value.chars().next().unwrap().is_uppercase(),
16 "The first character of a pascal case string must be a capital letter!"
17 );
18 debug_assert!(
19 value.chars().all(|ch| ch.is_alphanumeric()),
20 "Pascal case string given must only contain letters and digits!"
21 );
22 Self(value)
23 }
24}
25
26impl ToWords for PascalCaseStr<'_> {
27 fn to_words(&self) -> Cow<[String]> {
28 let mut words = vec![];
29 let mut cap_letter = "";
30 for substr in (self.0.to_owned() + "A").split_inclusive(char::is_uppercase) {
31 let word = cap_letter.to_owned() + &substr[..substr.len() - 1];
32 if !word.is_empty() {
33 words.push(word);
34 }
35 cap_letter = &substr[substr.len() - 1..];
36 }
37 words.into()
38 }
39}
40
41impl ToCamelCase for PascalCaseStr<'_> {
42 fn to_camel_case(&self) -> String {
43 self.0[0..1].to_lowercase() + &self.0[1..]
44 }
45}
46
47impl ToLowerCase for PascalCaseStr<'_> {
48 fn to_lower_case(&self) -> String {
49 self
50 .to_words()
51 .iter()
52 .map(|word| word.to_lowercase())
53 .fold("".to_owned(), |result, word| result + &word + " ")
54 .trim_end()
55 .to_owned()
56 }
57}
58
59impl ToScreamingCase for PascalCaseStr<'_> {
60 fn to_screaming_case(&self) -> String {
61 self
62 .to_words()
63 .iter()
64 .map(|word| word.to_uppercase())
65 .fold("".to_owned(), |result, word| result + &word + "_")
66 .trim_end_matches('_')
67 .to_owned()
68 }
69}
70
71impl ToSnakeCase for PascalCaseStr<'_> {
72 fn to_snake_case(&self) -> String {
73 self
74 .to_words()
75 .iter()
76 .map(|word| word.to_lowercase())
77 .fold("".to_owned(), |result, word| result + &word + "_")
78 .trim_end_matches('_')
79 .to_owned()
80 }
81}
82
83impl ToTitleCase for PascalCaseStr<'_> {
84 fn to_title_case(&self) -> String {
85 self
86 .to_words()
87 .iter()
88 .fold("".to_owned(), |result, word| result + word + " ")
89 .trim_end()
90 .to_owned()
91 }
92}
93
94impl ToUpperCase for PascalCaseStr<'_> {
95 fn to_upper_case(&self) -> String {
96 self
97 .to_words()
98 .iter()
99 .map(|word| word.to_uppercase())
100 .fold("".to_owned(), |result, word| result + &word + " ")
101 .trim_end()
102 .to_owned()
103 }
104}
105
106pub trait ToPascalCase {
107 fn to_pascal_case(&self) -> String;
108}
109
110impl ToPascalCase for PascalCaseStr<'_> {
111 fn to_pascal_case(&self) -> String {
112 self.0.to_owned()
113 }
114}