Skip to content
Snippets Groups Projects
interleaver.rs 1.58 KiB
Newer Older
Stephen D's avatar
Stephen D committed
use arrayvec::ArrayVec;
use bitvec::prelude::*;

pub(crate) fn interleave<const N: usize>(data: &ArrayVec<u8, N>) -> ArrayVec<u8, N> {
    let bv = data.view_bits::<Msb0>();

    let mut out: ArrayVec<u8, N> = ArrayVec::new();
    for _ in 0..data.len() {
        out.push(0);
    }
    let bv_out = out.view_bits_mut::<Msb0>();

    let mut out_i = 0;
    for i in 0..32 {
        for j in (0..bv.len()).step_by(32) {
            if i + j >= bv.len() {
                continue;
            }

            bv_out.set(out_i, bv[i + j]);

            out_i += 1;
        }
    }

    out
}

pub(crate) fn uninterleave<const N: usize>(data: &ArrayVec<u8, N>) -> ArrayVec<u8, N> {
    let bv = data.view_bits::<Msb0>();

    let mut out: ArrayVec<u8, N> = ArrayVec::new();
    for _ in 0..data.len() {
        out.push(0);
    }
    let bv_out = out.view_bits_mut::<Msb0>();

    let mut out_i = 0;
    for i in 0..32 {
        for j in (0..bv.len()).step_by(32) {
            if i + j >= bv.len() {
                continue;
            }

            bv_out.set(i + j, bv[out_i]);

            out_i += 1;
        }
    }

    out
}

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

    #[test]
    fn interleaver_works() {
        let orig =
            ArrayVec::try_from([0x84, 0x73, 0x12, 0xA3, 0xFF, 0x00, 0xC2, 0x1B, 0x77]).unwrap();
        let interleaved = interleave(&orig);

        let expected = [0xCD, 0xB5, 0xDB, 0x2A, 0x0A, 0x52, 0x0C, 0x89, 0x4F];
        assert_eq!(expected, interleaved[..]);

        let uninterleaved = uninterleave(&interleaved);

        assert_eq!(orig, uninterleaved);
    }
}