#![cfg_attr(not(feature = "std"), no_std)]
use core::{
cmp::Ordering,
fmt::{self, Debug, Formatter},
hash::{Hash, Hasher},
marker::PhantomData,
};
pub trait Borrow<'a, T>
where
T: for<'b> BorrowHkt<'b>,
{
fn borrow<'b>(&'a self) -> Borrowed<'b, T>
where
'a: 'b;
}
impl<'a> Borrow<'a, BorrowString> for &str {
fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowString>
where
'a: 'b,
{
self
}
}
#[cfg(feature = "std")]
impl<'a> Borrow<'a, BorrowString> for String {
fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowString>
where
'a: 'b,
{
self
}
}
pub trait BorrowHkt<'a> {
type T;
}
pub struct BorrowString;
impl<'a> BorrowHkt<'a> for BorrowString {
type T = &'a str;
}
pub type Borrowed<'a, T> = <T as BorrowHkt<'a>>::T;
pub trait BorrowMut<'a, T>: Borrow<'a, T>
where
T: for<'b> BorrowMutHkt<'b>,
{
fn borrow_mut<'b>(&'a mut self) -> BorrowedMut<'b, T>
where
'a: 'b;
}
pub trait BorrowMutHkt<'a>: BorrowHkt<'a> {
type T;
}
pub type BorrowedMut<'a, T> = <T as BorrowMutHkt<'a>>::T;
pub trait ToOwned: Sized {
type Owned;
fn to_owned(&self) -> Self::Owned;
fn into_owned(self) -> Self::Owned {
self.to_owned()
}
}
#[cfg(feature = "std")]
impl ToOwned for &str {
type Owned = String;
fn to_owned(&self) -> Self::Owned {
std::borrow::ToOwned::to_owned(*self)
}
}
#[cfg(feature = "std")]
impl ToOwned for String {
type Owned = String;
fn to_owned(&self) -> Self::Owned {
self.clone()
}
fn into_owned(self) -> Self::Owned {
self
}
}
#[cfg(feature = "std")]
impl<T> ToOwned for std::borrow::Cow<'_, T>
where
T: std::borrow::ToOwned + 'static,
T::Owned: Clone,
{
type Owned = std::borrow::Cow<'static, T>;
fn to_owned(&self) -> std::borrow::Cow<'static, T> {
let owned = match self {
Self::Borrowed(x) => T::to_owned(x),
Self::Owned(x) => x.clone(),
};
std::borrow::Cow::Owned(owned)
}
fn into_owned(self) -> std::borrow::Cow<'static, T> {
let owned = match self {
Self::Borrowed(x) => T::to_owned(x),
Self::Owned(x) => x,
};
std::borrow::Cow::Owned(owned)
}
}
pub enum Cow<'a, T>
where
T: Cowable,
{
Borrowed(CowableBorrowed<'a, T>),
Owned(CowableOwned<T>),
}
impl<'a, T> Cow<'a, T>
where
T: Cowable,
{
pub fn borrowed(borrowed: impl Into<CowableBorrowed<'a, T>>) -> Self {
Self::Borrowed(borrowed.into())
}
pub fn owned(owned: impl Into<CowableOwned<T>>) -> Self {
Self::Owned(owned.into())
}
pub fn is_borrowed(&self) -> bool {
matches!(self, Self::Borrowed(_))
}
pub fn is_owned(&self) -> bool {
matches!(self, Self::Owned(_))
}
pub fn unwrap_borrowed(self) -> CowableBorrowed<'a, T> {
match self {
Self::Borrowed(x) => x,
Self::Owned(_) => panic!("Cow contains owned data"),
}
}
pub fn unwrap_owned(self) -> CowableOwned<T> {
match self {
Self::Borrowed(_) => panic!("Cow contains borrowed data"),
Self::Owned(x) => x,
}
}
}
impl<'a, T> Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: ToOwned<Owned = CowableOwned<T>>,
{
pub fn to_mut(&mut self) -> &mut CowableOwned<T> {
match self {
Self::Borrowed(x) => {
*self = Cow::Owned(x.to_owned());
match self {
Self::Borrowed(_) => unreachable!(),
Self::Owned(x) => x,
}
}
Self::Owned(x) => x,
}
}
pub fn into_inner(self) -> CowableOwned<T> {
match self {
Self::Borrowed(x) => x.into_owned(),
Self::Owned(x) => x,
}
}
}
impl<'a, T> Borrow<'a, BorrowCow<T>> for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Borrow<'a, T::BorrowHkt>,
CowableOwned<T>: Borrow<'a, T::BorrowHkt>,
{
fn borrow<'b>(&'a self) -> Borrowed<'b, BorrowCow<T>>
where
'a: 'b,
{
match self {
Self::Borrowed(x) => Cow::Borrowed(x.borrow()),
Self::Owned(x) => Cow::Borrowed(x.borrow()),
}
}
}
impl<'a, T> ToOwned for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: ToOwned<Owned = CowableOwned<T>>,
CowableOwned<T>: Clone,
{
type Owned = Cow<'static, T>;
fn to_owned(&self) -> Cow<'static, T> {
match self {
Self::Borrowed(x) => Cow::Owned(x.to_owned()),
Self::Owned(x) => Cow::Owned(x.clone()),
}
}
fn into_owned(self) -> Cow<'static, T> {
match self {
Self::Borrowed(x) => Cow::Owned(x.into_owned()),
Self::Owned(x) => Cow::Owned(x),
}
}
}
impl<'a, T> Clone for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Clone,
CowableOwned<T>: Clone,
{
fn clone(&self) -> Self {
match self {
Self::Borrowed(x) => Self::Borrowed(x.clone()),
Self::Owned(x) => Self::Owned(x.clone()),
}
}
}
impl<'a, T> Copy for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Copy,
CowableOwned<T>: Copy,
{
}
impl<'a, T> Debug for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Debug,
CowableOwned<T>: Debug,
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Borrowed(x) => x.fmt(f),
Self::Owned(x) => x.fmt(f),
}
}
}
impl<T> Default for Cow<'_, T>
where
T: Cowable,
CowableOwned<T>: Default,
{
fn default() -> Self {
Self::Owned(Default::default())
}
}
impl<'a, T> Hash for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Hash,
CowableOwned<T>: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Self::Borrowed(x) => x.hash(state),
Self::Owned(x) => x.hash(state),
}
}
}
impl<'a, T> PartialEq<Cow<'a, T>> for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: PartialEq + PartialEq<CowableOwned<T>>,
CowableOwned<T>: PartialEq + PartialEq<CowableBorrowed<'a, T>>,
{
fn eq(&self, other: &Cow<'a, T>) -> bool {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.eq(b),
(Self::Borrowed(a), Self::Owned(b)) => a.eq(b),
(Self::Owned(a), Self::Borrowed(b)) => a.eq(b),
(Self::Owned(a), Self::Owned(b)) => a.eq(b),
}
}
}
impl<'a, T> Eq for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Eq + PartialEq<CowableOwned<T>>,
CowableOwned<T>: Eq + PartialEq<CowableBorrowed<'a, T>>,
{
}
impl<'a, T> PartialOrd for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: PartialOrd + PartialOrd<CowableOwned<T>>,
CowableOwned<T>: PartialOrd + PartialOrd<CowableBorrowed<'a, T>>,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.partial_cmp(b),
(Self::Borrowed(a), Self::Owned(b)) => a.partial_cmp(b),
(Self::Owned(a), Self::Borrowed(b)) => a.partial_cmp(b),
(Self::Owned(a), Self::Owned(b)) => a.partial_cmp(b),
}
}
fn ge(&self, other: &Self) -> bool {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.ge(b),
(Self::Borrowed(a), Self::Owned(b)) => a.ge(b),
(Self::Owned(a), Self::Borrowed(b)) => a.ge(b),
(Self::Owned(a), Self::Owned(b)) => a.ge(b),
}
}
fn gt(&self, other: &Self) -> bool {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.gt(b),
(Self::Borrowed(a), Self::Owned(b)) => a.gt(b),
(Self::Owned(a), Self::Borrowed(b)) => a.gt(b),
(Self::Owned(a), Self::Owned(b)) => a.gt(b),
}
}
fn le(&self, other: &Self) -> bool {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.le(b),
(Self::Borrowed(a), Self::Owned(b)) => a.le(b),
(Self::Owned(a), Self::Borrowed(b)) => a.le(b),
(Self::Owned(a), Self::Owned(b)) => a.le(b),
}
}
fn lt(&self, other: &Self) -> bool {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.lt(b),
(Self::Borrowed(a), Self::Owned(b)) => a.lt(b),
(Self::Owned(a), Self::Borrowed(b)) => a.lt(b),
(Self::Owned(a), Self::Owned(b)) => a.lt(b),
}
}
}
impl<'a, T> Ord for Cow<'a, T>
where
T: Cowable,
CowableBorrowed<'a, T>: Ord + PartialOrd<CowableOwned<T>>,
CowableOwned<T>: Ord + PartialOrd<CowableBorrowed<'a, T>>,
{
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Self::Borrowed(a), Self::Borrowed(b)) => a.cmp(b),
(Self::Borrowed(a), Self::Owned(b)) => a.partial_cmp(b).unwrap(),
(Self::Owned(a), Self::Borrowed(b)) => a.partial_cmp(b).unwrap(),
(Self::Owned(a), Self::Owned(b)) => a.cmp(b),
}
}
}
pub struct BorrowCow<T>(PhantomData<T>);
impl<'a, T> BorrowHkt<'a> for BorrowCow<T>
where
T: Cowable,
{
type T = Cow<'a, T>;
}
pub trait Cowable {
type BorrowHkt: for<'a> BorrowHkt<'a>;
type Owned;
}
impl<B, O> Cowable for B
where
B: for<'a> BorrowHkt<'a>,
for<'a> <B as BorrowHkt<'a>>::T: ToOwned<Owned = O>,
{
type BorrowHkt = B;
type Owned = O;
}
pub type CowableBorrowed<'a, T> = Borrowed<'a, <T as Cowable>::BorrowHkt>;
pub type CowableOwned<T> = <T as Cowable>::Owned;
macro_rules! simple_type {
($ty:ty) => {
impl<'a> Borrow<'a, $ty> for $ty {
fn borrow<'b>(&'a self) -> Borrowed<'b, $ty>
where
'a: 'b,
{
*self
}
}
impl BorrowHkt<'_> for $ty {
type T = $ty;
}
impl ToOwned for $ty {
type Owned = $ty;
fn to_owned(&self) -> Self::Owned {
*self
}
}
};
}
simple_type!(());
simple_type!(bool);
simple_type!(char);
simple_type!(i8);
simple_type!(i16);
simple_type!(i32);
simple_type!(i64);
simple_type!(i128);
simple_type!(isize);
simple_type!(u8);
simple_type!(u16);
simple_type!(u32);
simple_type!(u64);
simple_type!(u128);
simple_type!(usize);
simple_type!(f32);
simple_type!(f64);