diff options
Diffstat (limited to 'prism/src/unpack.rs')
-rw-r--r-- | prism/src/unpack.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/prism/src/unpack.rs b/prism/src/unpack.rs new file mode 100644 index 0000000..03e0018 --- /dev/null +++ b/prism/src/unpack.rs @@ -0,0 +1,62 @@ +const TEN_MASK: u64 = 1023; // ten bits + +pub fn tenbit(packd: &[u8], count: usize, upack: &mut [u16]) { + let required_len_packd = (count as f32 * (10.0 / 8.0)).ceil() as usize; + + println!( + "requires {required_len_packd} bytes | {} groups of 5", + count / 4 + ); + + if count > upack.len() { + panic!( + "expected output buffer to be {count} bytes, got {} bytes", + upack.len() + ) + } + + if required_len_packd > packd.len() { + panic!( + "expected input to be at least {required_len_packd} bytes, it was {}", + packd.len() + ) + } + + let mut packd = packd[..required_len_packd].to_vec(); + packd.reverse(); + let chunker = packd.chunks_exact(5); + let remain = chunker.remainder(); + + for (idx, chnk) in chunker.enumerate() { + let long = u64::from_be_bytes([ + 0x00, 0x00, 0x00, chnk[0], chnk[1], chnk[2], chnk[3], chnk[4], + ]); + + let b4 = long & TEN_MASK; + let b3 = (long >> 10) & TEN_MASK; + let b2 = (long >> 20) & TEN_MASK; + let b1 = (long >> 30) & TEN_MASK; + + let idx = idx * 4; + upack[idx] = b1 as u16; + upack[idx + 1] = b2 as u16; + upack[idx + 2] = b3 as u16; + upack[idx + 3] = b4 as u16; + } + + if remain.len() > 0 { + let mut long_bytes = [0x00; 8]; + + for (idx, byte) in remain.iter().enumerate() { + long_bytes[idx] = *byte; + } + + let long = u64::from_le_bytes(long_bytes); + + let count_remain = count % 4; + let start = count - count_remain; + for idx in 0..count_remain { + upack[start + idx] = ((long >> (10 * idx)) & TEN_MASK) as u16; + } + } +} |