use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::ops::Deref;
#[cfg(feature = "alloc")]
use ::rust_alloc::borrow::ToOwned;
use crate::clone::TryClone;
use crate::error::Error;
use crate::vec::Vec;
pub trait TryToOwned {
type Owned: Borrow<Self>;
fn try_to_owned(&self) -> Result<Self::Owned, Error>;
}
impl<T> TryToOwned for T
where
T: TryClone,
{
type Owned = T;
#[inline]
fn try_to_owned(&self) -> Result<T, Error> {
self.try_clone()
}
}
impl TryToOwned for crate::path::Path {
type Owned = crate::path::PathBuf;
fn try_to_owned(&self) -> Result<Self::Owned, Error> {
Ok(self.to_path_buf())
}
}
pub enum Cow<'b, T: ?Sized + 'b>
where
T: TryToOwned,
{
Borrowed(&'b T),
Owned(<T as TryToOwned>::Owned),
}
impl<B: ?Sized + TryToOwned> Cow<'_, B> {
pub const fn is_borrowed(&self) -> bool {
matches!(self, Cow::Borrowed(..))
}
pub const fn is_owned(&self) -> bool {
!self.is_borrowed()
}
pub fn try_to_mut(&mut self) -> Result<&mut <B as TryToOwned>::Owned, Error> {
Ok(match *self {
Cow::Borrowed(borrowed) => {
*self = Cow::Owned(borrowed.try_to_owned()?);
match *self {
Cow::Borrowed(..) => unreachable!(),
Cow::Owned(ref mut owned) => owned,
}
}
Cow::Owned(ref mut owned) => owned,
})
}
pub fn try_into_owned(self) -> Result<<B as TryToOwned>::Owned, Error> {
match self {
Cow::Borrowed(borrowed) => borrowed.try_to_owned(),
Cow::Owned(owned) => Ok(owned),
}
}
}
impl<'a, T: ?Sized + 'a> From<&'a T> for Cow<'a, T>
where
T: TryToOwned,
{
#[inline]
fn from(b: &'a T) -> Self {
Cow::Borrowed(b)
}
}
#[cfg(feature = "alloc")]
impl<'a, T: ?Sized + 'a> TryFrom<rust_alloc::borrow::Cow<'a, T>> for Cow<'a, T>
where
T: ToOwned + TryToOwned,
<T as TryToOwned>::Owned: TryFrom<<T as ToOwned>::Owned>,
{
type Error = <<T as TryToOwned>::Owned as TryFrom<<T as ToOwned>::Owned>>::Error;
fn try_from(value: rust_alloc::borrow::Cow<'a, T>) -> Result<Self, Self::Error> {
Ok(match value {
rust_alloc::borrow::Cow::Borrowed(b) => Cow::Borrowed(b),
rust_alloc::borrow::Cow::Owned(o) => Cow::Owned(<T as TryToOwned>::Owned::try_from(o)?),
})
}
}
impl<B: ?Sized + TryToOwned> Deref for Cow<'_, B>
where
B::Owned: Borrow<B>,
{
type Target = B;
fn deref(&self) -> &B {
match *self {
Cow::Borrowed(borrowed) => borrowed,
Cow::Owned(ref owned) => owned.borrow(),
}
}
}
impl<T: ?Sized + TryToOwned> AsRef<T> for Cow<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T: ?Sized> fmt::Display for Cow<'_, T>
where
T: fmt::Display + TryToOwned,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T: ?Sized> fmt::Debug for Cow<'_, T>
where
T: fmt::Debug + TryToOwned,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}
impl TryClone for Cow<'_, str> {
#[inline]
fn try_clone(&self) -> Result<Self, Error> {
Ok(match self {
Cow::Borrowed(b) => Cow::Borrowed(b),
Cow::Owned(o) => Cow::Owned(o.try_clone()?),
})
}
}
impl<T> From<Vec<T>> for Cow<'_, [T]>
where
T: TryClone,
{
fn from(vec: Vec<T>) -> Self {
Cow::Owned(vec)
}
}
impl<B: ?Sized> PartialEq for Cow<'_, B>
where
B: PartialEq + TryToOwned,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
(**self).eq(&**other)
}
}
impl<B: ?Sized> Eq for Cow<'_, B> where B: Eq + TryToOwned {}
impl<B: ?Sized> PartialOrd for Cow<'_, B>
where
B: PartialOrd + TryToOwned,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
}
impl<B: ?Sized> Ord for Cow<'_, B>
where
B: Ord + TryToOwned,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
(**self).cmp(&**other)
}
}
impl<B: ?Sized> Hash for Cow<'_, B>
where
B: Hash + TryToOwned,
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}