//! Single-bit extraction from a [`U256`] value.
use super::U256;

impl U256 {
    /// Returns `true` if the bit at position `pos` (0 = LSB) is set.
    ///
    /// Indexes into the appropriate limb and shifts to isolate the target bit.
    /// Positions beyond 255 read from limb index ≥ 4, which will panic in
    /// debug builds.
    #[inline]
    pub(crate) const fn bit(&self, pos: u32) -> bool {
        let limb_idx = (pos / 64) as usize;
        let bit_idx = pos % 64;
        (self.0[limb_idx] >> bit_idx) & 1 == 1
    }
}

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

    /// LSB of 0b1010 is not set.
    #[test]
    fn lsb_not_set() {
        let v = U256::from_be_limbs([0, 0, 0, 0b1010]);
        assert!(!v.bit(0));
    }

    /// Bit 1 of 0b1010 is set.
    #[test]
    fn bit_1_set() {
        let v = U256::from_be_limbs([0, 0, 0, 0b1010]);
        assert!(v.bit(1));
    }

    /// Bit 3 of 0b1010 is set.
    #[test]
    fn bit_3_set() {
        let v = U256::from_be_limbs([0, 0, 0, 0b1010]);
        assert!(v.bit(3));
    }

    /// Bit 2 of 0b1010 is not set.
    #[test]
    fn bit_2_not_set() {
        let v = U256::from_be_limbs([0, 0, 0, 0b1010]);
        assert!(!v.bit(2));
    }

    /// Bit 192 (first bit of limb 3 in LE order) crosses limb boundary.
    #[test]
    fn bit_cross_limb() {
        let v = U256::from_be_limbs([1, 0, 0, 0]);
        assert!(v.bit(192));
        assert!(!v.bit(191));
        assert!(!v.bit(193));
    }

    /// Bit 255 (MSB) is set for a value with MSB set.
    #[test]
    fn msb() {
        let v = U256::from_be_limbs([0x8000000000000000, 0, 0, 0]);
        assert!(v.bit(255));
        assert!(!v.bit(254));
    }

    /// All bits of zero are unset.
    #[test]
    fn zero_all_bits_clear() {
        for i in 0..256 {
            assert!(!U256::ZERO.bit(i));
        }
    }
}
