mc_core/util/
packed.rs

1
2/// A packed array is an array of cell (`u64`) with a fixed length and a varying bits
3/// length (byte size) that allows it to store multiple values in the same cell.
4///
5/// Its content can be modified and queried by using methods of this method, the byte
6/// size can also be changed and methods allows to replace its content in-place.
7pub struct PackedArray {
8    cells: Vec<u64>,
9    length: usize,
10    byte_size: u8,
11}
12
13
14impl PackedArray {
15
16    /// Create a new packed array with specific length and byte size (the bit size of each value,
17    /// smallest addressable unit), the default value is 0 if `None` is given.
18    pub fn new(length: usize, byte_size: u8, default: Option<u64>) -> Self {
19
20        Self::check_byte_size(byte_size);
21
22        let default_value = match default {
23            Some(default) if default != 0 => {
24                assert!(default <= Self::calc_mask(byte_size), "Given default value does not fit in {} bits.", byte_size);
25                let vpc = Self::calc_values_per_cell(byte_size);
26                let mut value = default;
27                for _ in 1..vpc {
28                    value <<= byte_size;
29                    value |= default;
30                }
31                value
32            },
33            _ => 0
34        };
35
36        Self {
37            cells: vec![default_value; Self::calc_cells_capacity(length, byte_size)],
38            length,
39            byte_size,
40        }
41
42    }
43
44    pub fn from_raw(length: usize, byte_size: u8, cells: Vec<u64>) -> Option<Self> {
45        Self::check_byte_size(byte_size);
46        if cells.len() >= Self::calc_cells_capacity(length, byte_size) {
47            Some(Self {
48                cells,
49                length,
50                byte_size
51            })
52        } else {
53            None
54        }
55    }
56
57    /// Get the value at a specific index, `None` is returned if you are out of range.
58    pub fn get(&self, index: usize) -> Option<u64> {
59        if index < self.length {
60            let (cell_index, bit_index) = self.get_indices(index);
61            let cell = self.cells[cell_index];
62            Some((cell >> bit_index) & Self::calc_mask(self.byte_size))
63        } else {
64            None
65        }
66    }
67
68    /// Set the value at a specific index.
69    ///
70    /// # Panics
71    /// If the index is out of bounds or if the given value cannot fit in the current byte size.
72    pub fn set(&mut self, index: usize, value: u64) -> u64 {
73        if index < self.length {
74            let mask = Self::calc_mask(self.byte_size);
75            if value <= mask {
76                self.internal_set(index, value, mask)
77            } else {
78                panic!("Given value {} does not fit in {} bits.", value, self.byte_size);
79            }
80        } else {
81            panic!("Index out of bounds, {} with length {}.", index, self.length);
82        }
83    }
84
85    /// Set the value at a specific index and ensure that the given value can fit into it, if
86    /// not, the packed array is resized to a new byte size and the value is inserted.
87    pub fn set_with_resize(&mut self, index: usize, value: u64) -> u64 {
88        let mask = Self::calc_mask(self.byte_size);
89        if value > mask {
90            self.resize_byte(Self::calc_min_byte_size(value));
91        }
92        self.internal_set(index, value, mask)
93    }
94
95    #[inline]
96    fn internal_set(&mut self, index: usize, value: u64, mask: u64) -> u64 {
97        let (cell_index, bit_index) = self.get_indices(index);
98        let cell = &mut self.cells[cell_index];
99        let old_value = (*cell >> bit_index) & mask;
100        *cell = (*cell & !(mask << bit_index)) | (value << bit_index); // Clear and Set
101        old_value
102    }
103
104    fn get_indices(&self, index: usize) -> (usize, usize) {
105        let vpc = Self::calc_values_per_cell(self.byte_size);
106        let cell_index = index / vpc;
107        let bit_index = (index % vpc) * self.byte_size as usize;
108        (cell_index, bit_index)
109    }
110
111    #[inline]
112    pub fn iter<'a>(&'a self) -> impl Iterator<Item = u64> + 'a {
113        self.cells.iter().copied().unpack_aligned(self.byte_size).take(self.length)
114    }
115
116    pub fn replace(&mut self, mut replacer: impl FnMut(usize, u64) -> u64) {
117        let byte_size = self.byte_size as usize;
118        let vpc = Self::calc_values_per_cell(self.byte_size);
119        let mask = Self::calc_mask(self.byte_size);
120        let mut index = 0;
121        for mut_cell in &mut self.cells {
122            let mut old_cell = *mut_cell;
123            let mut new_cell = 0;
124            for value_index in 0..vpc {
125                let bit_index = value_index * byte_size;
126                new_cell |= (replacer(index, old_cell & mask) & mask) << bit_index;
127                old_cell >>= self.byte_size;
128                index += 1;
129                if index >= self.length {
130                    break;
131                }
132            }
133            *mut_cell = new_cell;
134        }
135    }
136
137    pub fn resize_byte(&mut self, new_byte_size: u8) {
138        self.internal_resize_byte::<fn(usize, u64) -> u64>(new_byte_size, None);
139    }
140
141    pub fn resize_byte_and_replace<F>(&mut self, new_byte_size: u8, replacer: F)
142    where
143        F: FnMut(usize, u64) -> u64
144    {
145        self.internal_resize_byte(new_byte_size, Some(replacer));
146    }
147
148    fn internal_resize_byte<F>(&mut self, new_byte_size: u8, mut replacer: Option<F>)
149    where
150        F: FnMut(usize, u64) -> u64
151    {
152
153        if new_byte_size == self.byte_size {
154            if let Some(replacer) = replacer {
155                self.replace(replacer);
156                return;
157            }
158        }
159
160        Self::check_byte_size(new_byte_size);
161        assert!(new_byte_size > self.byte_size, "New byte size should be greater than previous.");
162
163        let old_byte_size = self.byte_size;
164        self.byte_size = new_byte_size;
165
166        let old_mask = Self::calc_mask(old_byte_size);
167        let new_mask = Self::calc_mask(new_byte_size);
168
169        let new_cells_cap = Self::calc_cells_capacity(self.length, new_byte_size);
170
171        let old_vpc = Self::calc_values_per_cell(old_byte_size);
172        let new_vpc = Self::calc_values_per_cell(new_byte_size);
173
174        let old_byte_size = old_byte_size as usize;
175        let new_byte_size = new_byte_size as usize;
176
177        let old_cells_cap = self.cells.len();
178        self.cells.resize(new_cells_cap, 0u64);
179
180        for old_cell_index in (0..old_cells_cap).rev() {
181            let old_cell = self.cells[old_cell_index];
182            for value_index in 0..old_vpc {
183                let index = old_cell_index * old_vpc + value_index;
184                if index < self.length {
185
186                    let old_bit_index = value_index * old_byte_size;
187                    let mut value = (old_cell >> old_bit_index) & old_mask;
188
189                    let new_cell_index = index / new_vpc;
190                    let new_bit_index = (index % new_vpc) * new_byte_size;
191
192                    if let Some(ref mut replacer) = replacer {
193                        value = replacer(index, value);
194                    }
195
196                    let cell = &mut self.cells[new_cell_index];
197                    *cell = (*cell & !(new_mask << new_bit_index)) | (value << new_bit_index);
198
199                }
200            }
201        }
202
203    }
204
205    #[inline]
206    pub fn len(&self) -> usize {
207        self.length
208    }
209
210    #[inline]
211    pub fn is_empty(&self) -> bool {
212        self.length == 0
213    }
214
215    #[inline]
216    pub fn byte_size(&self) -> u8 {
217        self.byte_size
218    }
219
220    pub fn max_value(&self) -> u64 {
221        Self::calc_mask(self.byte_size)
222    }
223
224    #[inline]
225    pub fn cells_len(&self) -> usize {
226        self.cells.len()
227    }
228
229    // Unsafe and cell-related methods //
230
231    pub fn get_cell(&self, index: usize) -> u64 {
232        self.cells[index]
233    }
234
235    pub unsafe fn set_cell(&mut self, index: usize, cell: u64) {
236        self.cells[index] = cell;
237    }
238
239    pub unsafe fn resize_raw(&mut self, new_byte_size: u8) {
240        Self::check_byte_size(new_byte_size);
241        self.byte_size = new_byte_size;
242        let new_cells_cap = Self::calc_cells_capacity(self.length, new_byte_size);
243        self.cells.resize(new_cells_cap, 0u64);
244    }
245
246    pub unsafe fn clear_cells(&mut self) {
247        self.cells.iter_mut().for_each(|c| *c = 0);
248    }
249
250    #[inline]
251    pub fn into_inner(self) -> Vec<u64> {
252        self.cells
253    }
254
255    // Utils //
256
257    #[inline]
258    pub fn calc_values_per_cell(byte_size: u8) -> usize {
259        64 / byte_size as usize
260    }
261
262    #[inline]
263    pub fn calc_cells_capacity(length: usize, byte_size: u8) -> usize {
264        let vpc = Self::calc_values_per_cell(byte_size);
265        (length + vpc - 1) / vpc
266    }
267
268    #[inline]
269    pub fn calc_mask(byte_size: u8) -> u64 {
270        if byte_size == 64 {
271            u64::MAX
272        } else {
273            (1u64 << byte_size) - 1
274        }
275    }
276
277    /// Calculate the minimum size in bits to store de given value, the special case is for
278    /// value `0` which returns a bits size of 1, this special value is simpler to handle
279    /// by the structure's methods.
280    #[inline]
281    pub fn calc_min_byte_size(value: u64) -> u8 {
282        if value == 0 {
283            1
284        } else {
285            (u64::BITS - value.leading_zeros()) as u8
286        }
287    }
288
289    #[inline]
290    fn check_byte_size(byte_size: u8) {
291        assert!(byte_size <= 64, "Byte size is greater than 64.");
292    }
293
294}
295
296
297// Custom iterators //
298
299/// An iterator extension trait for unpacking aligned values from an u64 iterator.
300pub trait PackedIterator: Iterator<Item = u64> {
301
302    #[inline]
303    fn unpack_aligned(self, byte_size: u8) -> UnpackAlignedIter<Self>
304    where
305        Self: Sized
306    {
307        UnpackAlignedIter::new(self, byte_size)
308    }
309
310    #[inline]
311    fn pack_aligned(self, byte_size: u8) -> PackAlignedIter<Self>
312    where
313        Self: Sized
314    {
315        PackAlignedIter::new(self, byte_size)
316    }
317
318}
319
320impl<I> PackedIterator for I
321where
322    I: Iterator<Item = u64>
323{
324    // Defaults are not redefined //
325}
326
327
328/// An iterator to unpack aligned values in from an u64 iterator.
329/// This iterator only requires an byte size and will output every
330/// value found in each cell. What means "aligned" is that value
331/// cannot be defined on two different cells, if there is remaining
332/// space in cells, it is ignored.
333///
334/// The first value in a cell is composed of the first least significant
335/// 'byte size' bits. For exemple with two cells and byte size of 13
336/// (underscore are unused padding bits):
337///
338/// ```text
339/// cell #0: ____________3333333333333222222222222211111111111110000000000000
340/// cell #1: ____________7777777777777666666666666655555555555554444444444444
341/// ```
342///
343/// As you can see, in this configured, only 8 values can be stored.
344pub struct UnpackAlignedIter<I> {
345    inner: I,
346    byte_size: u8,
347    mask: u64,
348    vpc: usize,
349    index: usize,
350    value: u64
351}
352
353impl<I> UnpackAlignedIter<I>
354where
355    I: Iterator<Item = u64>
356{
357
358    pub fn new(inner: I, byte_size: u8) -> Self {
359        Self {
360            inner,
361            byte_size,
362            mask: PackedArray::calc_mask(byte_size),
363            vpc: PackedArray::calc_values_per_cell(byte_size),
364            index: 0,
365            value: 0
366        }
367    }
368
369}
370
371impl<I> Iterator for UnpackAlignedIter<I>
372where
373    I: Iterator<Item = u64>
374{
375
376    type Item = u64;
377
378    fn next(&mut self) -> Option<Self::Item> {
379
380        if self.index % self.vpc == 0 {
381            self.value = self.inner.next()?;
382        }
383
384        let ret = self.value & self.mask;
385        self.value >>= self.byte_size;
386        self.index += 1;
387        Some(ret)
388
389    }
390
391    /*fn nth(&mut self, n: usize) -> Option<Self::Item> {
392        TODO: We should redefine this method in order to speedrun skips.
393    }*/
394
395}
396
397
398/// Reciprocal iterator to `UnpackAlignedIter`.
399pub struct PackAlignedIter<I> {
400    inner: I,
401    byte_size: u8,
402    mask: u64,
403}
404
405impl<I> PackAlignedIter<I>
406where
407    I: Iterator<Item = u64>
408{
409
410    pub fn new(inner: I, byte_size: u8) -> Self {
411        Self {
412            inner,
413            byte_size,
414            mask: PackedArray::calc_mask(byte_size)
415        }
416    }
417
418}
419
420impl<I> Iterator for PackAlignedIter<I>
421where
422    I: Iterator<Item = u64>
423{
424
425    type Item = u64;
426
427    fn next(&mut self) -> Option<Self::Item> {
428
429        let mut value = match self.inner.next() {
430            None => return None,
431            Some(val) => val & self.mask
432        };
433
434        let mut shift = self.byte_size;
435        let shift_limit = 64 - self.byte_size;
436
437        while shift <= shift_limit {
438            match self.inner.next() {
439                None => break,
440                Some(cell) => {
441                    value |= (cell & self.mask) << shift;
442                    shift += self.byte_size;
443                }
444            }
445        }
446
447        Some(value)
448
449    }
450
451}
452
453
454#[cfg(test)]
455mod tests {
456
457    use super::*;
458
459    #[test]
460    fn valid_byte_size() {
461        PackedArray::new(1, 64, None);
462    }
463
464    #[test]
465    #[should_panic]
466    fn invalid_byte_size() {
467        PackedArray::new(1, 65, None);
468    }
469
470    #[test]
471    fn min_byte_size() {
472        assert_eq!(PackedArray::calc_min_byte_size(0), 1);
473        assert_eq!(PackedArray::calc_min_byte_size(1), 1);
474        assert_eq!(PackedArray::calc_min_byte_size(2), 2);
475        assert_eq!(PackedArray::calc_min_byte_size(7), 3);
476        assert_eq!(PackedArray::calc_min_byte_size(63), 6);
477        assert_eq!(PackedArray::calc_min_byte_size(64), 7);
478        assert_eq!(PackedArray::calc_min_byte_size(127), 7);
479    }
480
481    #[test]
482    #[should_panic]
483    fn invalid_default_value() {
484        PackedArray::new(1, 4, Some(16));
485    }
486
487    #[test]
488    #[should_panic]
489    fn invalid_value() {
490        let mut array = PackedArray::new(1, 4, None);
491        array.set(0, 16);
492    }
493
494    #[test]
495    #[should_panic]
496    fn out_of_range_get() {
497        PackedArray::new(10, 4, None).get(10).unwrap();
498    }
499
500    #[test]
501    #[should_panic]
502    fn out_of_range_set() {
503        PackedArray::new(10, 4, None).set(10, 15);
504    }
505
506    #[test]
507    #[should_panic]
508    fn invalid_resize() {
509        PackedArray::new(10, 4, None).resize_byte(4);
510    }
511
512    #[test]
513    fn valid_usage() {
514
515        const LEN: usize = 32;
516
517        let mut array = PackedArray::new(LEN, 4, Some(15));
518
519        assert_eq!(array.cells.len(), 2);
520        assert_eq!(array.cells[0], u64::MAX);
521        assert_eq!(array.cells[1], u64::MAX);
522
523        for value in array.iter() {
524            assert_eq!(value, 15, "construction failed");
525        }
526
527        array.set(2, 3);
528
529        for (i, value) in array.iter().enumerate() {
530            assert_eq!(value, if i == 2 { 3 } else { 15 }, "set failed");
531        }
532
533        array.replace(|_, val| val / 2);
534
535        for (i, value) in array.iter().enumerate() {
536            assert_eq!(value, if i == 2 { 1 } else { 7 }, "replace failed");
537        }
538
539        array.resize_byte(5);
540        assert_eq!(array.cells.len(), 3, "resize failed to change cells len");
541        assert_eq!(array.byte_size, 5, "resize failed to set the new byte size");
542
543        for (i, value) in array.iter().enumerate() {
544            assert_eq!(value, if i == 2 { 1 } else { 7 }, "resize failed to transform values");
545        }
546
547        array.resize_byte_and_replace(16, |_, val| val * 5678);
548        assert_eq!(array.cells.len(), 8, "resize and replace failed to change cells len");
549        assert_eq!(array.byte_size, 16, "resize and replace failed to set the new byte size");
550
551        for (i, value) in array.iter().enumerate() {
552            assert_eq!(value, if i == 2 { 5678 } else { 7 * 5678 }, "resize and replace failed to transform values");
553        }
554
555    }
556
557    #[test]
558    fn iter_unpack_aligned() {
559
560        let raw = [u64::MAX, u64::MAX, u64::MAX];
561
562        assert!(raw.iter().copied().unpack_aligned(4).all(|v| v == 15), "byte size = 4, wrong values");
563        assert_eq!(raw.iter().copied().unpack_aligned(4).count(), 48, "byte size = 4, invalid values count");
564
565        assert!(raw.iter().copied().unpack_aligned(16).all(|v| v == 65_535), "byte size = 16, wrong values");
566        assert_eq!(raw.iter().copied().unpack_aligned(16).count(), 12, "byte size = 16, invalid values count");
567
568        assert!(raw.iter().copied().unpack_aligned(33).all(|v| v == 0x0001_FFFF_FFFF), "byte size = 33, wrong values");
569        assert_eq!(raw.iter().copied().unpack_aligned(33).count(), 3, "byte size = 33, invalid values count");
570
571    }
572
573    #[test]
574    fn iter_pack_aligned() {
575
576        let raw = [0, u32::MAX as u64, u64::MAX];
577
578        let out: Vec<u64> = raw.iter()
579            .copied()
580            .unpack_aligned(4)
581            .pack_aligned(4)
582            .collect();
583
584        assert_eq!(&raw[..], &out[..]);
585
586    }
587
588}