//! Type-level bits. //! //! These are rather simple and are used as the building blocks of the //! other number types in this crate. //! //! //! **Type operators** implemented: //! //! - From `core::ops`: `BitAnd`, `BitOr`, `BitXor`, and `Not`. //! - From `typenum`: `Same` and `Cmp`. use crate::{private::InternalMarker, Cmp, Equal, Greater, Less, NonZero, PowerOfTwo, Zero}; use core::ops::{BitAnd, BitOr, BitXor, Not}; pub use crate::marker_traits::Bit; /// The type-level bit 0. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct B0; impl B0 { /// Instantiates a singleton representing this bit. #[inline] pub fn new() -> B0 { B0 } } /// The type-level bit 1. #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Hash, Debug, Default)] #[cfg_attr(feature = "scale_info", derive(scale_info::TypeInfo))] pub struct B1; impl B1 { /// Instantiates a singleton representing this bit. #[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 {} /// Not of 0 (!0 = 1) impl Not for B0 { type Output = B1; #[inline] fn not(self) -> Self::Output { B1 } } /// Not of 1 (!1 = 0) impl Not for B1 { type Output = B0; #[inline] fn not(self) -> Self::Output { B0 } } /// And with 0 ( 0 & B = 0) impl BitAnd for B0 { type Output = B0; #[inline] fn bitand(self, _: Rhs) -> Self::Output { B0 } } /// And with 1 ( 1 & 0 = 0) impl BitAnd for B1 { type Output = B0; #[inline] fn bitand(self, _: B0) -> Self::Output { B0 } } /// And with 1 ( 1 & 1 = 1) impl BitAnd for B1 { type Output = B1; #[inline] fn bitand(self, _: B1) -> Self::Output { B1 } } /// Or with 0 ( 0 | 0 = 0) impl BitOr for B0 { type Output = B0; #[inline] fn bitor(self, _: B0) -> Self::Output { B0 } } /// Or with 0 ( 0 | 1 = 1) impl BitOr for B0 { type Output = B1; #[inline] fn bitor(self, _: B1) -> Self::Output { B1 } } /// Or with 1 ( 1 | B = 1) impl BitOr for B1 { type Output = B1; #[inline] fn bitor(self, _: Rhs) -> Self::Output { B1 } } /// Xor between 0 and 0 ( 0 ^ 0 = 0) impl BitXor for B0 { type Output = B0; #[inline] fn bitxor(self, _: B0) -> Self::Output { B0 } } /// Xor between 1 and 0 ( 1 ^ 0 = 1) impl BitXor for B1 { type Output = B1; #[inline] fn bitxor(self, _: B0) -> Self::Output { B1 } } /// Xor between 0 and 1 ( 0 ^ 1 = 1) impl BitXor for B0 { type Output = B1; #[inline] fn bitxor(self, _: B1) -> Self::Output { B1 } } /// Xor between 1 and 1 ( 1 ^ 1 = 0) impl BitXor for B1 { type Output = B0; #[inline] fn bitxor(self, _: B1) -> Self::Output { B0 } } #[cfg(tests)] mod tests { // macro for testing operation results. Uses `Same` to ensure the types are equal and // not just the values they evaluate to. 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(), ::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(), ::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 for B0 { type Output = Equal; #[inline] fn compare(&self, _: &B0) -> Self::Output { Equal } } impl Cmp for B0 { type Output = Less; #[inline] fn compare(&self, _: &B1) -> Self::Output { Less } } impl Cmp for B1 { type Output = Greater; #[inline] fn compare(&self, _: &B0) -> Self::Output { Greater } } impl Cmp for B1 { type Output = Equal; #[inline] fn compare(&self, _: &B1) -> Self::Output { Equal } } use crate::Min; impl Min for B0 { type Output = B0; #[inline] fn min(self, _: B0) -> B0 { self } } impl Min for B0 { type Output = B0; #[inline] fn min(self, _: B1) -> B0 { self } } impl Min for B1 { type Output = B0; #[inline] fn min(self, rhs: B0) -> B0 { rhs } } impl Min for B1 { type Output = B1; #[inline] fn min(self, _: B1) -> B1 { self } } use crate::Max; impl Max for B0 { type Output = B0; #[inline] fn max(self, _: B0) -> B0 { self } } impl Max for B0 { type Output = B1; #[inline] fn max(self, rhs: B1) -> B1 { rhs } } impl Max for B1 { type Output = B1; #[inline] fn max(self, _: B0) -> B1 { self } } impl Max 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 = ::new(); let _: B1 = ::new(); } } }