//! Extraction of the lower 256 bits from a `U320` as a `U256`.
use super::U320;
use crate::u256::U256;

impl U320 {
    /// Extracts the lower 256 bits as a [`U256`], discarding the most
    /// significant limb.
    ///
    /// Since the internal layout is little-endian `[w0, w1, w2, w3, w4]`,
    /// this returns `U256` from limbs `[w0, w1, w2, w3]`, dropping `w4`
    /// (the MSB). The operation is zero-cost — it simply copies the four
    /// least significant limbs.
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    /// use cnfy_uint::u320::U320;
    ///
    /// let wide = U320::from_be_limbs([0xFF, 0xAA, 0xBB, 0xCC, 0xDD]);
    /// assert_eq!(wide.low_u256(), U256::from_be_limbs([0xAA, 0xBB, 0xCC, 0xDD]));
    /// ```
    #[inline]
    pub const fn low_u256(&self) -> U256 {
        U256([self.0[0], self.0[1], self.0[2], self.0[3]])
    }
}

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

    /// Lower 256 bits of a value with zero high limb.
    #[test]
    fn zero_high_limb() {
        let v = U320::from_be_limbs([0, 1, 2, 3, 4]);
        assert_eq!(v.low_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    }

    /// High limb is discarded.
    #[test]
    fn discards_high_limb() {
        let v = U320::from_be_limbs([0xDEAD, 1, 2, 3, 4]);
        assert_eq!(v.low_u256(), U256::from_be_limbs([1, 2, 3, 4]));
    }

    /// All-zero U320 produces U256::ZERO.
    #[test]
    fn zero_produces_zero() {
        assert_eq!(U320::from_be_limbs([0; 5]).low_u256(), U256::ZERO);
    }

    /// All-MAX U320 produces U256::MAX.
    #[test]
    fn max_lower_bits() {
        let v = U320::from_be_limbs([u64::MAX; 5]);
        assert_eq!(v.low_u256(), U256::MAX);
    }
}
