use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero};
use core::ops::{BitAnd, BitOr, BitXor, Not};
pub use crate::marker_traits::Bit;
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
pub struct B0;
impl B0 {
    #[inline]
    pub fn new() -> B0 {
        B0
    }
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)]
#[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))]
pub struct B1;
impl B1 {
    #[inline]
    pub fn new() -> B1 {
        B1
    }
}
impl Bit for B0 {
    const U8: u8 = 0;
    const BOOL: bool = false;
    #[inline]
    fn new() -> Self {
        Self
    }
    #[inline]
    fn to_u8() -> u8 {
        0
    }
    #[inline]
    fn to_bool() -> bool {
        false
    }
}
impl Bit for B1 {
    const U8: u8 = 1;
    const BOOL: bool = true;
    #[inline]
    fn new() -> Self {
        Self
    }
    #[inline]
    fn to_u8() -> u8 {
        1
    }
    #[inline]
    fn to_bool() -> bool {
        true
    }
}
impl Zero for B0 {}
impl NonZero for B1 {}
impl PowerOfTwo for B1 {}
impl Not for B0 {
    type Output = B1;
    #[inline]
    fn not(self) -> Self::Output {
        B1
    }
}
impl Not for B1 {
    type Output = B0;
    #[inline]
    fn not(self) -> Self::Output {
        B0
    }
}
impl<Rhs: Bit> BitAnd<Rhs> for B0 {
    type Output = B0;
    #[inline]
    fn bitand(self, _: Rhs) -> Self::Output {
        B0
    }
}
impl BitAnd<B0> for B1 {
    type Output = B0;
    #[inline]
    fn bitand(self, _: B0) -> Self::Output {
        B0
    }
}
impl BitAnd<B1> for B1 {
    type Output = B1;
    #[inline]
    fn bitand(self, _: B1) -> Self::Output {
        B1
    }
}
impl BitOr<B0> for B0 {
    type Output = B0;
    #[inline]
    fn bitor(self, _: B0) -> Self::Output {
        B0
    }
}
impl BitOr<B1> for B0 {
    type Output = B1;
    #[inline]
    fn bitor(self, _: B1) -> Self::Output {
        B1
    }
}
impl<Rhs: Bit> BitOr<Rhs> for B1 {
    type Output = B1;
    #[inline]
    fn bitor(self, _: Rhs) -> Self::Output {
        B1
    }
}
impl BitXor<B0> for B0 {
    type Output = B0;
    #[inline]
    fn bitxor(self, _: B0) -> Self::Output {
        B0
    }
}
impl BitXor<B0> for B1 {
    type Output = B1;
    #[inline]
    fn bitxor(self, _: B0) -> Self::Output {
        B1
    }
}
impl BitXor<B1> for B0 {
    type Output = B1;
    #[inline]
    fn bitxor(self, _: B1) -> Self::Output {
        B1
    }
}
impl BitXor<B1> for B1 {
    type Output = B0;
    #[inline]
    fn bitxor(self, _: B1) -> Self::Output {
        B0
    }
}
#[cfg(tests)]
mod tests {
    macro_rules! test_bit_op {
        ($op:ident $Lhs:ident = $Answer:ident) => {{
            type Test = <<$Lhs as $op>::Output as ::Same<$Answer>>::Output;
            assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8());
        }};
        ($Lhs:ident $op:ident $Rhs:ident = $Answer:ident) => {{
            type Test = <<$Lhs as $op<$Rhs>>::Output as ::Same<$Answer>>::Output;
            assert_eq!(<$Answer as Bit>::to_u8(), <Test as Bit>::to_u8());
        }};
    }
    #[test]
    fn bit_operations() {
        test_bit_op!(Not B0 = B1);
        test_bit_op!(Not B1 = B0);
        test_bit_op!(B0 BitAnd B0 = B0);
        test_bit_op!(B0 BitAnd B1 = B0);
        test_bit_op!(B1 BitAnd B0 = B0);
        test_bit_op!(B1 BitAnd B1 = B1);
        test_bit_op!(B0 BitOr B0 = B0);
        test_bit_op!(B0 BitOr B1 = B1);
        test_bit_op!(B1 BitOr B0 = B1);
        test_bit_op!(B1 BitOr B1 = B1);
        test_bit_op!(B0 BitXor B0 = B0);
        test_bit_op!(B0 BitXor B1 = B1);
        test_bit_op!(B1 BitXor B0 = B1);
        test_bit_op!(B1 BitXor B1 = B0);
    }
}
impl Cmp<B0> for B0 {
    type Output = Equal;
    #[inline]
    fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
        Equal
    }
}
impl Cmp<B1> for B0 {
    type Output = Less;
    #[inline]
    fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
        Less
    }
}
impl Cmp<B0> for B1 {
    type Output = Greater;
    #[inline]
    fn compare<P: InternalMarker>(&self, _: &B0) -> Self::Output {
        Greater
    }
}
impl Cmp<B1> for B1 {
    type Output = Equal;
    #[inline]
    fn compare<P: InternalMarker>(&self, _: &B1) -> Self::Output {
        Equal
    }
}
use crate::Min;
impl Min<B0> for B0 {
    type Output = B0;
    #[inline]
    fn min(self, _: B0) -> B0 {
        self
    }
}
impl Min<B1> for B0 {
    type Output = B0;
    #[inline]
    fn min(self, _: B1) -> B0 {
        self
    }
}
impl Min<B0> for B1 {
    type Output = B0;
    #[inline]
    fn min(self, rhs: B0) -> B0 {
        rhs
    }
}
impl Min<B1> for B1 {
    type Output = B1;
    #[inline]
    fn min(self, _: B1) -> B1 {
        self
    }
}
use crate::Max;
impl Max<B0> for B0 {
    type Output = B0;
    #[inline]
    fn max(self, _: B0) -> B0 {
        self
    }
}
impl Max<B1> for B0 {
    type Output = B1;
    #[inline]
    fn max(self, rhs: B1) -> B1 {
        rhs
    }
}
impl Max<B0> for B1 {
    type Output = B1;
    #[inline]
    fn max(self, _: B0) -> B1 {
        self
    }
}
impl Max<B1> for B1 {
    type Output = B1;
    #[inline]
    fn max(self, _: B1) -> B1 {
        self
    }
}
#[cfg(test)]
mod tests {
    #[test]
    fn bit_creation() {
        {
            use crate::{B0, B1};
            let _: B0 = B0::new();
            let _: B1 = B1::new();
        }
        {
            use crate::{Bit, B0, B1};
            let _: B0 = <B0 as Bit>::new();
            let _: B1 = <B1 as Bit>::new();
        }
    }
}