@@ -7,62 +7,64 @@ use alloc::boxed::Box;
77/// Decoding errors for [`BoxedUint`].
88#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
99pub enum DecodeError {
10- /// Input is not a valid size .
10+ /// Input size is too small to fit in the given precision .
1111 InputSize ,
1212
13- /// Precision is not a multiple of [`Limb::BYTES`] .
13+ /// The deserialized number is larger than the given precision .
1414 Precision ,
1515}
1616
1717impl BoxedUint {
1818 /// Create a new [`BoxedUint`] from the provided big endian bytes.
1919 ///
2020 /// The `bits_precision` argument represents the precision of the resulting integer, which is
21- /// fixed as this type is not arbitrary-precision. It MUST be a multiple of the limb size, i.e.
22- /// [`Limb::BITS`], or otherwise this function will return [`DecodeError::Precision`].
21+ /// fixed as this type is not arbitrary-precision.
22+ /// The new [`BoxedUint`] will be created with `bits_precision`
23+ /// rounded up to a multiple of [`Limb::BITS`].
2324 ///
24- /// If the length of `bytes` (when interpreted as bits) is larger than `bits_precision`, this
25- /// function will return [`DecodeError::InputSize`].
25+ /// If the length of `bytes` is larger than `bits_precision` (rounded up to a multiple of 8)
26+ /// this function will return [`DecodeError::InputSize`].
27+ /// If the size of the decoded integer is larger than `bits_precision`,
28+ /// this function will return [`DecodeError::Precision`].
2629 pub fn from_be_slice ( bytes : & [ u8 ] , bits_precision : usize ) -> Result < Self , DecodeError > {
2730 if bytes. is_empty ( ) && bits_precision == 0 {
2831 return Ok ( Self :: zero ( ) ) ;
2932 }
3033
31- if bits_precision % Limb :: BITS != 0 {
32- return Err ( DecodeError :: Precision ) ;
33- }
34-
35- if bytes. len ( ) % Limb :: BYTES != 0 || bytes. len ( ) * 8 > bits_precision {
34+ if bytes. len ( ) > ( bits_precision + 7 ) / 8 {
3635 return Err ( DecodeError :: InputSize ) ;
3736 }
3837
3938 let mut ret = Self :: zero_with_precision ( bits_precision) ;
4039
41- for ( chunk, limb) in bytes. chunks ( Limb :: BYTES ) . rev ( ) . zip ( ret. limbs . iter_mut ( ) ) {
40+ for ( chunk, limb) in bytes. rchunks ( Limb :: BYTES ) . zip ( ret. limbs . iter_mut ( ) ) {
4241 * limb = Limb :: from_be_slice ( chunk) ;
4342 }
4443
44+ if bits_precision < ret. bits ( ) {
45+ return Err ( DecodeError :: Precision ) ;
46+ }
47+
4548 Ok ( ret)
4649 }
4750
4851 /// Create a new [`BoxedUint`] from the provided little endian bytes.
4952 ///
5053 /// The `bits_precision` argument represents the precision of the resulting integer, which is
51- /// fixed as this type is not arbitrary-precision. It MUST be a multiple of the limb size, i.e.
52- /// [`Limb::BITS`], or otherwise this function will return [`DecodeError::Precision`].
54+ /// fixed as this type is not arbitrary-precision.
55+ /// The new [`BoxedUint`] will be created with `bits_precision`
56+ /// rounded up to a multiple of [`Limb::BITS`].
5357 ///
54- /// If the length of `bytes` (when interpreted as bits) is larger than `bits_precision`, this
55- /// function will return [`DecodeError::InputSize`].
58+ /// If the length of `bytes` is larger than `bits_precision` (rounded up to a multiple of 8)
59+ /// this function will return [`DecodeError::InputSize`].
60+ /// If the size of the decoded integer is larger than `bits_precision`,
61+ /// this function will return [`DecodeError::Precision`].
5662 pub fn from_le_slice ( bytes : & [ u8 ] , bits_precision : usize ) -> Result < Self , DecodeError > {
5763 if bytes. is_empty ( ) && bits_precision == 0 {
5864 return Ok ( Self :: zero ( ) ) ;
5965 }
6066
61- if bits_precision % Limb :: BITS != 0 {
62- return Err ( DecodeError :: Precision ) ;
63- }
64-
65- if bytes. len ( ) % Limb :: BYTES != 0 || bytes. len ( ) * 8 > bits_precision {
67+ if bytes. len ( ) > ( bits_precision + 7 ) / 8 {
6668 return Err ( DecodeError :: InputSize ) ;
6769 }
6870
@@ -72,6 +74,10 @@ impl BoxedUint {
7274 * limb = Limb :: from_le_slice ( chunk) ;
7375 }
7476
77+ if bits_precision < ret. bits ( ) {
78+ return Err ( DecodeError :: Precision ) ;
79+ }
80+
7581 Ok ( ret)
7682 }
7783
@@ -173,19 +179,39 @@ mod tests {
173179 }
174180
175181 #[ test]
182+ #[ cfg( target_pointer_width = "32" ) ]
176183 fn from_be_slice_not_word_sized ( ) {
177- let bytes = hex ! ( "00112233445566778899aabbccddee" ) ;
184+ let bytes = hex ! ( "112233445566778899aabbccddeeff" ) ;
185+ let n = BoxedUint :: from_be_slice ( & bytes, 127 ) . unwrap ( ) ;
178186 assert_eq ! (
179- BoxedUint :: from_be_slice( & bytes, 128 ) ,
180- Err ( DecodeError :: InputSize )
187+ n. as_limbs( ) ,
188+ & [
189+ Limb ( 0xccddeeff ) ,
190+ Limb ( 0x8899aabb ) ,
191+ Limb ( 0x44556677 ) ,
192+ Limb ( 0x00112233 )
193+ ]
181194 ) ;
195+ assert_eq ! ( n. bits_precision( ) , 128 ) ;
182196 }
183197
184198 #[ test]
185- fn from_be_slice_bad_precision ( ) {
186- let bytes = hex ! ( "00112233445566778899aabbccddeeff" ) ;
199+ #[ cfg( target_pointer_width = "64" ) ]
200+ fn from_be_slice_not_word_sized ( ) {
201+ let bytes = hex ! ( "112233445566778899aabbccddeeff" ) ;
202+ let n = BoxedUint :: from_be_slice ( & bytes, 127 ) . unwrap ( ) ;
187203 assert_eq ! (
188- BoxedUint :: from_be_slice( & bytes, 127 ) ,
204+ n. as_limbs( ) ,
205+ & [ Limb ( 0x8899aabbccddeeff ) , Limb ( 0x0011223344556677 ) ]
206+ ) ;
207+ assert_eq ! ( n. bits_precision( ) , 128 ) ;
208+ }
209+
210+ #[ test]
211+ fn from_be_slice_non_multiple_precision ( ) {
212+ let bytes = hex ! ( "0f112233445566778899aabbccddeeff" ) ;
213+ assert_eq ! (
214+ BoxedUint :: from_be_slice( & bytes, 121 ) ,
189215 Err ( DecodeError :: Precision )
190216 ) ;
191217 }
@@ -246,19 +272,39 @@ mod tests {
246272 }
247273
248274 #[ test]
275+ #[ cfg( target_pointer_width = "32" ) ]
249276 fn from_le_slice_not_word_sized ( ) {
250277 let bytes = hex ! ( "ffeeddccbbaa998877665544332211" ) ;
278+ let n = BoxedUint :: from_le_slice ( & bytes, 127 ) . unwrap ( ) ;
251279 assert_eq ! (
252- BoxedUint :: from_be_slice( & bytes, 128 ) ,
253- Err ( DecodeError :: InputSize )
280+ n. as_limbs( ) ,
281+ & [
282+ Limb ( 0xbbccddee ) ,
283+ Limb ( 0x778899aa ) ,
284+ Limb ( 0x33445566 ) ,
285+ Limb ( 0x00001122 )
286+ ]
254287 ) ;
288+ assert_eq ! ( n. bits_precision( ) , 128 ) ;
255289 }
256290
257291 #[ test]
258- fn from_le_slice_bad_precision ( ) {
259- let bytes = hex ! ( "ffeeddccbbaa99887766554433221100" ) ;
292+ #[ cfg( target_pointer_width = "64" ) ]
293+ fn from_le_slice_not_word_sized ( ) {
294+ let bytes = hex ! ( "ffeeddccbbaa998877665544332211" ) ;
295+ let n = BoxedUint :: from_le_slice ( & bytes, 127 ) . unwrap ( ) ;
296+ assert_eq ! (
297+ n. as_limbs( ) ,
298+ & [ Limb ( 0x8899aabbccddeeff ) , Limb ( 0x0011223344556677 ) ]
299+ ) ;
300+ assert_eq ! ( n. bits_precision( ) , 128 ) ;
301+ }
302+
303+ #[ test]
304+ fn from_le_slice_non_multiple_precision ( ) {
305+ let bytes = hex ! ( "ffeeddccbbaa998877665544332211f0" ) ;
260306 assert_eq ! (
261- BoxedUint :: from_le_slice( & bytes, 127 ) ,
307+ BoxedUint :: from_le_slice( & bytes, 121 ) ,
262308 Err ( DecodeError :: Precision )
263309 ) ;
264310 }
0 commit comments