//! Constant-time equality comparison for [`U320`].
use super::U320;

impl U320 {
    /// Returns `true` if `self` and `other` are equal, using a
    /// constant-time comparison pattern.
    ///
    /// XORs all five limb pairs and ORs the results together, producing
    /// zero only when all limbs match. This avoids early-exit branching
    /// that could leak information through timing side channels.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u320::U320;
    ///
    /// let a = U320::from_be_limbs([1, 2, 3, 4, 5]);
    /// let b = U320::from_be_limbs([1, 2, 3, 4, 5]);
    /// assert!(a.const_eq(&b));
    /// ```
    #[inline]
    pub const fn const_eq(&self, other: &U320) -> bool {
        let x = (self.0[0] ^ other.0[0])
            | (self.0[1] ^ other.0[1])
            | (self.0[2] ^ other.0[2])
            | (self.0[3] ^ other.0[3])
            | (self.0[4] ^ other.0[4]);
        x == 0
    }
}

#[cfg(test)]
mod ai_tests {
    use super::*;

    /// Equal values compare as equal.
    #[test]
    fn equal_values() {
        let a = U320::from_be_limbs([1, 2, 3, 4, 5]);
        assert!(a.const_eq(&a));
    }

    /// Different values compare as unequal.
    #[test]
    fn different_values() {
        let a = U320::from_be_limbs([1, 2, 3, 4, 5]);
        let b = U320::from_be_limbs([1, 2, 3, 4, 6]);
        assert!(!a.const_eq(&b));
    }

    /// Zero equals zero.
    #[test]
    fn zero_eq_zero() {
        assert!(U320::ZERO.const_eq(&U320::ZERO));
    }

    /// MAX equals MAX.
    #[test]
    fn max_eq_max() {
        assert!(U320::MAX.const_eq(&U320::MAX));
    }

    /// Difference in only the MSB limb is detected.
    #[test]
    fn msb_difference() {
        let a = U320::from_be_limbs([1, 0, 0, 0, 0]);
        let b = U320::from_be_limbs([2, 0, 0, 0, 0]);
        assert!(!a.const_eq(&b));
    }

    /// Consistent with PartialEq.
    #[test]
    fn consistent_with_eq() {
        let a = U320::from_be_limbs([0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);
        let b = U320::from_be_limbs([0xAA, 0xBB, 0xCC, 0xDD, 0xEE]);
        assert_eq!(a.const_eq(&b), a == b);
    }
}
