use std::borrow::{Borrow, Cow};
use std::ops::Deref;
use crate::Butcher;
pub trait ButcheringMethod<'cow, T>
where
T: 'cow,
{
type Output: 'cow;
fn from_owned(i: T) -> Self::Output;
fn from_borrowed(i: &'cow T) -> Self::Output;
fn unbutcher(i: Self::Output) -> T;
}
pub struct Regular;
impl<'cow, T> ButcheringMethod<'cow, T> for Regular
where
T: Clone + 'cow,
{
type Output = Cow<'cow, T>;
fn from_owned(i: T) -> Self::Output {
Cow::Owned(i)
}
fn from_borrowed(i: &'cow T) -> Self::Output {
Cow::Borrowed(i)
}
fn unbutcher(i: Self::Output) -> T {
match i {
Cow::Borrowed(b) => b.clone(),
Cow::Owned(o) => o,
}
}
}
pub struct AsDeref;
impl<'cow, T> ButcheringMethod<'cow, T> for AsDeref
where
T: Deref + Borrow<<T as Deref>::Target> + 'cow,
<T as Deref>::Target: ToOwned + 'cow,
T: Into<<<T as Deref>::Target as ToOwned>::Owned>,
T: From<<<T as Deref>::Target as ToOwned>::Owned>,
{
type Output = Cow<'cow, <T as Deref>::Target>;
fn from_owned(i: T) -> Self::Output {
Cow::Owned(i.into())
}
fn from_borrowed(i: &'cow T) -> Self::Output {
Cow::Borrowed(i)
}
fn unbutcher(i: Self::Output) -> T {
match i {
Cow::Owned(o) => T::from(o),
Cow::Borrowed(b) => b.to_owned().into(),
}
}
}
pub struct Unbox;
impl<'cow, T> ButcheringMethod<'cow, Box<T>> for Unbox
where
T: Clone + 'cow,
{
type Output = Cow<'cow, T>;
fn from_owned(i: Box<T>) -> Self::Output {
Cow::Owned(*i)
}
fn from_borrowed(i: &'cow Box<T>) -> Self::Output {
Cow::Borrowed(Deref::deref(i))
}
fn unbutcher(i: Self::Output) -> Box<T> {
match i {
Cow::Owned(o) => Box::new(o),
Cow::Borrowed(b) => Box::new(b.clone()),
}
}
}
pub struct Copy;
impl<'cow, T> ButcheringMethod<'cow, T> for Copy
where
T: Clone + 'cow,
{
type Output = T;
fn from_owned(i: T) -> Self::Output {
i
}
fn from_borrowed(i: &'cow T) -> Self::Output {
i.clone()
}
fn unbutcher(i: Self::Output) -> T {
i
}
}
pub struct Rebutcher;
impl<'cow, T> ButcheringMethod<'cow, T> for Rebutcher
where
T: Butcher<'cow> + Clone + ToOwned<Owned = T> + 'cow,
{
type Output = <T as Butcher<'cow>>::Output;
fn from_owned(i: T) -> Self::Output {
<T as Butcher>::butcher(Cow::Owned(i))
}
fn from_borrowed(i: &'cow T) -> Self::Output {
<T as Butcher>::butcher(Cow::Borrowed(i))
}
fn unbutcher(i: Self::Output) -> T {
Butcher::unbutcher(i)
}
}
pub trait ButcherField<'cow, T>
where
T: 'cow + Clone,
{
type Method: ButcheringMethod<'cow, T>;
fn from_owned(i: T) -> <Self::Method as ButcheringMethod<'cow, T>>::Output {
<Self::Method as ButcheringMethod<'cow, T>>::from_owned(i)
}
fn from_borrowed(i: &'cow T) -> <Self::Method as ButcheringMethod<'cow, T>>::Output {
<Self::Method as ButcheringMethod<'cow, T>>::from_borrowed(i)
}
fn unbutcher(i: <Self::Method as ButcheringMethod<'cow, T>>::Output) -> T {
<Self::Method as ButcheringMethod<'cow, T>>::unbutcher(i)
}
}