//! Construction of a [`U256`] from a 32-byte little-endian array.

use super::U256;

impl U256 {
    /// Creates a new [`U256`] from a 32-byte array in little-endian order.
    ///
    /// Byte `[0]` is the least significant and byte `[31]` is the most
    /// significant. This is the wire format used internally by Bitcoin
    /// (e.g. transaction hashes, block headers). Reverses the bytes and
    /// delegates to [`U256::from_be_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u256::U256;
    ///
    /// let mut le_bytes = [0u8; 32];
    /// le_bytes[0] = 1; // LSB
    /// assert_eq!(U256::from_le_bytes(le_bytes), U256::from_be_limbs([0, 0, 0, 1]));
    /// ```
    #[inline]
    pub const fn from_le_bytes(bytes: [u8; 32]) -> Self {
        Self::from_be_bytes([
            bytes[31], bytes[30], bytes[29], bytes[28],
            bytes[27], bytes[26], bytes[25], bytes[24],
            bytes[23], bytes[22], bytes[21], bytes[20],
            bytes[19], bytes[18], bytes[17], bytes[16],
            bytes[15], bytes[14], bytes[13], bytes[12],
            bytes[11], bytes[10], bytes[9], bytes[8],
            bytes[7], bytes[6], bytes[5], bytes[4],
            bytes[3], bytes[2], bytes[1], bytes[0],
        ])
    }
}

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

    /// All zeros produces the zero value.
    #[test]
    fn zero() {
        assert_eq!(U256::from_le_bytes([0; 32]), U256::ZERO);
    }

    /// All 0xFF produces the maximum value.
    #[test]
    fn max() {
        assert_eq!(U256::from_le_bytes([0xFF; 32]), U256::MAX);
    }

    /// Byte 0 (LSB in LE) maps to the lowest bit of limb w3.
    #[test]
    fn single_lsb() {
        let mut bytes = [0u8; 32];
        bytes[0] = 1;
        assert_eq!(U256::from_le_bytes(bytes), U256::from_be_limbs([0, 0, 0, 1]));
    }

    /// Byte 31 (MSB in LE) maps to the high bit of limb w0.
    #[test]
    fn single_msb() {
        let mut bytes = [0u8; 32];
        bytes[31] = 0x80;
        assert_eq!(
            U256::from_le_bytes(bytes),
            U256::from_be_limbs([0x8000000000000000, 0, 0, 0]),
        );
    }

    /// Round-trip: from_le_bytes reverses from_be_bytes.
    #[test]
    fn inverse_of_be() {
        let be_bytes: [u8; 32] = [
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
            0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
            0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
            0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
        ];
        let mut le_bytes = be_bytes;
        le_bytes.reverse();
        assert_eq!(U256::from_le_bytes(le_bytes), U256::from_be_bytes(be_bytes));
    }

    /// LE byte 7 maps to MSB of limb w3.
    #[test]
    fn limb_w3_msb() {
        let mut bytes = [0u8; 32];
        bytes[7] = 0x01;
        assert_eq!(
            U256::from_le_bytes(bytes),
            U256::from_be_limbs([0, 0, 0, 0x0100000000000000]),
        );
    }

    /// LE byte 8 maps to LSB of limb w2.
    #[test]
    fn limb_w2_lsb() {
        let mut bytes = [0u8; 32];
        bytes[8] = 0x01;
        assert_eq!(U256::from_le_bytes(bytes), U256::from_be_limbs([0, 0, 1, 0]));
    }
}
