@@ -10,14 +10,11 @@ mod rlp;
1010use alloc:: { string:: String , vec:: Vec } ;
1111
1212use super :: Uint ;
13- use crate :: { DecodeError , Limb , Word } ;
13+ use crate :: { DecodeError , Encoding , Limb , Word } ;
1414
1515#[ cfg( feature = "alloc" ) ]
1616use crate :: { ConstChoice , NonZero , Reciprocal , UintRef , WideWord } ;
1717
18- #[ cfg( feature = "hybrid-array" ) ]
19- use crate :: Encoding ;
20-
2118#[ cfg( feature = "alloc" ) ]
2219const RADIX_ENCODING_LIMBS_LARGE : usize = 16 ;
2320#[ cfg( feature = "alloc" ) ]
@@ -204,58 +201,123 @@ impl<const LIMBS: usize> Uint<LIMBS> {
204201 let mut buf = * self ;
205202 radix_encode_limbs_mut_to_string ( radix, buf. as_mut_uint_ref ( ) )
206203 }
207- }
208204
209- /// Encode a [`Uint`] to a big endian byte array of the given size.
210- pub ( crate ) const fn uint_to_be_bytes < const LIMBS : usize , const BYTES : usize > (
211- uint : & Uint < LIMBS > ,
212- ) -> [ u8 ; BYTES ] {
213- if BYTES != LIMBS * Limb :: BYTES {
214- panic ! ( "BYTES != LIMBS * Limb::BYTES" ) ;
205+ /// Serialize as big endian bytes.
206+ pub const fn to_be_bytes ( & self ) -> EncodedUint < LIMBS > {
207+ EncodedUint :: as_be_bytes ( self )
215208 }
216209
217- let mut ret = [ 0u8 ; BYTES ] ;
218- let mut i = 0 ;
210+ /// Serialize as little endian bytes.
211+ pub const fn to_le_bytes ( & self ) -> EncodedUint < LIMBS > {
212+ EncodedUint :: as_le_bytes ( self )
213+ }
214+ }
219215
220- while i < LIMBS {
221- let limb_bytes = uint . limbs [ LIMBS - i - 1 ] . 0 . to_be_bytes ( ) ;
222- let mut j = 0 ;
216+ /// [`Uint`] encoded as bytes.
217+ # [ derive ( Default , Copy , Clone , Debug , PartialEq , Eq ) ]
218+ pub struct EncodedUint < const LIMBS : usize > ( Uint < LIMBS > ) ;
223219
224- while j < Limb :: BYTES {
225- ret[ i * Limb :: BYTES + j] = limb_bytes[ j] ;
226- j += 1 ;
220+ impl < const LIMBS : usize > EncodedUint < LIMBS > {
221+ const fn as_le_bytes ( value : & Uint < LIMBS > ) -> Self {
222+ let mut buffer = * value;
223+ let mut i = 0 ;
224+
225+ while i < LIMBS {
226+ let src_bytes = & value. limbs [ i] . 0 . to_le_bytes ( ) ;
227+
228+ // We could cast the whole `buffer.limbs` to bytes at once,
229+ // but IndexMut does not work in const context.
230+ let dst_bytes: & mut [ u8 ] =
231+ bytemuck:: must_cast_slice_mut ( core:: slice:: from_mut ( & mut buffer. limbs [ i] . 0 ) ) ;
232+
233+ // `copy_from_slice` can be used here when MSRV moves past 1.87
234+ let mut j = 0 ;
235+ while j < Limb :: BYTES {
236+ dst_bytes[ j] = src_bytes[ j] ;
237+ j += 1 ;
238+ }
239+
240+ i += 1 ;
227241 }
242+ Self ( buffer)
243+ }
244+
245+ const fn as_be_bytes ( value : & Uint < LIMBS > ) -> Self {
246+ let mut buffer = * value;
247+ let mut i = 0 ;
248+ while i < LIMBS {
249+ let src_bytes = & value. limbs [ i] . 0 . to_be_bytes ( ) ;
250+
251+ // We could cast the whole `buffer.limbs` to bytes at once,
252+ // but IndexMut does not work in const context.
253+ let dst_bytes: & mut [ u8 ] = bytemuck:: must_cast_slice_mut ( core:: slice:: from_mut (
254+ & mut buffer. limbs [ LIMBS - 1 - i] . 0 ,
255+ ) ) ;
256+
257+ // `copy_from_slice` can be used here when MSRV moves past 1.87
258+ let mut j = 0 ;
259+ while j < Limb :: BYTES {
260+ dst_bytes[ j] = src_bytes[ j] ;
261+ j += 1 ;
262+ }
228263
229- i += 1 ;
264+ i += 1 ;
265+ }
266+ Self ( buffer)
230267 }
268+ }
231269
232- ret
270+ impl < const LIMBS : usize > AsRef < [ u8 ] > for EncodedUint < LIMBS > {
271+ fn as_ref ( & self ) -> & [ u8 ] {
272+ bytemuck:: must_cast_slice ( & self . 0 . limbs )
273+ }
233274}
234275
235- /// Encode a [`Uint`] to a little endian byte array of the given size.
236- pub ( crate ) const fn uint_to_le_bytes < const LIMBS : usize , const BYTES : usize > (
237- uint : & Uint < LIMBS > ,
238- ) -> [ u8 ; BYTES ] {
239- if BYTES != LIMBS * Limb :: BYTES {
240- panic ! ( "BYTES != LIMBS * Limb::BYTES" ) ;
276+ impl < const LIMBS : usize > AsMut < [ u8 ] > for EncodedUint < LIMBS > {
277+ fn as_mut ( & mut self ) -> & mut [ u8 ] {
278+ bytemuck:: must_cast_slice_mut ( & mut self . 0 . limbs )
241279 }
280+ }
242281
243- let mut ret = [ 0u8 ; BYTES ] ;
244- let mut i = 0 ;
282+ /// Returned if an object cannot be instantiated from the given byte slice.
283+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
284+ pub struct TryFromSliceError ;
245285
246- while i < LIMBS {
247- let limb_bytes = uint. limbs [ i] . 0 . to_le_bytes ( ) ;
248- let mut j = 0 ;
286+ impl < ' a , const LIMBS : usize > TryFrom < & ' a [ u8 ] > for EncodedUint < LIMBS > {
287+ type Error = TryFromSliceError ;
249288
250- while j < Limb :: BYTES {
251- ret [ i * Limb :: BYTES + j ] = limb_bytes [ j ] ;
252- j += 1 ;
289+ fn try_from ( bytes : & ' a [ u8 ] ) -> Result < Self , Self :: Error > {
290+ if bytes . len ( ) != Uint :: < LIMBS > :: BYTES {
291+ return Err ( TryFromSliceError ) ;
253292 }
293+ let mut result = Self ( Uint :: < LIMBS > :: ZERO ) ;
294+ result. as_mut ( ) . copy_from_slice ( bytes) ;
295+ Ok ( result)
296+ }
297+ }
298+
299+ impl < const LIMBS : usize > Encoding for Uint < LIMBS > {
300+ type Repr = EncodedUint < LIMBS > ;
301+
302+ #[ inline]
303+ fn from_be_bytes ( bytes : Self :: Repr ) -> Self {
304+ Self :: from_be_slice ( bytes. as_ref ( ) )
305+ }
254306
255- i += 1 ;
307+ #[ inline]
308+ fn from_le_bytes ( bytes : Self :: Repr ) -> Self {
309+ Self :: from_le_slice ( bytes. as_ref ( ) )
256310 }
257311
258- ret
312+ #[ inline]
313+ fn to_be_bytes ( & self ) -> Self :: Repr {
314+ self . to_be_bytes ( )
315+ }
316+
317+ #[ inline]
318+ fn to_le_bytes ( & self ) -> Self :: Repr {
319+ self . to_le_bytes ( )
320+ }
259321}
260322
261323/// Decode a single nibble of upper or lower hex
@@ -1057,7 +1119,7 @@ mod tests {
10571119 let n = UintEx :: from_be_hex ( "0011223344556677" ) ;
10581120
10591121 let bytes = n. to_be_bytes ( ) ;
1060- assert_eq ! ( bytes, hex!( "0011223344556677" ) ) ;
1122+ assert_eq ! ( bytes. as_ref ( ) , hex!( "0011223344556677" ) ) ;
10611123
10621124 #[ cfg( feature = "der" ) ]
10631125 assert_eq ! ( super :: der:: count_der_be_bytes( & n. limbs) , 7 ) ;
@@ -1069,7 +1131,7 @@ mod tests {
10691131 let n = UintEx :: from_be_hex ( "00112233445566778899aabbccddeeff" ) ;
10701132
10711133 let bytes = n. to_be_bytes ( ) ;
1072- assert_eq ! ( bytes, hex!( "00112233445566778899aabbccddeeff" ) ) ;
1134+ assert_eq ! ( bytes. as_ref ( ) , hex!( "00112233445566778899aabbccddeeff" ) ) ;
10731135
10741136 #[ cfg( feature = "der" ) ]
10751137 assert_eq ! ( super :: der:: count_der_be_bytes( & n. limbs) , 15 ) ;
0 commit comments