cow2 0.2.0

Like Cow, but T is covariant
Documentation
#![allow(clippy::partialeq_ne_impl)]

use core::{
    borrow::Borrow,
    cmp::Ordering,
    fmt::{Debug, Display},
    hash::Hash,
    ops::{Add, AddAssign},
};

use alloc::{
    borrow::{self as b, ToOwned},
    string::String,
};

use crate::Cow;


impl<'a> Add<&'a str> for Cow<'a, str> {
    type Output = Self;

    fn add(mut self, rhs: &'a str) -> Self::Output {
        self += rhs;
        self
    }
}


impl<'a> Add<Cow<'a, str>> for Cow<'a, str> {
    type Output = Self;

    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}


impl<'a> Add<b::Cow<'a, str>> for Cow<'a, str> {
    type Output = Self;

    fn add(mut self, rhs: b::Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}


impl<'a> Add<Cow<'a, str>> for b::Cow<'a, str> {
    type Output = Self;

    fn add(mut self, rhs: Cow<'a, str>) -> Self::Output {
        self += rhs;
        self
    }
}


impl<'a> AddAssign<&'a str> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: &'a str) {
        if self.is_empty() {
            *self = Self::Borrowed(rhs)
        } else if !rhs.is_empty() {
            if let Self::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = s.into();
            }
            self.to_mut().push_str(rhs);
        }
    }
}


impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs
        } else if !rhs.is_empty() {
            if let Self::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = s.into();
            }
            self.to_mut().push_str(&rhs);
        }
    }
}


impl<'a> AddAssign<Cow<'a, str>> for b::Cow<'a, str> {
    fn add_assign(&mut self, rhs: Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs.into()
        } else if !rhs.is_empty() {
            if let Self::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = s.into();
            }
            self.to_mut().push_str(&rhs);
        }
    }
}


impl<'a> AddAssign<b::Cow<'a, str>> for Cow<'a, str> {
    fn add_assign(&mut self, rhs: b::Cow<'a, str>) {
        if self.is_empty() {
            *self = rhs.into()
        } else if !rhs.is_empty() {
            if let Self::Borrowed(lhs) = *self {
                let mut s = String::with_capacity(lhs.len() + rhs.len());
                s.push_str(lhs);
                *self = s.into();
            }
            self.to_mut().push_str(&rhs);
        }
    }
}


impl<T> AsRef<T> for Cow<'_, T>
where T: ToOwned + ?Sized,
{
    fn as_ref(&self) -> &T {
        self
    }
}


#[cfg(feature = "std")]
impl AsRef<std::path::Path> for Cow<'_, std::ffi::OsStr> {
    fn as_ref(&self) -> &std::path::Path {
        (**self).as_ref()
    }
}


impl<T> Borrow<T> for Cow<'_, T>
where T: ToOwned + ?Sized,
{
    fn borrow(&self) -> &T {
        self
    }
}


impl<T> Debug for Cow<'_, T>
where T: ToOwned + ?Sized + Debug,
      T::Owned: Debug,
{
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Cow::Borrowed(borrowed) => borrowed.fmt(f),
            Cow::Owned(owned) => owned.fmt(f),
        }
    }
}


impl<T> Default for Cow<'_, T>
where T: ToOwned + ?Sized,
      T::Owned: Default,
{
    fn default() -> Self {
        Self::Owned(Default::default())
    }
}


impl<T> Display for Cow<'_, T>
where T: ToOwned + ?Sized + Display,
      T::Owned: Display,
{
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Cow::Borrowed(borrowed) => borrowed.fmt(f),
            Cow::Owned(owned) => owned.fmt(f),
        }
    }
}


impl<T> Eq for Cow<'_, T>
where T: ToOwned + ?Sized + Eq,
{
}


impl<T> Ord for Cow<'_, T>
where T: ToOwned + ?Sized + Ord,
{
    fn cmp(&self, other: &Self) -> Ordering {
        (**self).cmp(other)
    }
}


impl<B> PartialEq for Cow<'_, B>
where B: ToOwned + ?Sized + PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        **self == **other
    }

    fn ne(&self, other: &Self) -> bool {
        **self != **other
    }
}


impl<B> PartialOrd for Cow<'_, B>
where B: ToOwned + ?Sized + PartialOrd,
{
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        (**self).partial_cmp(&**other)
    }

    fn lt(&self, other: &Self) -> bool {
        (**self).lt(&**other)
    }

    fn le(&self, other: &Self) -> bool {
        (**self).le(&**other)
    }

    fn gt(&self, other: &Self) -> bool {
        (**self).gt(&**other)
    }

    fn ge(&self, other: &Self) -> bool {
        (**self).ge(&**other)
    }
}


impl<T, B> PartialEq<T> for Cow<'_, B>
where B: ToOwned + ?Sized,
      for<'a> b::Cow<'a, B>: PartialEq<T>,
{
    fn eq(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self) == *other
    }

    fn ne(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self) != *other
    }
}


impl<T, B> PartialOrd<T> for Cow<'_, B>
where B: ToOwned + ?Sized,
      for<'a> b::Cow<'a, B>: PartialOrd<T>,
{
    fn partial_cmp(&self, other: &T) -> Option<Ordering> {
        b::Cow::Borrowed(&**self).partial_cmp(other)
    }

    fn lt(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self).lt(other)
    }

    fn le(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self).le(other)
    }

    fn gt(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self).gt(other)
    }

    fn ge(&self, other: &T) -> bool {
        b::Cow::Borrowed(&**self).ge(other)
    }
}


impl<'a> Extend<Cow<'a, str>> for String {
    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
        iter.into_iter().for_each(|s| self.push_str(&s));
    }
}


#[cfg(feature = "std")]
impl<'a> Extend<Cow<'a, std::ffi::OsStr>> for std::ffi::OsString {
    fn extend<T: IntoIterator<Item = Cow<'a, std::ffi::OsStr>>>(&mut self, iter: T) {
        iter.into_iter().for_each(|s| self.push(&*s));
    }
}


impl<'a, T, B> From<T> for Cow<'a, B>
where B: ToOwned + ?Sized,
      b::Cow<'a, B>: From<T>,
{
    fn from(value: T) -> Self {
        match value.into() {
            b::Cow::Borrowed(borrowed) => Self::Borrowed(borrowed),
            b::Cow::Owned(owned) => Self::Owned(owned),
        }
    }
}


#[allow(clippy::from_over_into)]
impl<'a, B> Into<b::Cow<'a, B>> for Cow<'a, B>
where B: ToOwned + ?Sized,
{
    fn into(self) -> b::Cow<'a, B> {
        match self {
            Cow::Borrowed(borrowed) => b::Cow::Borrowed(borrowed),
            Cow::Owned(owned) => b::Cow::Owned(owned),
        }
    }
}


impl<'a, T, B> FromIterator<T> for Cow<'a, B>
where B: ToOwned + ?Sized,
      b::Cow<'a, B>: FromIterator<T>,
{
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
        b::Cow::from_iter(iter).into()
    }
}


impl<B> Hash for Cow<'_, B>
where B: ToOwned + ?Sized + Hash,
{
    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}