1use std::fmt;
2
3use crate::{capitalize, transform};
4
5/// This trait defines an upper camel case conversion.
6///
7/// In UpperCamelCase, word boundaries are indicated by capital letters,
8/// including the first word.
9///
10/// ## Example:
11///
12/// ```rust
13/// use heck::ToUpperCamelCase;
14///
15/// let sentence = "We are not in the least afraid of ruins.";
16/// assert_eq!(sentence.to_upper_camel_case(), "WeAreNotInTheLeastAfraidOfRuins");
17/// ```
18pub trait ToUpperCamelCase: ToOwned {
19 /// Convert this type to upper camel case.
20 fn to_upper_camel_case(&self) -> Self::Owned;
21}
22
23impl ToUpperCamelCase for str {
24 fn to_upper_camel_case(&self) -> String {
25 AsUpperCamelCase(self).to_string()
26 }
27}
28
29/// ToPascalCase is an alias for ToUpperCamelCase. See ToUpperCamelCase for more
30/// documentation.
31pub trait ToPascalCase: ToOwned {
32 /// Convert this type to upper camel case.
33 fn to_pascal_case(&self) -> Self::Owned;
34}
35
36impl<T: ?Sized + ToUpperCamelCase> ToPascalCase for T {
37 fn to_pascal_case(&self) -> Self::Owned {
38 self.to_upper_camel_case()
39 }
40}
41
42/// This wrapper performs a upper camel case conversion in [`fmt::Display`].
43///
44/// ## Example:
45///
46/// ```
47/// use heck::AsUpperCamelCase;
48///
49/// let sentence = "We are not in the least afraid of ruins.";
50/// assert_eq!(format!("{}", AsUpperCamelCase(sentence)), "WeAreNotInTheLeastAfraidOfRuins");
51/// ```
52pub struct AsUpperCamelCase<T: AsRef<str>>(pub T);
53
54impl<T: AsRef<str>> fmt::Display for AsUpperCamelCase<T> {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 transform(self.0.as_ref(), with_word:capitalize, |_| Ok(()), f)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::ToUpperCamelCase;
63
64 macro_rules! t {
65 ($t:ident : $s1:expr => $s2:expr) => {
66 #[test]
67 fn $t() {
68 assert_eq!($s1.to_upper_camel_case(), $s2)
69 }
70 };
71 }
72
73 t!(test1: "CamelCase" => "CamelCase");
74 t!(test2: "This is Human case." => "ThisIsHumanCase");
75 t!(test3: "MixedUP_CamelCase, with some Spaces" => "MixedUpCamelCaseWithSomeSpaces");
76 t!(test4: "mixed_up_ snake_case, with some _spaces" => "MixedUpSnakeCaseWithSomeSpaces");
77 t!(test5: "kebab-case" => "KebabCase");
78 t!(test6: "SHOUTY_SNAKE_CASE" => "ShoutySnakeCase");
79 t!(test7: "snake_case" => "SnakeCase");
80 t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "ThisContainsAllKindsOfWordBoundaries");
81 #[cfg(feature = "unicode")]
82 t!(test9: "XΣXΣ baffle" => "XσxςBaffle");
83 t!(test10: "XMLHttpRequest" => "XmlHttpRequest");
84}
85