//! Construction of a [`U512`] from a 64-byte little-endian array.
use super::U512;

impl U512 {
    /// Creates a new [`U512`] from a 64-byte array in little-endian order.
    ///
    /// Byte `[0]` is the least significant and byte `[63]` is the most
    /// significant. Reverses the byte order and delegates to
    /// [`U512::from_be_bytes`].
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u512::U512;
    ///
    /// let mut le_bytes = [0u8; 64];
    /// le_bytes[0] = 1; // LSB
    /// assert_eq!(U512::from_le_bytes(le_bytes), U512::from_be_limbs([0, 0, 0, 0, 0, 0, 0, 1]));
    /// ```
    #[inline]
    pub const fn from_le_bytes(bytes: [u8; 64]) -> Self {
        Self::from_be_bytes([
            bytes[63], bytes[62], bytes[61], bytes[60],
            bytes[59], bytes[58], bytes[57], bytes[56],
            bytes[55], bytes[54], bytes[53], bytes[52],
            bytes[51], bytes[50], bytes[49], bytes[48],
            bytes[47], bytes[46], bytes[45], bytes[44],
            bytes[43], bytes[42], bytes[41], bytes[40],
            bytes[39], bytes[38], bytes[37], bytes[36],
            bytes[35], bytes[34], bytes[33], bytes[32],
            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!(U512::from_le_bytes([0; 64]), U512::ZERO);
    }

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

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

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

    /// Round-trip: from_le_bytes reverses from_be_bytes.
    #[test]
    fn inverse_of_be() {
        let be_bytes: [u8; 64] = {
            let mut b = [0u8; 64];
            let mut i = 0;
            while i < 64 {
                b[i] = (i + 1) as u8;
                i += 1;
            }
            b
        };
        let mut le_bytes = be_bytes;
        le_bytes.reverse();
        assert_eq!(
            U512::from_le_bytes(le_bytes),
            U512::from_be_bytes(be_bytes),
        );
    }

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

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