1use alloc::borrow::{Cow, Borrow};
2use alloc::{string::String, boxed::Box};
3
4use core::ops::Deref;
5use core::cmp::Ordering;
6use core::hash::{Hash, Hasher};
7use core::fmt;
8
9use crate::{UncasedStr, AsUncased};
10
11#[cfg_attr(nightly, doc(cfg(feature = "alloc")))]
14#[derive(Clone, Debug)]
15pub struct Uncased<'s> {
16 #[doc(hidden)]
17 pub string: Cow<'s, str>
18}
19
20impl<'s> Uncased<'s> {
21 #[inline(always)]
33 pub fn new<S: Into<Cow<'s, str>>>(string: S) -> Uncased<'s> {
34 Uncased { string: string.into() }
35 }
36
37 #[inline(always)]
49 pub const fn from_borrowed(string: &'s str) -> Uncased<'s> {
50 Uncased { string: Cow::Borrowed(string) }
51 }
52
53 #[inline(always)]
67 pub const fn from_owned(string: String) -> Uncased<'s> {
68 Uncased { string: Cow::Owned(string) }
69 }
70
71 #[inline(always)]
85 pub fn as_uncased_str(&self) -> &UncasedStr {
86 self.as_ref()
87 }
88
89 #[inline(always)]
101 pub fn into_string(self) -> String {
102 self.string.into_owned()
103 }
104
105 #[inline(always)]
119 pub fn into_owned(self) -> Uncased<'static> {
120 match self.string {
121 Cow::Owned(string) => Uncased::new(string),
122 Cow::Borrowed(str) => Uncased::new(String::from(str)),
123 }
124 }
125
126 #[inline(always)]
137 pub fn into_boxed_uncased(self) -> Box<UncasedStr> {
138 unsafe {
142 let raw_str = Box::into_raw(self.string.into_owned().into_boxed_str());
143 Box::from_raw(raw_str as *mut UncasedStr)
144 }
145 }
146
147 #[doc(hidden)]
149 #[inline(always)]
150 pub fn into_cow(self) -> Cow<'s, str> {
151 self.string
152 }
153}
154
155impl Deref for Uncased<'_> {
156 type Target = UncasedStr;
157
158 #[inline(always)]
159 fn deref(&self) -> &UncasedStr {
160 UncasedStr::new(self.string.borrow())
161 }
162}
163
164impl AsRef<UncasedStr> for Uncased<'_> {
165 #[inline(always)]
166 fn as_ref(&self) -> &UncasedStr {
167 UncasedStr::new(self.string.borrow())
168 }
169}
170
171impl AsRef<str> for Uncased<'_> {
172 #[inline(always)]
173 fn as_ref(&self) -> &str {
174 self.as_str()
175 }
176}
177
178impl AsRef<[u8]> for Uncased<'_> {
179 #[inline(always)]
180 fn as_ref(&self) -> &[u8] {
181 self.as_str().as_bytes()
182 }
183}
184
185impl Borrow<UncasedStr> for Uncased<'_> {
186 #[inline(always)]
187 fn borrow(&self) -> &UncasedStr {
188 self.as_str().into()
189 }
190}
191
192impl<'s, 'c: 's> From<&'c UncasedStr> for Uncased<'s> {
193 #[inline(always)]
194 fn from(string: &'c UncasedStr) -> Self {
195 Uncased::new(string.as_str())
196 }
197}
198
199impl<'s, 'c: 's> From<&'c str> for Uncased<'s> {
200 #[inline(always)]
201 fn from(string: &'c str) -> Self {
202 Uncased::new(string)
203 }
204}
205
206impl From<String> for Uncased<'static> {
207 #[inline(always)]
208 fn from(string: String) -> Self {
209 Uncased::new(string)
210 }
211}
212
213impl<'s, 'c: 's> From<Cow<'c, str>> for Uncased<'s> {
214 #[inline(always)]
215 fn from(string: Cow<'c, str>) -> Self {
216 Uncased::new(string)
217 }
218}
219
220impl fmt::Display for Uncased<'_> {
221 #[inline(always)]
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 self.string.fmt(f)
224 }
225}
226
227macro_rules! impl_partial_eq {
228 ($other:ty $([$o_i:ident])? = $this:ty $([$t_i:ident])?) => (
229 impl PartialEq<$other> for $this {
230 #[inline(always)]
231 fn eq(&self, other: &$other) -> bool {
232 let this: &UncasedStr = self$(.$t_i())?;
233 let other: &UncasedStr = other$(.$o_i())?;
234 this.eq(other)
235 }
236 }
237 )
238}
239
240impl_partial_eq!(Uncased<'_> [as_uncased_str] = Uncased<'_> [as_uncased_str]);
241impl_partial_eq!(str [as_uncased] = Uncased<'_> [as_uncased_str]);
242impl_partial_eq!(Uncased<'_> [as_uncased_str] = str [as_uncased]);
243impl_partial_eq!(&str [as_uncased] = Uncased<'_> [as_uncased_str]);
244impl_partial_eq!(Uncased<'_> [as_uncased_str] = &str [as_uncased]);
245impl_partial_eq!(String [as_uncased] = Uncased<'_> [as_uncased_str]);
246impl_partial_eq!(Uncased<'_> [as_uncased_str] = String [as_uncased]);
247impl_partial_eq!(String [as_uncased] = &Uncased<'_> [as_uncased_str]);
248impl_partial_eq!(&Uncased<'_> [as_uncased_str] = String [as_uncased]);
249impl_partial_eq!(UncasedStr = Uncased<'_> [as_uncased_str]);
250impl_partial_eq!(&UncasedStr = Uncased<'_> [as_uncased_str]);
251impl_partial_eq!(Uncased<'_> [as_uncased_str] = UncasedStr);
252impl_partial_eq!(Uncased<'_> [as_uncased_str] = &UncasedStr);
253impl_partial_eq!(UncasedStr = &Uncased<'_> [as_uncased_str]);
254impl_partial_eq!(&Uncased<'_> [as_uncased_str] = UncasedStr);
255
256macro_rules! impl_partial_ord {
257 ($other:ty $([$o_i:ident])? >< $this:ty $([$t_i:ident])?) => (
258 impl PartialOrd<$other> for $this {
259 #[inline(always)]
260 fn partial_cmp(&self, other: &$other) -> Option<Ordering> {
261 let this: &UncasedStr = self$(.$t_i())?;
262 let other: &UncasedStr = other$(.$o_i())?;
263 this.partial_cmp(other)
264 }
265 }
266 )
267}
268
269impl Ord for Uncased<'_> {
270 fn cmp(&self, other: &Self) -> Ordering {
271 self.as_uncased_str().cmp(other.as_uncased_str())
272 }
273}
274
275impl_partial_ord!(Uncased<'_> [as_uncased_str] >< Uncased<'_> [as_uncased_str]);
276impl_partial_ord!(str [as_uncased] >< Uncased<'_> [as_uncased_str]);
277impl_partial_ord!(Uncased<'_> [as_uncased_str] >< str [as_uncased]);
278impl_partial_ord!(String [as_uncased] >< Uncased<'_> [as_uncased_str]);
279impl_partial_ord!(Uncased<'_> [as_uncased_str] >< String [as_uncased]);
280impl_partial_ord!(String [as_uncased] >< &Uncased<'_> [as_uncased_str]);
281impl_partial_ord!(&Uncased<'_> [as_uncased_str] >< String [as_uncased]);
282impl_partial_ord!(UncasedStr >< Uncased<'_> [as_uncased_str]);
283impl_partial_ord!(&UncasedStr >< Uncased<'_> [as_uncased_str]);
284impl_partial_ord!(Uncased<'_> [as_uncased_str] >< UncasedStr);
285impl_partial_ord!(UncasedStr >< &Uncased<'_> [as_uncased_str]);
286impl_partial_ord!(Uncased<'_> [as_uncased_str] >< &UncasedStr);
287impl_partial_ord!(&Uncased<'_> [as_uncased_str] >< UncasedStr);
288
289impl Eq for Uncased<'_> { }
290
291impl Hash for Uncased<'_> {
292 #[inline(always)]
293 fn hash<H: Hasher>(&self, hasher: &mut H) {
294 self.as_uncased_str().hash(hasher)
295 }
296}