use std::borrow::{Cow, ToOwned};
use std::convert::Infallible;
use std::fmt::Debug;
pub trait Carrier<'a, T: ToOwned + ?Sized>: Sized {
type Residual;
const NONE: Option<Self>;
fn from_inner(inner: Cow<'a, T>) -> Self;
fn from_residual(residual: Self::Residual) -> Self;
fn into_inner(self) -> Result<Cow<'a, T>, Self::Residual>;
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, Self::Residual>;
}
macro_rules! carrier_into_inner_opt {
($expr:expr) => {
match $expr.into_inner_opt() {
Ok(inner) => inner,
Err(residual) => return Carrier::from_residual(residual),
}
};
}
pub(crate) use carrier_into_inner_opt;
macro_rules! carrier_try_none {
() => {
if let Some(none) = Carrier::NONE {
return none;
}
};
}
pub(crate) use carrier_try_none;
impl<'a, T: ToOwned + ?Sized> Carrier<'a, T> for Cow<'a, T> {
type Residual = Infallible;
const NONE: Option<Self> = None;
fn from_inner(inner: Cow<'a, T>) -> Self {
inner
}
fn from_residual(residual: Infallible) -> Self {
match residual {}
}
fn into_inner(self) -> Result<Cow<'a, T>, Infallible> {
Ok(self)
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, Infallible> {
Ok(Some(self))
}
}
impl<'a, T: ToOwned + ?Sized> Carrier<'a, T> for Option<Cow<'a, T>> {
type Residual = ();
const NONE: Option<Self> = Some(None);
fn from_inner(inner: Cow<'a, T>) -> Self {
Some(inner)
}
fn from_residual(_residual: ()) -> Self {
None
}
fn into_inner(self) -> Result<Cow<'a, T>, ()> {
self.ok_or(())
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, ()> {
Ok(self)
}
}
impl<'a, T: ToOwned + ?Sized> Carrier<'a, T> for () {
type Residual = ();
const NONE: Option<Self> = Some(());
fn from_inner(_inner: Cow<'a, T>) -> Self {}
fn from_residual(_residual: ()) -> Self {}
fn into_inner(self) -> Result<Cow<'a, T>, ()> {
Err(())
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, ()> {
Ok(None)
}
}
impl<'a, T: ToOwned + ?Sized, E: Debug> Carrier<'a, T> for Result<Cow<'a, T>, E> {
type Residual = E;
const NONE: Option<Self> = None;
fn from_inner(inner: Cow<'a, T>) -> Self {
Ok(inner)
}
fn from_residual(residual: E) -> Self {
Err(residual)
}
fn into_inner(self) -> Result<Cow<'a, T>, E> {
self
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, E> {
self.map(Some)
}
}
impl<'a, T: ToOwned + ?Sized, E: Debug> Carrier<'a, T> for Result<Option<Cow<'a, T>>, E> {
type Residual = Option<E>;
const NONE: Option<Self> = Some(Ok(None));
fn from_inner(inner: Cow<'a, T>) -> Self {
Ok(Some(inner))
}
fn from_residual(residual: Option<E>) -> Self {
residual.map_or(Ok(None), Err)
}
fn into_inner(self) -> Result<Cow<'a, T>, Option<E>> {
match self {
Ok(Some(inner)) => Ok(inner),
Ok(None) => Err(None),
Err(err) => Err(Some(err)),
}
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, Option<E>> {
self.map_err(Some)
}
}
impl<'a, T: ToOwned + ?Sized, E: Debug> Carrier<'a, T> for Result<(), E> {
type Residual = Option<E>;
const NONE: Option<Self> = Some(Ok(()));
fn from_inner(_inner: Cow<'a, T>) -> Self {
Ok(())
}
fn from_residual(residual: Option<E>) -> Self {
residual.map_or(Ok(()), Err)
}
fn into_inner(self) -> Result<Cow<'a, T>, Option<E>> {
Err(self.err())
}
fn into_inner_opt(self) -> Result<Option<Cow<'a, T>>, Option<E>> {
match self {
Ok(()) => Ok(None),
Err(err) => Err(Some(err)),
}
}
}