about summary refs log tree commit diff
path: root/prism/src/unpack.rs
blob: bc761f39b1281aeaaaae2205fa70dd1abd9039d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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;

	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;
		}
	}
}

//pub fn twelvebit(packed: &[u8]) {
// 3 bytes per 2 12-bits
//}