1use core::ops::RangeInclusive;
4
5use crabslab::{Id, Slab};
6
7pub const fn bits(range: RangeInclusive<u32>) -> (u32, u32) {
9 let mut start = *range.start();
10 let end = *range.end();
11 let mut mask = 0;
12 while start <= end {
13 mask = (mask << 1) | 1;
14 start += 1;
15 }
16 (*range.start(), mask)
17}
18
19pub fn insert(bits: &mut u32, (shift, mask): (u32, u32), value: u32) {
21 if shift >= 1 {
23 *bits = (*bits >> shift) | (*bits << (32 - shift));
24 }
25 *bits &= !mask;
27 *bits |= value & mask;
29 if shift >= 1 {
31 *bits = (*bits << shift) | (*bits >> (32 - shift));
32 }
33}
34
35pub fn extract(bits: u32, (shift, mask): (u32, u32)) -> u32 {
37 (bits >> shift) & mask
38}
39
40pub const U8_0_BITS: (u32, u32) = bits(0..=7);
42pub const U8_1_BITS: (u32, u32) = bits(8..=15);
44pub const U8_2_BITS: (u32, u32) = bits(16..=23);
46pub const U8_3_BITS: (u32, u32) = bits(24..=31);
48
49pub const U16_0_BITS: (u32, u32) = bits(0..=15);
51pub const U16_1_BITS: (u32, u32) = bits(16..=31);
53
54pub fn extract_u8(
59 u32_index: usize,
61 byte_offset: usize,
63 slab: &[u32],
65) -> (u32, usize, usize) {
66 const SHIFT_MASKS: [((u32, u32), usize); 4] = [
67 (U8_0_BITS, 0),
68 (U8_1_BITS, 0),
69 (U8_2_BITS, 0),
70 (U8_3_BITS, 1),
71 ];
72 let byte_mod = byte_offset % 4;
73 let (shift_mask, index_inc) = SHIFT_MASKS[byte_mod];
74 let u32_value = slab.read(Id::from(u32_index));
75 let value = extract(u32_value, shift_mask);
76 (value, u32_index + index_inc, byte_mod + 1)
77}
78
79pub fn extract_i8(
84 u32_index: usize,
86 byte_offset: usize,
88 slab: &[u32],
90) -> (i32, usize, usize) {
91 let (value, u32_index, n) = extract_u8(u32_index, byte_offset, slab);
92 let value: i32 = (value as i32 & 0xFF) - ((value as i32 & 0x80) << 1);
93 (value, u32_index, n)
94}
95
96pub fn extract_u16(
98 u32_index: usize,
100 byte_offset: usize,
102 slab: &[u32],
104) -> (u32, usize, usize) {
105 const SHIFT_MASKS: [((u32, u32), usize, usize); 4] = [
109 (U16_0_BITS, 2, 0),
110 (U16_0_BITS, 2, 0),
111 (U16_1_BITS, 0, 1),
112 (U16_1_BITS, 0, 1),
113 ];
114 let byte_mod = byte_offset % 4;
115 crate::println!("byte_mod: {byte_mod}");
116 let (shift_mask, next_byte_offset, index_inc) = SHIFT_MASKS[byte_mod];
117 let u32_value = slab.read(Id::from(u32_index));
118 crate::println!("u32: {:032b}", u32_value);
119 let value = extract(u32_value, shift_mask);
120 crate::println!("u16: {:016b}", value);
121 crate::println!("u32: {:?}", u32_value);
122 (value, u32_index + index_inc, next_byte_offset)
123}
124
125pub fn extract_i16(
127 u32_index: usize,
129 byte_offset: usize,
131 slab: &[u32],
133) -> (i32, usize, usize) {
134 let (value, u32_index, n) = extract_u16(u32_index, byte_offset, slab);
135 let value: i32 = (value as i32 & 0xFFFF) - ((value as i32 & 0x8000) << 1);
136 (value, u32_index, n)
137}
138
139pub fn extract_u32(
141 u32_index: usize,
143 _byte_offset: usize,
145 slab: &[u32],
147) -> (u32, usize, usize) {
148 (slab.read(Id::from(u32_index)), u32_index + 1, 0)
149}
150
151pub fn extract_i32(
153 u32_index: usize,
155 _byte_offset: usize,
157 slab: &[u32],
159) -> (i32, usize, usize) {
160 let (value, _, _) = extract_u32(u32_index, 0, slab);
161 (value as i32, u32_index + 1, 0)
162}
163
164pub fn extract_f32(
166 u32_index: usize,
168 _byte_offset: usize,
170 slab: &[u32],
172) -> (f32, usize, usize) {
173 let (value, _, _) = extract_u32(u32_index, 0, slab);
174 (f32::from_bits(value), u32_index + 1, 0)
175}
176
177#[cfg(test)]
178mod test {
179 use super::*;
180
181 #[test]
182 fn bits_sanity() {
183 let mut store = 0;
184 assert_eq!(
185 "00000000000000000000000000000000",
186 &format!("{:032b}", store)
187 );
188 insert(&mut store, bits(0..=7), u8::MAX as u32);
189 assert_eq!(
190 "00000000000000000000000011111111",
191 &format!("{:032b}", store)
192 );
193 store = 0;
194 insert(&mut store, bits(8..=15), u8::MAX as u32);
195 assert_eq!(
196 "00000000000000001111111100000000",
197 &format!("{:032b}", store)
198 );
199 }
200
201 #[test]
202 fn bits_u8_sanity() {
203 let mut bits = 0;
204 println!("bits: {:032b}", bits);
205 super::insert(&mut bits, super::U8_0_BITS, 6u8 as u32);
206 println!("bits: {:032b}", bits);
207 assert_eq!(super::extract(bits, super::U8_0_BITS), 6);
208 super::insert(&mut bits, super::U8_1_BITS, 5u8 as u32);
209 println!("bits: {:032b}", bits);
210 assert_eq!(super::extract(bits, super::U8_0_BITS), 6);
211 assert_eq!(super::extract(bits, super::U8_1_BITS), 5);
212 super::insert(&mut bits, super::U8_2_BITS, 4u8 as u32);
213 println!("bits: {:032b}", bits);
214 assert_eq!(super::extract(bits, super::U8_0_BITS), 6);
215 assert_eq!(super::extract(bits, super::U8_1_BITS), 5);
216 assert_eq!(super::extract(bits, super::U8_2_BITS), 4);
217 super::insert(&mut bits, super::U8_3_BITS, 3u8 as u32);
218 println!("bits: {:032b}", bits);
219 assert_eq!(super::extract(bits, super::U8_0_BITS), 6);
220 assert_eq!(super::extract(bits, super::U8_1_BITS), 5);
221 assert_eq!(super::extract(bits, super::U8_2_BITS), 4);
222 assert_eq!(super::extract(bits, super::U8_3_BITS), 3);
223 }
224
225 #[test]
226 fn extract_u8_sanity() {
227 let u8_slab = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 0u8, 0u8];
228 let u32_slab: &[u32] = bytemuck::cast_slice(&u8_slab);
229 let index = 0;
230 let n = 0;
231 let (a, index, n) = extract_u8(index, n, u32_slab);
232 let (b, index, n) = extract_u8(index, n, u32_slab);
233 let (c, index, n) = extract_u8(index, n, u32_slab);
234 let (d, index, n) = extract_u8(index, n, u32_slab);
235 let (e, index, n) = extract_u8(index, n, u32_slab);
236 let (f, _, _) = extract_u8(index, n, u32_slab);
237 assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]);
238 }
239
240 #[test]
241 fn extract_i8_sanity() {
242 let i8_slab = [0i8, -1i8, -2i8, -3i8, 4i8, 5i8, 0i8, 0i8];
243 let u32_slab: &[u32] = bytemuck::cast_slice(&i8_slab);
244 let index = 0;
245 let n = 0;
246 let (a, index, n) = extract_i8(index, n, u32_slab);
247 let (b, index, n) = extract_i8(index, n, u32_slab);
248 let (c, index, n) = extract_i8(index, n, u32_slab);
249 let (d, index, n) = extract_i8(index, n, u32_slab);
250 let (e, index, n) = extract_i8(index, n, u32_slab);
251 let (f, _, _) = extract_i8(index, n, u32_slab);
252 assert_eq!([0, -1, -2, -3, 4, 5], [a, b, c, d, e, f]);
253 }
254
255 #[test]
256 fn extract_u16_sanity() {
257 let u16_slab = [0u16, 1u16, 2u16, 3u16, 4u16, 5u16];
258 let u32_slab: &[u32] = bytemuck::cast_slice(&u16_slab);
259 let index = 0;
260 let n = 0;
261 let (a, index, n) = extract_u16(index, n, u32_slab);
262 let (b, index, n) = extract_u16(index, n, u32_slab);
263 let (c, index, n) = extract_u16(index, n, u32_slab);
264 let (d, index, n) = extract_u16(index, n, u32_slab);
265 let (e, index, n) = extract_u16(index, n, u32_slab);
266 let (f, _, _) = extract_u16(index, n, u32_slab);
267 assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]);
268 }
269
270 #[test]
271 fn extract_i16_sanity() {
272 let i16_slab = [0i16, -1i16, -2i16, -3i16, 4i16, 5i16, -12345i16, 0i16];
273 let u32_slab: &[u32] = bytemuck::cast_slice(&i16_slab);
274 let index = 0;
275 let n = 0;
276 let (a, index, n) = extract_i16(index, n, u32_slab);
277 let (b, index, n) = extract_i16(index, n, u32_slab);
278 let (c, index, n) = extract_i16(index, n, u32_slab);
279 let (d, index, n) = extract_i16(index, n, u32_slab);
280 let (e, index, n) = extract_i16(index, n, u32_slab);
281 let (f, index, n) = extract_i16(index, n, u32_slab);
282 let (g, _, _) = extract_i16(index, n, u32_slab);
283 assert_eq!([0, -1, -2, -3, 4, 5, -12345], [a, b, c, d, e, f, g]);
284 }
285
286 #[test]
287 fn extract_u32_sanity() {
288 let u32_slab = [0u32, 1u32, 2u32, 3u32, 4u32, 5u32];
289 let u32_slab: &[u32] = bytemuck::cast_slice(&u32_slab);
290 let index = 0;
291 let n = 0;
292 let (a, index, n) = extract_u32(index, n, u32_slab);
293 let (b, index, n) = extract_u32(index, n, u32_slab);
294 let (c, index, n) = extract_u32(index, n, u32_slab);
295 let (d, index, n) = extract_u32(index, n, u32_slab);
296 let (e, index, n) = extract_u32(index, n, u32_slab);
297 let (f, _, _) = extract_u32(index, n, u32_slab);
298 assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]);
299 }
300
301 #[test]
302 fn extract_i32_sanity() {
303 let i32_slab = [0i32, -1i32, -2i32, -3i32, 4i32, 5i32, -12345i32];
304 let u32_slab: &[u32] = bytemuck::cast_slice(&i32_slab);
305 let index = 0;
306 let n = 0;
307 let (a, index, n) = extract_i32(index, n, u32_slab);
308 let (b, index, n) = extract_i32(index, n, u32_slab);
309 let (c, index, n) = extract_i32(index, n, u32_slab);
310 let (d, index, n) = extract_i32(index, n, u32_slab);
311 let (e, index, n) = extract_i32(index, n, u32_slab);
312 let (f, index, n) = extract_i32(index, n, u32_slab);
313 let (g, _, _) = extract_i32(index, n, u32_slab);
314 assert_eq!([0, -1, -2, -3, 4, 5, -12345], [a, b, c, d, e, f, g]);
315 }
316
317 #[test]
318 fn extract_f32_sanity() {
319 let f32_slab = [
320 0.0f32,
321 -1.0f32,
322 -2.0f32,
323 -3.0f32,
324 4.0f32,
325 5.0f32,
326 -12345.0f32,
327 ];
328 let u32_slab: &[u32] = bytemuck::cast_slice(&f32_slab);
329 let index = 0;
330 let n = 0;
331 let (a, index, n) = extract_f32(index, n, u32_slab);
332 let (b, index, n) = extract_f32(index, n, u32_slab);
333 let (c, index, n) = extract_f32(index, n, u32_slab);
334 let (d, index, n) = extract_f32(index, n, u32_slab);
335 let (e, index, n) = extract_f32(index, n, u32_slab);
336 let (f, index, n) = extract_f32(index, n, u32_slab);
337 let (g, _, _) = extract_f32(index, n, u32_slab);
338 assert_eq!(
339 [0f32, -1f32, -2f32, -3f32, 4f32, 5f32, -12345f32],
340 [a, b, c, d, e, f, g]
341 );
342 }
343}