option_trait 1.0.7

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

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

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        T: Sized,
        F: FnOnce(T) -> Rhs,
        Self::Output: Sized,
        Self: Sized,
        Rhs: Sized;
}

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

    default fn and_then<F>(self, _: F) -> Self::Output
    where
        T: Sized,
        F: FnOnce(T) -> Rhs,
        Self::Output: Sized,
        Self: Sized,
        Rhs: Sized
    {
        unreachable!()
    }
}

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

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        T: Sized,
        F: FnOnce(T) -> Option<U>
    {
        self.and_then(and_then)
    }
}
impl<T, U> MaybeAndThen<T, U, ()> for Option<T>
where
    U: NotVoid
{
    type Output = ();

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        F: FnOnce(T)
    {
        if let Some(x) = self
        {
            and_then(x)
        }
    }
}
impl<T, U> MaybeAndThen<T, U, U> for Option<T>
{
    type Output = Option<U>;
    
    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        F: FnOnce(T) -> U
    {
        self.map(and_then)
    }
}

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

    fn and_then<F>(self, _: F) -> Self::Output
    {
        
    }
}
impl<Rhs, T> MaybeAndThen<T, (), Rhs> for ()
where
    T: ?Sized + NotVoid,
    Rhs: PureMaybe<()>
{
    type Output = ();

    fn and_then<F>(self, _: F) -> Self::Output
    {
        
    }
}

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

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        F: FnOnce(T) -> Option<U>
    {
        and_then(self)
    }
}
impl<T, U> MaybeAndThen<T, U, ()> for T
where
    T: ?Sized,
    U: NotVoid + ?Sized,
{
    type Output = ();

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        T: Sized,
        F: FnOnce(T)
    {
        and_then(self)
    }
}
impl<T, U> MaybeAndThen<T, U, U> for T
where
    U: ?Sized,
    T: ?Sized
{
    type Output = U;

    fn and_then<F>(self, and_then: F) -> Self::Output
    where
        T: Sized,
        F: FnOnce(T) -> U,
        Self::Output: Sized,
        Self: Sized
    {
        and_then(self)
    }
}