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

impl U384 {
    /// Creates a new [`U384`] from a 48-byte array in little-endian order.
    ///
    /// Bytes `[0..8]` become limb `[0]` (least significant), bytes `[8..16]`
    /// become `[1]`, and so on through bytes `[40..48]` which become `[5]`
    /// (most significant).
    ///
    /// # Examples
    ///
    /// ```
    /// use cnfy_uint::u384::U384;
    ///
    /// let mut bytes = [0u8; 48];
    /// bytes[0] = 1;
    /// assert_eq!(U384::from_le_bytes(bytes), U384::from_be_limbs([0, 0, 0, 0, 0, 1]));
    /// ```
    #[inline]
    pub const fn from_le_bytes(bytes: [u8; 48]) -> Self {
        let l0 = u64::from_le_bytes([
            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
        ]);
        let l1 = u64::from_le_bytes([
            bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
        ]);
        let l2 = u64::from_le_bytes([
            bytes[16], bytes[17], bytes[18], bytes[19], bytes[20], bytes[21], bytes[22], bytes[23],
        ]);
        let l3 = u64::from_le_bytes([
            bytes[24], bytes[25], bytes[26], bytes[27], bytes[28], bytes[29], bytes[30], bytes[31],
        ]);
        let l4 = u64::from_le_bytes([
            bytes[32], bytes[33], bytes[34], bytes[35], bytes[36], bytes[37], bytes[38], bytes[39],
        ]);
        let l5 = u64::from_le_bytes([
            bytes[40], bytes[41], bytes[42], bytes[43], bytes[44], bytes[45], bytes[46], bytes[47],
        ]);
        Self([l0, l1, l2, l3, l4, l5])
    }
}

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

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

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

    /// Byte 0 (least significant in LE) maps to the low bit of limb w5.
    #[test]
    fn single_lsb() {
        let mut bytes = [0u8; 48];
        bytes[0] = 1;
        assert_eq!(
            U384::from_le_bytes(bytes),
            U384::from_be_limbs([0, 0, 0, 0, 0, 1]),
        );
    }

    /// Byte 47 (most significant in LE) maps to the high byte of limb w0.
    #[test]
    fn single_msb() {
        let mut bytes = [0u8; 48];
        bytes[47] = 0x80;
        assert_eq!(
            U384::from_le_bytes(bytes),
            U384::from_be_limbs([0x8000000000000000, 0, 0, 0, 0, 0]),
        );
    }

    /// Round-trip with from_be_bytes using reversed bytes.
    #[test]
    fn le_vs_be() {
        let mut be_bytes = [0u8; 48];
        be_bytes[47] = 0x42;
        let mut le_bytes = [0u8; 48];
        le_bytes[0] = 0x42;
        assert_eq!(U384::from_be_bytes(be_bytes), U384::from_le_bytes(le_bytes));
    }
}
