use {
alloc::{
borrow::Cow,
string::{String, ToString},
},
core::{
cmp::Ordering,
fmt,
hash::{Hash, Hasher},
str::FromStr,
},
crate::Error,
};
#[derive(Debug, Eq)]
pub struct CainStr<'a> {
src: Cow<'a, str>,
lowercase: String,
}
impl CainStr<'_> {
pub fn lowercase(&self) -> &str {
&self.lowercase
}
pub fn into_lowercase(self) -> String {
self.lowercase
}
}
impl Clone for CainStr<'_> {
fn clone(&self) -> Self {
Self {
src: self.src.clone().into_owned().into(),
lowercase: self.lowercase.to_string(),
}
}
}
impl PartialEq for CainStr<'_> {
fn eq(&self, other: &Self) -> bool {
self.lowercase.eq(&other.lowercase)
}
}
impl Ord for CainStr<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.lowercase.cmp(&other.lowercase)
}
}
impl PartialOrd for CainStr<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Hash for CainStr<'_> {
fn hash<H>(&self, h: &mut H) where H: Hasher {
self.lowercase.hash(h);
}
}
impl fmt::Display for CainStr<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> core::result::Result<(), fmt::Error> {
f.write_str(&self.src)
}
}
impl<'a> From<Cow<'a, str>> for CainStr<'a> {
fn from(src: Cow<'a, str>) -> Self {
let lowercase = src.to_lowercase();
Self {
src,
lowercase,
}
}
}
impl<'a> From<CainStr<'a>> for Cow<'a, str> {
fn from(src: CainStr<'a>) -> Self {
src.src
}
}
impl<'a> From<&'a str> for CainStr<'a> {
fn from(src: &'a str) -> Self {
Self {
src: src.into(),
lowercase: src.to_lowercase(),
}
}
}
impl From<String> for CainStr<'_> {
fn from(src: String) -> Self {
let lowercase = src.to_lowercase();
Self {
src: src.into(),
lowercase,
}
}
}
impl FromStr for CainStr<'_> {
type Err = Error;
fn from_str(s: &str) -> core::result::Result<Self, Self::Err> {
Ok(Self::from(String::from(s)))
}
}
impl AsRef<str> for CainStr<'_> {
fn as_ref(&self) -> &str {
&self.src
}
}
#[test]
fn test_cain_str() {
let s = "UPPER-CASE";
assert_eq!(s.to_lowercase(), CainStr::from(s).lowercase);
}