as-is 0.0.27

An abstraction over ownership
Documentation
use crate::{AsIs, BorrowAsIs, Is, IsCow, Owned, ToOwned, ToOwnedMut};
use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
use core::ops::{
    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Deref,
    DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
    ShrAssign, Sub, SubAssign,
};
use ref_ops::{
    RefAdd, RefBitAnd, RefBitOr, RefBitXor, RefDiv, RefMul, RefMutAdd, RefMutBitAnd, RefMutBitOr,
    RefMutBitXor, RefMutDiv, RefMutMul, RefMutNeg, RefMutNot, RefMutRem, RefMutShl, RefMutShr,
    RefMutSub, RefNeg, RefNot, RefRem, RefShl, RefShr, RefSub,
};

/// Represents an owned or a mutably borrowed data.
#[derive(Debug)]
pub enum IsMut<'a, T>
where
    T: ?Sized + ToOwned,
{
    /// Owned data.
    Owned(T::Owned),
    /// Mutably borrowed data.
    MutBorrowed(&'a mut T),
}

impl<T> Default for IsMut<'_, T>
where
    T: ?Sized + ToOwned,
    T::Owned: Default,
{
    /// Creates an owned [`IsMut<'_, T>`] with the default value for `T::Owned`.
    ///
    /// [`IsMut<'_, T>`]: enum.IsMut.html
    fn default() -> Self {
        IsMut::Owned(T::Owned::default())
    }
}

impl<T> Deref for IsMut<'_, T>
where
    T: ?Sized + ToOwned,
{
    type Target = T;

    fn deref(&self) -> &T {
        match self {
            IsMut::Owned(x) => x.borrow(),
            IsMut::MutBorrowed(x) => x,
        }
    }
}

impl<T> DerefMut for IsMut<'_, T>
where
    T: ?Sized + ToOwnedMut,
{
    fn deref_mut(&mut self) -> &mut T {
        match self {
            IsMut::Owned(x) => x.borrow_mut(),
            IsMut::MutBorrowed(x) => x,
        }
    }
}

impl<T> Borrow<T> for IsMut<'_, T>
where
    T: ?Sized + ToOwned,
{
    fn borrow(&self) -> &T {
        self
    }
}

impl<T> Borrow<T> for &IsMut<'_, T>
where
    T: ?Sized + ToOwned,
{
    fn borrow(&self) -> &T {
        self
    }
}

impl<T> Borrow<T> for &mut IsMut<'_, T>
where
    T: ?Sized + ToOwned,
{
    fn borrow(&self) -> &T {
        self
    }
}

impl<T> BorrowMut<T> for IsMut<'_, T>
where
    T: ?Sized + ToOwnedMut,
{
    fn borrow_mut(&mut self) -> &mut T {
        self
    }
}

impl<T> BorrowMut<T> for &mut IsMut<'_, T>
where
    T: ?Sized + ToOwnedMut,
{
    fn borrow_mut(&mut self) -> &mut T {
        self
    }
}

impl<T, U> PartialEq<Is<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialEq<U>,
    U: ?Sized + ToOwned,
{
    fn eq(&self, other: &Is<'_, U>) -> bool {
        **self == **other
    }
}

impl<T, U> PartialEq<IsCow<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialEq<U>,
    U: ?Sized + ToOwned,
{
    fn eq(&self, other: &IsCow<'_, U>) -> bool {
        **self == **other
    }
}

impl<T, U> PartialEq<IsMut<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialEq<U>,
    U: ?Sized + ToOwned,
{
    fn eq(&self, other: &IsMut<'_, U>) -> bool {
        **self == **other
    }
}

impl<T> Eq for IsMut<'_, T> where T: ?Sized + ToOwned + Eq {}

impl<T, U> PartialOrd<Is<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialOrd<U>,
    U: ?Sized + ToOwned,
{
    fn partial_cmp(&self, other: &Is<'_, U>) -> Option<Ordering> {
        (**self).partial_cmp(&**other)
    }
}

impl<T, U> PartialOrd<IsCow<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialOrd<U>,
    U: ?Sized + ToOwned,
{
    fn partial_cmp(&self, other: &IsCow<'_, U>) -> Option<Ordering> {
        (**self).partial_cmp(&**other)
    }
}

impl<T, U> PartialOrd<IsMut<'_, U>> for IsMut<'_, T>
where
    T: ?Sized + ToOwned + PartialOrd<U>,
    U: ?Sized + ToOwned,
{
    fn partial_cmp(&self, other: &IsMut<'_, U>) -> Option<Ordering> {
        (**self).partial_cmp(&**other)
    }
}

impl<T> Ord for IsMut<'_, T>
where
    T: ?Sized + ToOwned + Ord,
{
    fn cmp(&self, other: &Self) -> Ordering {
        (**self).cmp(&**other)
    }
}

impl<T> Hash for IsMut<'_, T>
where
    T: ?Sized + ToOwned + Hash,
{
    fn hash<H: Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl<T> BorrowAsIs for IsMut<'_, T>
where
    T: ?Sized + BorrowAsIs<Is = T> + ToOwned,
{
    type Is = T;

    fn borrow_or_clone<B: ?Sized>(&self) -> IsCow<'_, B>
    where
        T: Borrow<B>,
        B: ToOwned<Owned = T::Owned>,
    {
        (**self).borrow_or_clone()
    }
}

impl<T> AsIs for IsMut<'_, T>
where
    T: ?Sized + BorrowAsIs<Is = T> + ToOwned,
{
    fn as_is<'a>(self) -> Is<'a, T>
    where
        Self: 'a,
    {
        match self {
            IsMut::Owned(x) => Is::Owned(x),
            IsMut::MutBorrowed(x) => match x.borrow_or_clone() {
                IsCow::Owned(x) => Is::Owned(x),
                IsCow::Borrowed(_) => Is::MutBorrowed(x),
            },
        }
    }
}

macro_rules! impl_unop {
    ($Op:ident, $op:ident, $RefOp:ident, $ref_op:ident, $RefMutOp:ident, $ref_mut_op:ident) => {
        impl<T> $Op for IsMut<'_, T>
        where
            T: ?Sized + ToOwned + $RefMutOp,
            T::Owned: $Op<Output = T::Output>,
        {
            type Output = T::Output;

            fn $op(self) -> Self::Output {
                match self {
                    IsMut::Owned(x) => x.$op(),
                    IsMut::MutBorrowed(x) => x.$ref_mut_op(),
                }
            }
        }

        impl<T> $Op for &IsMut<'_, T>
        where
            T: ?Sized + ToOwned + $RefOp,
        {
            type Output = T::Output;

            fn $op(self) -> Self::Output {
                (**self).$ref_op()
            }
        }

        impl<T> $Op for &mut IsMut<'_, T>
        where
            T: ?Sized + ToOwnedMut + $RefMutOp,
        {
            type Output = T::Output;

            fn $op(self) -> Self::Output {
                match self {
                    IsMut::Owned(x) => x.borrow_mut().$ref_mut_op(),
                    IsMut::MutBorrowed(x) => x.$ref_mut_op(),
                }
            }
        }
    };
}

impl_unop!(Neg, neg, RefNeg, ref_neg, RefMutNeg, ref_mut_neg);
impl_unop!(Not, not, RefNot, ref_not, RefMutNot, ref_mut_not);

macro_rules! impl_binop {
    ($Op:ident, $op:ident, $RefOp:ident, $ref_op:ident, $RefMutOp:ident, $ref_mut_op:ident) => {
        impl<T, U, O> $Op<U> for IsMut<'_, T>
        where
            T: ?Sized
                + ToOwned
                + $RefMutOp<Owned<U>, Output = O>
                + for<'a> $RefMutOp<&'a U::Is, Output = O>
                + for<'a> $RefMutOp<&'a mut U::Is, Output = O>,
            U: AsIs,
            T::Owned: $Op<Owned<U>, Output = O>
                + for<'a> $Op<&'a U::Is, Output = O>
                + for<'a> $Op<&'a mut U::Is, Output = O>,
        {
            type Output = O;

            fn $op(self, rhs: U) -> Self::Output {
                match self {
                    IsMut::Owned(x) => match rhs.as_is() {
                        Is::Owned(y) => x.$op(y),
                        Is::Borrowed(y) => x.$op(y),
                        Is::MutBorrowed(y) => x.$op(y),
                    },
                    IsMut::MutBorrowed(x) => match rhs.as_is() {
                        Is::Owned(y) => x.$ref_mut_op(y),
                        Is::Borrowed(y) => x.$ref_mut_op(y),
                        Is::MutBorrowed(y) => x.$ref_mut_op(y),
                    },
                }
            }
        }

        impl<T, U, O> $Op<U> for &IsMut<'_, T>
        where
            T: ?Sized
                + ToOwned
                + $RefOp<Owned<U>, Output = O>
                + for<'a> $RefOp<&'a U::Is, Output = O>
                + for<'a> $RefOp<&'a mut U::Is, Output = O>,
            U: AsIs,
        {
            type Output = O;

            fn $op(self, rhs: U) -> Self::Output {
                match rhs.as_is() {
                    Is::Owned(y) => (**self).$ref_op(y),
                    Is::Borrowed(y) => (**self).$ref_op(y),
                    Is::MutBorrowed(y) => (**self).$ref_op(y),
                }
            }
        }

        impl<T, U, O> $Op<U> for &mut IsMut<'_, T>
        where
            T: ?Sized
                + ToOwnedMut
                + $RefMutOp<Owned<U>, Output = O>
                + for<'a> $RefMutOp<&'a U::Is, Output = O>
                + for<'a> $RefMutOp<&'a mut U::Is, Output = O>,
            U: AsIs,
        {
            type Output = O;

            fn $op(self, rhs: U) -> Self::Output {
                match self {
                    IsMut::Owned(x) => match rhs.as_is() {
                        Is::Owned(y) => x.borrow_mut().$ref_mut_op(y),
                        Is::Borrowed(y) => x.borrow_mut().$ref_mut_op(y),
                        Is::MutBorrowed(y) => x.borrow_mut().$ref_mut_op(y),
                    },
                    IsMut::MutBorrowed(x) => match rhs.as_is() {
                        Is::Owned(y) => x.$ref_mut_op(y),
                        Is::Borrowed(y) => x.$ref_mut_op(y),
                        Is::MutBorrowed(y) => x.$ref_mut_op(y),
                    },
                }
            }
        }
    };
}

impl_binop!(Add, add, RefAdd, ref_add, RefMutAdd, ref_mut_add);
impl_binop!(Sub, sub, RefSub, ref_sub, RefMutSub, ref_mut_sub);
impl_binop!(Mul, mul, RefMul, ref_mul, RefMutMul, ref_mut_mul);
impl_binop!(Div, div, RefDiv, ref_div, RefMutDiv, ref_mut_div);
impl_binop!(Rem, rem, RefRem, ref_rem, RefMutRem, ref_mut_rem);
impl_binop!(Shl, shl, RefShl, ref_shl, RefMutShl, ref_mut_shl);
impl_binop!(Shr, shr, RefShr, ref_shr, RefMutShr, ref_mut_shr);
impl_binop!(
    BitAnd,
    bitand,
    RefBitAnd,
    ref_bitand,
    RefMutBitAnd,
    ref_mut_bitand
);
impl_binop!(
    BitOr,
    bitor,
    RefBitOr,
    ref_bitor,
    RefMutBitOr,
    ref_mut_bitor
);
impl_binop!(
    BitXor,
    bitxor,
    RefBitXor,
    ref_bitxor,
    RefMutBitXor,
    ref_mut_bitxor
);

macro_rules! impl_binop_assign {
    ($OpAssign:ident, $op_assign:ident) => {
        impl<T, U> $OpAssign<U> for IsMut<'_, T>
        where
            T: ?Sized
                + ToOwned
                + $OpAssign<Owned<U>>
                + for<'a> $OpAssign<&'a U::Is>
                + for<'a> $OpAssign<&'a mut U::Is>,
            U: AsIs,
            T::Owned: $OpAssign<Owned<U>>
                + for<'a> $OpAssign<&'a U::Is>
                + for<'a> $OpAssign<&'a mut U::Is>,
        {
            fn $op_assign(&mut self, rhs: U) {
                match self {
                    IsMut::Owned(x) => match rhs.as_is() {
                        Is::Owned(y) => x.$op_assign(y),
                        Is::Borrowed(y) => x.$op_assign(y),
                        Is::MutBorrowed(y) => x.$op_assign(y),
                    },
                    IsMut::MutBorrowed(x) => match rhs.as_is() {
                        Is::Owned(y) => x.$op_assign(y),
                        Is::Borrowed(y) => x.$op_assign(y),
                        Is::MutBorrowed(y) => x.$op_assign(y),
                    },
                }
            }
        }
    };
}

impl_binop_assign!(AddAssign, add_assign);
impl_binop_assign!(SubAssign, sub_assign);
impl_binop_assign!(MulAssign, mul_assign);
impl_binop_assign!(DivAssign, div_assign);
impl_binop_assign!(RemAssign, rem_assign);
impl_binop_assign!(ShlAssign, shl_assign);
impl_binop_assign!(ShrAssign, shr_assign);
impl_binop_assign!(BitAndAssign, bitand_assign);
impl_binop_assign!(BitOrAssign, bitor_assign);
impl_binop_assign!(BitXorAssign, bitxor_assign);