1pub(crate) fn deserialize_13(bytes: &[u8; 13 * 256 / 8]) -> [u16; 256] {
7 let mut out = [0u16; 256];
8 for g in 0..32 {
10 let b = &bytes[13 * g..13 * g + 13];
11 let w = |k: usize| b[k] as u16;
13 let o = 8 * g;
14 out[o] = w(0) | ((w(1) & 0x1f) << 8);
15 out[o + 1] = (w(1) >> 5) | ((w(2)) << 3) | ((w(3) & 0x03) << 11);
16 out[o + 2] = (w(3) >> 2) | ((w(4) & 0x7f) << 6);
17 out[o + 3] = (w(4) >> 7) | ((w(5)) << 1) | ((w(6) & 0x0f) << 9);
18 out[o + 4] = (w(6) >> 4) | ((w(7)) << 4) | ((w(8) & 0x01) << 12);
19 out[o + 5] = (w(8) >> 1) | ((w(9) & 0x3f) << 7);
20 out[o + 6] = (w(9) >> 6) | ((w(10)) << 2) | ((w(11) & 0x07) << 10);
21 out[o + 7] = (w(11) >> 3) | ((w(12)) << 5);
22 }
23 out
24}
25
26pub(crate) fn deserialize_10(bytes: &[u8; 10 * 256 / 8]) -> [u16; 256] {
30 let mut out = [0u16; 256];
31 for g in 0..64 {
33 let b = &bytes[5 * g..5 * g + 5];
34 let w = |k: usize| b[k] as u16;
35 let o = 4 * g;
36 out[o] = w(0) | ((w(1) & 0x03) << 8);
37 out[o + 1] = (w(1) >> 2) | ((w(2) & 0x0f) << 6);
38 out[o + 2] = (w(2) >> 4) | ((w(3) & 0x3f) << 4);
39 out[o + 3] = (w(3) >> 6) | (w(4) << 2);
40 }
41 out
42}
43
44#[allow(clippy::needless_range_loop)]
47pub(crate) fn deserialize_generic<const N: usize>(bytes: &[u8], bits_per_elem: usize) -> [u16; N] {
48 assert_eq!((bits_per_elem * N) % 8, 0);
50 assert_eq!(bytes.len(), bits_per_elem * N / 8);
51
52 let mut out = [0u16; N];
53 let bitmask: u32 = (1 << bits_per_elem) - 1;
54
55 let mut window: u32 = 0;
58 let mut bits_in_window: usize = 0;
59 let mut byte_pos: usize = 0;
60
61 for idx in 0..N {
62 while bits_in_window < bits_per_elem {
64 window |= (bytes[byte_pos] as u32) << bits_in_window;
65 byte_pos += 1;
66 bits_in_window += 8;
67 }
68
69 out[idx] = (window & bitmask) as u16;
71 window >>= bits_per_elem;
72 bits_in_window -= bits_per_elem;
73 }
74
75 out
76}
77
78pub(crate) fn serialize_10(data: &[u16; 256], out_buf: &mut [u8; 10 * 256 / 8]) {
82 for g in 0..64 {
84 let o = 4 * g;
85 let d = |k: usize| data[o + k] & 0x3ff;
88 let b = 5 * g;
89 out_buf[b] = d(0) as u8;
90 out_buf[b + 1] = ((d(0) >> 8) | (d(1) << 2)) as u8;
91 out_buf[b + 2] = ((d(1) >> 6) | (d(2) << 4)) as u8;
92 out_buf[b + 3] = ((d(2) >> 4) | (d(3) << 6)) as u8;
93 out_buf[b + 4] = (d(3) >> 2) as u8;
94 }
95}
96
97pub(crate) fn serialize(data: &[u16], out_buf: &mut [u8], bits_per_elem: usize) {
101 assert_eq!(out_buf.len(), bits_per_elem * data.len() / 8);
102
103 let bitmask: u32 = (1 << bits_per_elem) - 1;
104
105 let mut window: u32 = 0;
108 let mut bits_in_window: usize = 0;
109 let mut byte_pos: usize = 0;
110
111 for &elem in data.iter() {
112 window |= ((elem as u32) & bitmask) << bits_in_window;
114 bits_in_window += bits_per_elem;
115
116 while bits_in_window >= 8 {
118 out_buf[byte_pos] = window as u8;
119 window >>= 8;
120 bits_in_window -= 8;
121 byte_pos += 1;
122 }
123 }
124
125 debug_assert_eq!(bits_in_window, 0);
127}
128
129#[test]
131fn specialized_deser_matches_generic() {
132 use rand::Rng;
133 let mut rng = rand::rng();
134
135 for _ in 0..100 {
137 let bytes: [u8; 13 * 256 / 8] = rng.random();
138 let generic: [u16; 256] = deserialize_generic(&bytes, 13);
139 let fast = deserialize_13(&bytes);
140 assert_eq!(generic, fast);
141 }
142
143 for _ in 0..100 {
145 let bytes: [u8; 10 * 256 / 8] = rng.random();
146 let generic: [u16; 256] = deserialize_generic(&bytes, 10);
147 let fast = deserialize_10(&bytes);
148 assert_eq!(generic, fast);
149 }
150}
151
152#[test]
154fn specialized_ser_matches_generic() {
155 use rand::Rng;
156 let mut rng = rand::rng();
157
158 for _ in 0..100 {
160 let data: [u16; 256] = rng.random();
161 let mut generic = [0u8; 10 * 256 / 8];
162 let mut fast = [0u8; 10 * 256 / 8];
163 serialize(&data, &mut generic, 10);
164 serialize_10(&data, &mut fast);
165 assert_eq!(generic, fast);
166 }
167}