option_trait 1.0.7

Helper traits for more generalized options
use crate::{Maybe, NotVoid, PureMaybe};

pub trait MaybeXor<T, Rhs>: PureMaybe<T>
where
    T: ?Sized,
    Rhs: PureMaybe<T> + ?Sized
{
    type Output: PureMaybe<T> + ?Sized;

    fn xor(self, other: Rhs) -> Self::Output
    where
        Self::Output: Sized,
        Self: Sized,
        Rhs: Sized;
}

impl<Lhs, Rhs, T> MaybeXor<T, Rhs> for Lhs
where
    T: ?Sized,
    Lhs: PureMaybe<T> + ?Sized,
    Rhs: PureMaybe<T> + ?Sized
{
    default type Output = T;

    default fn xor(self, _: Rhs) -> Self::Output
    where
        Self::Output: Sized,
        Self: Sized,
        Rhs: Sized
    {
        unreachable!()
    }
}

impl<T> MaybeXor<T, Option<T>> for Option<T>
{
    type Output = Option<T>;

    fn xor(self, other: Option<T>) -> Self::Output
    {
        self.xor(other)
    }
}
impl<T> MaybeXor<T, ()> for Option<T>
where
    T: NotVoid
{
    type Output = Option<T>;

    fn xor(self, (): ()) -> Self::Output
    {
        self
    }
}
impl<T> MaybeXor<T, T> for Option<T>
{
    type Output = Option<T>;

    fn xor(self, other: T) -> Self::Output
    {
        self.xor(other.option())
    }
}

impl<Rhs, T> MaybeXor<T, Rhs> for ()
where
    Rhs: PureMaybe<T> + ?Sized,
    T: NotVoid + ?Sized
{
    type Output = Rhs;

    fn xor(self, other: Rhs) -> Self::Output
    where
        Self::Output: Sized,
        Self: Sized
    {
        other
    }
}

impl<T> MaybeXor<T, Option<T>> for T
{
    type Output = Option<T>;

    fn xor(self, other: Option<T>) -> Self::Output
    {
        self.option().xor(other)
    }
}
impl<T> MaybeXor<T, ()> for T
where
    T: NotVoid + ?Sized
{
    type Output = T;

    fn xor(self, (): ()) -> Self::Output
    where
        Self: Sized
    {
        self
    }
}
impl<T> MaybeXor<T, T> for T
where
    T: ?Sized,
    (): PureMaybe<T>
{
    type Output = ();

    fn xor(self, _: T) -> Self::Output
    where
        Self: Sized
    {
        
    }
}