use super::constants::*;

#[allow(dead_code)]
#[inline(always)]
pub const fn weight_payload_limit(n_weights: usize) -> usize {
    (n_weights * MAX_W_BITS + 7) / 8
}

#[inline(always)]
pub fn decode_weight(u: usize) -> (usize, usize) {
    let index = u & 0x1F;
    let u_bits = WEIGHTS_BITS_TABLE[index] as usize;
    let w = match u_bits {
        8 => 8 + ((u >> 4) & 0xF),
        14 => 24 + ((u >> 4) & 0x3FF),
        _ => WEIGHTS_VALUE_TABLE[index] as usize,
    };
    debug_assert!(w < 1048);
    (w, u_bits)
}

#[inline(always)]
pub fn encode_weight(w: usize) -> (usize, usize) {
    debug_assert!(w < 1048);
    match w {
        0 => (0, 2),
        1 => (2, 2),
        2 => (1, 3),
        3 => (5, 3),
        4 => (3, 5),
        5 => (11, 5),
        6 => (19, 5),
        7 => (27, 5),
        v if v < 24 => (((v - 8) << 4) + 7, 8),
        v => (((v - 24) << 4) + 15, 14),
    }
}

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

    #[test]
    fn encode_decode_all() {
        for value in 0..1048 {
            let (u, u_bits) = encode_weight(value);
            let (v, v_bits) = decode_weight(u);
            assert_eq!(v, value);
            assert_eq!(u_bits, v_bits);
        }
    }
}
