iron_ingot/str/
pascal_case_str.rs

1use 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}