@@ -83,10 +83,50 @@ impl<const BITS: usize, const LIMBS: usize> fmt::Debug for Uint<BITS, LIMBS> {
8383}
8484
8585impl_fmt ! ( fmt:: Display ; base:: Decimal , "" ) ;
86- impl_fmt ! ( fmt:: Binary ; base:: Binary , "b" ) ;
87- impl_fmt ! ( fmt:: Octal ; base:: Octal , "o" ) ;
88- impl_fmt ! ( fmt:: LowerHex ; base:: Hexadecimal , "x" ) ;
89- impl_fmt ! ( fmt:: UpperHex ; base:: Hexadecimal , "X" ) ;
86+ macro_rules! impl_fmt_pow2 {
87+ ( $tr: path; $base: ty, $bits_per_digit: literal, $upper: literal) => {
88+ impl <const BITS : usize , const LIMBS : usize > $tr for Uint <BITS , LIMBS > {
89+ fn fmt( & self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
90+ if let Ok ( small) = u64 :: try_from( self ) {
91+ return <u64 as $tr>:: fmt( & small, f) ;
92+ }
93+ if let Ok ( small) = u128 :: try_from( self ) {
94+ return <u128 as $tr>:: fmt( & small, f) ;
95+ }
96+
97+ let alphabet: & [ u8 ; 16 ] = if $upper {
98+ b"0123456789ABCDEF"
99+ } else {
100+ b"0123456789abcdef"
101+ } ;
102+ let mask: u64 = ( 1 << $bits_per_digit) - 1 ;
103+
104+ let bit_len = self . bit_len( ) ;
105+ let total_digits = bit_len. div_ceil( $bits_per_digit) ;
106+
107+ let mut s = StackString :: <BITS >:: new( ) ;
108+ let mut i = total_digits;
109+ while i > 0 {
110+ i -= 1 ;
111+ let bit_offset = i * $bits_per_digit;
112+ let limb_idx = bit_offset / 64 ;
113+ let bit_idx = bit_offset % 64 ;
114+ let mut digit = ( self . limbs[ limb_idx] >> bit_idx) & mask;
115+ if bit_idx + $bits_per_digit > 64 && limb_idx + 1 < LIMBS {
116+ digit |= ( self . limbs[ limb_idx + 1 ] << ( 64 - bit_idx) ) & mask;
117+ }
118+ s. push_byte( alphabet[ digit as usize ] ) ;
119+ }
120+ f. pad_integral( true , <$base>:: PREFIX , s. as_str( ) )
121+ }
122+ }
123+ } ;
124+ }
125+
126+ impl_fmt_pow2 ! ( fmt:: Binary ; base:: Binary , 1 , false ) ;
127+ impl_fmt_pow2 ! ( fmt:: Octal ; base:: Octal , 3 , false ) ;
128+ impl_fmt_pow2 ! ( fmt:: LowerHex ; base:: Hexadecimal , 4 , false ) ;
129+ impl_fmt_pow2 ! ( fmt:: UpperHex ; base:: Hexadecimal , 4 , true ) ;
90130
91131/// A stack-allocated buffer that implements [`fmt::Write`].
92132pub ( crate ) struct StackString < const SIZE : usize > {
@@ -115,6 +155,13 @@ impl<const SIZE: usize> StackString<SIZE> {
115155 const fn as_bytes ( & self ) -> & [ u8 ] {
116156 unsafe { core:: slice:: from_raw_parts ( self . buf . as_ptr ( ) . cast ( ) , self . len ) }
117157 }
158+
159+ #[ inline]
160+ fn push_byte ( & mut self , b : u8 ) {
161+ debug_assert ! ( self . len < SIZE ) ;
162+ unsafe { self . buf . as_mut_ptr ( ) . add ( self . len ) . cast :: < u8 > ( ) . write ( b) } ;
163+ self . len += 1 ;
164+ }
118165}
119166
120167impl < const SIZE : usize > fmt:: Write for StackString < SIZE > {
0 commit comments