Skip to content

Commit 4c06f72

Browse files
committed
PackedFe32: introduce ability to re-pack elements
Adds a couple elements to the API. Note that this *is* a breaking change because we are adding a method to the `PackedFe32` trait, which is not sealed, so any downstream implementors will be broken.
1 parent a24825d commit 4c06f72

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

api/all-features.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,12 +850,14 @@ pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::new(hrp: &'hrp bech32::p
850850
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
851851
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::size_hint(&self) -> (usize, core::option::Option<usize>)
852852
pub fn bech32::primitives::checksum::PackedFe32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
853+
pub fn bech32::primitives::checksum::PackedFe32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
853854
pub fn bech32::primitives::checksum::PackedFe32::unpack(&self, n: usize) -> u8
854855
pub fn bech32::primitives::checksum::PackedNull::bitxor(self, bech32::primitives::checksum::PackedNull) -> bech32::primitives::checksum::PackedNull
855856
pub fn bech32::primitives::checksum::PackedNull::clone(&self) -> bech32::primitives::checksum::PackedNull
856857
pub fn bech32::primitives::checksum::PackedNull::eq(&self, other: &bech32::primitives::checksum::PackedNull) -> bool
857858
pub fn bech32::primitives::checksum::PackedNull::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
858859
pub fn bech32::primitives::checksum::PackedNull::mul_by_x_then_add(&mut self, usize, u8) -> u8
860+
pub fn bech32::primitives::checksum::PackedNull::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
859861
pub fn bech32::primitives::checksum::PackedNull::unpack(&self, usize) -> u8
860862
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::len(&self) -> usize
861863
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
@@ -1122,10 +1124,13 @@ pub fn bech32::segwit::encode_v0(hrp: bech32::primitives::hrp::Hrp, witness_prog
11221124
pub fn bech32::segwit::encode_v1(hrp: bech32::primitives::hrp::Hrp, witness_program: &[u8]) -> core::result::Result<alloc::string::String, bech32::segwit::EncodeError>
11231125
pub fn bech32::segwit::encoded_length(hrp: bech32::primitives::hrp::Hrp, _witness_version: bech32::primitives::gf32::Fe32, witness_program: &[u8]) -> core::result::Result<usize, bech32::primitives::decode::SegwitCodeLengthError>
11241126
pub fn u128::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1127+
pub fn u128::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
11251128
pub fn u128::unpack(&self, n: usize) -> u8
11261129
pub fn u32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1130+
pub fn u32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
11271131
pub fn u32::unpack(&self, n: usize) -> u8
11281132
pub fn u64::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1133+
pub fn u64::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
11291134
pub fn u64::unpack(&self, n: usize) -> u8
11301135
pub fn u8::from(v: bech32::primitives::gf32::Fe32) -> u8
11311136
pub mod bech32

api/alloc-only.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,12 +810,14 @@ pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::new(hrp: &'hrp bech32::p
810810
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
811811
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::size_hint(&self) -> (usize, core::option::Option<usize>)
812812
pub fn bech32::primitives::checksum::PackedFe32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
813+
pub fn bech32::primitives::checksum::PackedFe32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
813814
pub fn bech32::primitives::checksum::PackedFe32::unpack(&self, n: usize) -> u8
814815
pub fn bech32::primitives::checksum::PackedNull::bitxor(self, bech32::primitives::checksum::PackedNull) -> bech32::primitives::checksum::PackedNull
815816
pub fn bech32::primitives::checksum::PackedNull::clone(&self) -> bech32::primitives::checksum::PackedNull
816817
pub fn bech32::primitives::checksum::PackedNull::eq(&self, other: &bech32::primitives::checksum::PackedNull) -> bool
817818
pub fn bech32::primitives::checksum::PackedNull::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
818819
pub fn bech32::primitives::checksum::PackedNull::mul_by_x_then_add(&mut self, usize, u8) -> u8
820+
pub fn bech32::primitives::checksum::PackedNull::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
819821
pub fn bech32::primitives::checksum::PackedNull::unpack(&self, usize) -> u8
820822
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::len(&self) -> usize
821823
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
@@ -1064,10 +1066,13 @@ pub fn bech32::segwit::encode_v0(hrp: bech32::primitives::hrp::Hrp, witness_prog
10641066
pub fn bech32::segwit::encode_v1(hrp: bech32::primitives::hrp::Hrp, witness_program: &[u8]) -> core::result::Result<alloc::string::String, bech32::segwit::EncodeError>
10651067
pub fn bech32::segwit::encoded_length(hrp: bech32::primitives::hrp::Hrp, _witness_version: bech32::primitives::gf32::Fe32, witness_program: &[u8]) -> core::result::Result<usize, bech32::primitives::decode::SegwitCodeLengthError>
10661068
pub fn u128::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1069+
pub fn u128::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
10671070
pub fn u128::unpack(&self, n: usize) -> u8
10681071
pub fn u32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1072+
pub fn u32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
10691073
pub fn u32::unpack(&self, n: usize) -> u8
10701074
pub fn u64::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1075+
pub fn u64::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
10711076
pub fn u64::unpack(&self, n: usize) -> u8
10721077
pub fn u8::from(v: bech32::primitives::gf32::Fe32) -> u8
10731078
pub mod bech32

api/no-features.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,12 +751,14 @@ pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::new(hrp: &'hrp bech32::p
751751
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
752752
pub fn bech32::primitives::checksum::HrpFe32Iter<'hrp>::size_hint(&self) -> (usize, core::option::Option<usize>)
753753
pub fn bech32::primitives::checksum::PackedFe32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
754+
pub fn bech32::primitives::checksum::PackedFe32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
754755
pub fn bech32::primitives::checksum::PackedFe32::unpack(&self, n: usize) -> u8
755756
pub fn bech32::primitives::checksum::PackedNull::bitxor(self, bech32::primitives::checksum::PackedNull) -> bech32::primitives::checksum::PackedNull
756757
pub fn bech32::primitives::checksum::PackedNull::clone(&self) -> bech32::primitives::checksum::PackedNull
757758
pub fn bech32::primitives::checksum::PackedNull::eq(&self, other: &bech32::primitives::checksum::PackedNull) -> bool
758759
pub fn bech32::primitives::checksum::PackedNull::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
759760
pub fn bech32::primitives::checksum::PackedNull::mul_by_x_then_add(&mut self, usize, u8) -> u8
761+
pub fn bech32::primitives::checksum::PackedNull::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
760762
pub fn bech32::primitives::checksum::PackedNull::unpack(&self, usize) -> u8
761763
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::len(&self) -> usize
762764
pub fn bech32::primitives::decode::AsciiToFe32Iter<'s>::next(&mut self) -> core::option::Option<bech32::primitives::gf32::Fe32>
@@ -989,10 +991,13 @@ pub fn bech32::segwit::encode_to_fmt_unchecked<W: core::fmt::Write>(fmt: &mut W,
989991
pub fn bech32::segwit::encode_upper_to_fmt_unchecked<W: core::fmt::Write>(fmt: &mut W, hrp: bech32::primitives::hrp::Hrp, witness_version: bech32::primitives::gf32::Fe32, witness_program: &[u8]) -> core::fmt::Result
990992
pub fn bech32::segwit::encoded_length(hrp: bech32::primitives::hrp::Hrp, _witness_version: bech32::primitives::gf32::Fe32, witness_program: &[u8]) -> core::result::Result<usize, bech32::primitives::decode::SegwitCodeLengthError>
991993
pub fn u128::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
994+
pub fn u128::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
992995
pub fn u128::unpack(&self, n: usize) -> u8
993996
pub fn u32::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
997+
pub fn u32::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
994998
pub fn u32::unpack(&self, n: usize) -> u8
995999
pub fn u64::mul_by_x_then_add(&mut self, degree: usize, add: u8) -> u8
1000+
pub fn u64::pack<I: core::iter::traits::iterator::Iterator<Item = u8>>(iter: I) -> Self
9961001
pub fn u64::unpack(&self, n: usize) -> u8
9971002
pub fn u8::from(v: bech32::primitives::gf32::Fe32) -> u8
9981003
pub mod bech32

src/primitives/checksum.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,18 @@ pub trait PackedFe32: Copy + PartialEq + Eq + ops::BitXor<Self, Output = Self> {
154154
/// The number of fe32s that can fit into the type; computed as floor(bitwidth / 5).
155155
const WIDTH: usize = mem::size_of::<Self>() * 8 / 5;
156156

157+
/// Takes an iterator of `u8`s (or [`Fe32`]s converted to `u8`s) and packs
158+
/// them into a [`Self`].
159+
///
160+
/// For sequences representing polynomials, the iterator should yield the
161+
/// coefficients in little-endian order, i.e. the 0th coefficien first.
162+
///
163+
/// # Panics
164+
///
165+
/// May panic if the iterator yields more items than can fit into the bit-packed
166+
/// type.
167+
fn pack<I: Iterator<Item = u8>>(iter: I) -> Self;
168+
157169
/// Extracts the coefficient of the x^n from the packed polynomial.
158170
fn unpack(&self, n: usize) -> u8;
159171

@@ -183,6 +195,14 @@ impl PackedFe32 for PackedNull {
183195
fn unpack(&self, _: usize) -> u8 { 0 }
184196
#[inline]
185197
fn mul_by_x_then_add(&mut self, _: usize, _: u8) -> u8 { 0 }
198+
199+
#[inline]
200+
fn pack<I: Iterator<Item = u8>>(mut iter: I) -> Self {
201+
if iter.next().is_some() {
202+
panic!("Cannot pack anything into a PackedNull");
203+
}
204+
Self
205+
}
186206
}
187207

188208
macro_rules! impl_packed_fe32 {
@@ -207,6 +227,18 @@ macro_rules! impl_packed_fe32 {
207227
*self |= Self::from(add);
208228
ret
209229
}
230+
231+
#[inline]
232+
fn pack<I: Iterator<Item = u8>>(iter: I) -> Self {
233+
let mut ret: Self = 0;
234+
for (n, elem) in iter.enumerate() {
235+
debug_assert!(elem < 32);
236+
debug_assert!(n < Self::WIDTH);
237+
ret <<= 5;
238+
ret |= Self::from(elem);
239+
}
240+
ret
241+
}
210242
}
211243
};
212244
}
@@ -276,3 +308,23 @@ impl<'hrp> Iterator for HrpFe32Iter<'hrp> {
276308
(min, max)
277309
}
278310
}
311+
312+
#[cfg(test)]
313+
mod tests {
314+
use super::*;
315+
316+
#[test]
317+
fn pack_unpack() {
318+
let packed = u128::pack([0, 0, 0, 1].iter().copied());
319+
assert_eq!(packed, 1);
320+
assert_eq!(packed.unpack(0), 1);
321+
assert_eq!(packed.unpack(3), 0);
322+
323+
let packed = u128::pack([1, 2, 3, 4].iter().copied());
324+
assert_eq!(packed, 0b00001_00010_00011_00100);
325+
assert_eq!(packed.unpack(0), 4);
326+
assert_eq!(packed.unpack(1), 3);
327+
assert_eq!(packed.unpack(2), 2);
328+
assert_eq!(packed.unpack(3), 1);
329+
}
330+
}

0 commit comments

Comments
 (0)