| 1 | use std::fmt; |
| 2 | |
| 3 | #[derive (Clone, Copy, PartialEq)] |
| 4 | pub(crate) struct Pack { |
| 5 | mask: usize, |
| 6 | shift: u32, |
| 7 | } |
| 8 | |
| 9 | impl Pack { |
| 10 | /// Value is packed in the `width` least-significant bits. |
| 11 | pub(crate) const fn least_significant(width: u32) -> Pack { |
| 12 | let mask = mask_for(width); |
| 13 | |
| 14 | Pack { mask, shift: 0 } |
| 15 | } |
| 16 | |
| 17 | /// Value is packed in the `width` more-significant bits. |
| 18 | pub(crate) const fn then(&self, width: u32) -> Pack { |
| 19 | let shift = usize::BITS - self.mask.leading_zeros(); |
| 20 | let mask = mask_for(width) << shift; |
| 21 | |
| 22 | Pack { mask, shift } |
| 23 | } |
| 24 | |
| 25 | /// Width, in bits, dedicated to storing the value. |
| 26 | pub(crate) const fn width(&self) -> u32 { |
| 27 | usize::BITS - (self.mask >> self.shift).leading_zeros() |
| 28 | } |
| 29 | |
| 30 | /// Max representable value. |
| 31 | pub(crate) const fn max_value(&self) -> usize { |
| 32 | (1 << self.width()) - 1 |
| 33 | } |
| 34 | |
| 35 | pub(crate) fn pack(&self, value: usize, base: usize) -> usize { |
| 36 | assert!(value <= self.max_value()); |
| 37 | (base & !self.mask) | (value << self.shift) |
| 38 | } |
| 39 | |
| 40 | pub(crate) fn unpack(&self, src: usize) -> usize { |
| 41 | unpack(src, self.mask, self.shift) |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | impl fmt::Debug for Pack { |
| 46 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 47 | write!( |
| 48 | fmt, |
| 49 | "Pack {{ mask: {:b}, shift: {} }}" , |
| 50 | self.mask, self.shift |
| 51 | ) |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /// Returns a `usize` with the right-most `n` bits set. |
| 56 | pub(crate) const fn mask_for(n: u32) -> usize { |
| 57 | let shift: usize = 1usize.wrapping_shl(n - 1); |
| 58 | shift | (shift - 1) |
| 59 | } |
| 60 | |
| 61 | /// Unpacks a value using a mask & shift. |
| 62 | pub(crate) const fn unpack(src: usize, mask: usize, shift: u32) -> usize { |
| 63 | (src & mask) >> shift |
| 64 | } |
| 65 | |