1 //! Compare numeric types by exact bit value.
4 fn biteq(&self, other: &Self) -> bool;
5 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result;
9 fn biteq(&self, other: &Self) -> bool {
13 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
14 write!(f, "{:?}", self)
18 macro_rules! impl_integer_biteq {
19 { $($type:ty),* } => {
21 impl BitEq for $type {
22 fn biteq(&self, other: &Self) -> bool {
26 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
27 write!(f, "{:?} ({:x})", self, self)
34 impl_integer_biteq! { u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize }
36 macro_rules! impl_float_biteq {
37 { $($type:ty),* } => {
39 impl BitEq for $type {
40 fn biteq(&self, other: &Self) -> bool {
41 if self.is_nan() && other.is_nan() {
42 true // exact nan bits don't matter
44 self.to_bits() == other.to_bits()
48 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
49 write!(f, "{:?} ({:x})", self, self.to_bits())
56 impl_float_biteq! { f32, f64 }
58 impl<T: BitEq, const N: usize> BitEq for [T; N] {
59 fn biteq(&self, other: &Self) -> bool {
62 .fold(true, |value, (left, right)| value && left.biteq(right))
65 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
67 struct Wrapper<'a, T: BitEq>(&'a T);
69 impl<T: BitEq> core::fmt::Debug for Wrapper<'_, T> {
70 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76 .entries(self.iter().map(|x| Wrapper(x)))
82 pub struct BitEqWrapper<'a, T>(pub &'a T);
84 impl<T: BitEq> PartialEq for BitEqWrapper<'_, T> {
85 fn eq(&self, other: &Self) -> bool {
90 impl<T: BitEq> core::fmt::Debug for BitEqWrapper<'_, T> {
91 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
97 macro_rules! prop_assert_biteq {
98 { $a:expr, $b:expr $(,)? } => {
100 use $crate::biteq::BitEqWrapper;
103 proptest::prop_assert_eq!(BitEqWrapper(&a), BitEqWrapper(&b));