1use std::borrow::{Borrow, Cow};
4use std::fmt::{Display, Error, Formatter};
5#[cfg(any(feature = "vic3", feature = "imperator"))]
6use std::slice::SliceIndex;
7#[cfg(any(feature = "vic3", feature = "imperator"))]
8use std::str::RMatchIndices;
9
10#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
20pub struct Lowercase<'a>(Cow<'a, str>);
21
22impl<'a> Lowercase<'a> {
23 pub fn new(s: &'a str) -> Self {
25 if s.chars().any(|c| c.is_ascii_uppercase()) {
27 Lowercase(Cow::Owned(s.to_ascii_lowercase()))
28 } else {
29 Lowercase(Cow::Borrowed(s))
30 }
31 }
32
33 pub fn new_unchecked(s: &'a str) -> Self {
37 Lowercase(Cow::Borrowed(s))
38 }
39
40 pub fn from_string_unchecked(s: String) -> Self {
42 Lowercase(Cow::Owned(s))
43 }
44
45 pub fn empty() -> &'static Self {
46 const EMPTY_LOWERCASE: Lowercase = Lowercase(Cow::Borrowed(""));
47 &EMPTY_LOWERCASE
48 }
49
50 pub fn as_str(&'a self) -> &'a str {
51 &self.0
52 }
53
54 pub fn into_cow(self) -> Cow<'a, str> {
55 self.0
56 }
57
58 pub fn to_uppercase(&self) -> String {
59 self.as_str().to_ascii_uppercase()
60 }
61
62 pub fn strip_prefix_unchecked<S: Borrow<str>>(&'a self, prefix: S) -> Option<Lowercase<'a>> {
64 self.0.strip_prefix(prefix.borrow()).map(|s| Self(Cow::Borrowed(s)))
65 }
66
67 pub fn strip_suffix_unchecked<S: Borrow<str>>(&'a self, suffix: S) -> Option<Lowercase<'a>> {
69 self.0.strip_suffix(suffix.borrow()).map(|s| Self(Cow::Borrowed(s)))
70 }
71
72 #[allow(dead_code)]
73 pub fn contains_unchecked<S: Borrow<str>>(&self, infix: S) -> bool {
74 self.0.contains(infix.borrow())
75 }
76
77 #[cfg(any(feature = "vic3", feature = "imperator"))]
78 pub fn rmatch_indices_unchecked(&self, separator: char) -> RMatchIndices<'_, char> {
79 self.0.rmatch_indices(separator)
80 }
81
82 #[cfg(any(feature = "vic3", feature = "imperator"))]
83 pub fn slice<R: 'a + SliceIndex<str, Output = str>>(&'a self, range: R) -> Self {
84 Lowercase::new_unchecked(&self.0[range])
85 }
86}
87
88impl Display for Lowercase<'_> {
89 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
90 write!(f, "{}", self.0)
91 }
92}
93
94impl<'a> Borrow<Cow<'a, str>> for Lowercase<'a> {
95 fn borrow(&self) -> &Cow<'a, str> {
96 &self.0
97 }
98}
99
100impl Borrow<str> for Lowercase<'_> {
101 fn borrow(&self) -> &str {
102 &self.0
103 }
104}
105
106impl Default for Lowercase<'static> {
107 fn default() -> Lowercase<'static> {
108 Lowercase::new_unchecked("")
109 }
110}
111
112impl PartialEq<str> for Lowercase<'_> {
113 fn eq(&self, s: &str) -> bool {
114 self.as_str() == s
115 }
116}
117
118impl PartialEq<&str> for Lowercase<'_> {
119 fn eq(&self, s: &&str) -> bool {
120 self.as_str() == *s
121 }
122}
123
124impl PartialEq<String> for &Lowercase<'_> {
125 fn eq(&self, s: &String) -> bool {
126 self.as_str() == s
127 }
128}