diff --git a/bitfield/src/pack.rs b/bitfield/src/pack.rs index 4b250ae3..56920833 100644 --- a/bitfield/src/pack.rs +++ b/bitfield/src/pack.rs @@ -286,7 +286,7 @@ macro_rules! make_packers { const fn mk_mask(n: u32) -> $Bits { if n == 0 { return 0 - }; + } let one: $Bits = 1; // lolmacros let shift = one.wrapping_shl(n - 1); shift | (shift.saturating_sub(1)) @@ -589,33 +589,42 @@ macro_rules! make_packers { /// /// The packing pair can be used to pack bits from one location /// into another location, and vice versa. - pub const fn pair_at(&self, at: u32) -> $Pair { - let dst = $Pack::<$Bits, ()>::starting_at(at, self.bits()).typed(); - let at = at.saturating_sub(1); - // TODO(eliza): validate that `at + self.bits() < N_BITS` in + pub const fn pair_at(&self, at: u32) -> $Pair { + let dst = $Pack::starting_at(at, self.bits()); + self.pair_with(dst.typed()) + } + + /// Returns a pair type for packing bits from the range + /// specified by `self` after the specified packing spec. + pub const fn pair_after(&self, after: &Self) -> $Pair { + self.pair_at(after.shift_next()) + } + + /// Returns a pair type for packing bits from the range + /// specified by `self` into the range specified by `with`. + /// + /// # Note + /// The two ranges must be the same size. This can be asserted + /// by the `assert_valid` method on the returned pair type. + pub const fn pair_with(&self, dst: Self) -> $Pair { + // TODO(eliza): validate that `dst.shift + self.bits() < N_BITS` in // const fn somehow lol - let (dst_shl, dst_shr) = if at > self.shift { + let (dst_shl, dst_shr) = if dst.shift > self.shift { // If the destination is greater than `self`, we need to // shift left. - ((at - self.shift) as $Bits, 0) + ((dst.shift - self.shift) as $Bits, 0) } else { // Otherwise, shift down. - (0, (self.shift - at) as $Bits) + (0, (self.shift - dst.shift) as $Bits) }; $Pair { src: self.typed(), - dst, + dst: dst.typed(), dst_shl, dst_shr, } } - /// Returns a pair type for packing bits from the range - /// specified by `self` after the specified packing spec. - pub const fn pair_after(&self, after: &Self) -> $Pair { - self.pair_at(after.shift_next()) - } - /// Pack the [`self.bits()`] least-significant bits from `value` into `base`. /// /// # Panics @@ -794,6 +803,25 @@ macro_rules! make_packers { Self(packer.pack_truncating(value, self.0)) } + /// Pack bits from `src` into `self`, using the packing pair + /// specified by `pair`, with `self` serving as the "destination" member + /// of the pair, and `src` serving as the "source" member of the + /// pair. + #[inline] + pub const fn pack_from_src(self, value: $Bits, pair: &$Pair) -> Self { + Self(pair.pack_from_src(self.0, value)) + } + + /// Pack bits from `dst` into `self`, using the packing pair + /// specified by `pair`, with `self` serving as the "siyrce" member + /// of the pair, and `dst` serving as the "destination" member of the + /// pair. + #[inline] + pub const fn pack_from_dst(self, value: $Bits, pair: &$Pair) -> Self { + Self(pair.pack_from_dst(value, self.0)) + } + + /// Pack bits from `value` into `self`, using the range /// specified by `packer`. ///