@@ -211,11 +211,46 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
211211 8081828384858687888990919293949596979899";
212212
213213macro_rules! impl_Display {
214- ( $( $t: ident) ,* as $u: ident via $conv_fn: ident named $name: ident) => {
214+ ( $( $t: ident => $size: literal $( as $positive: ident in $other: ident) ? => named $name: ident, ) * ; as $u: ident via $conv_fn: ident named $gen_name: ident) => {
215+
216+ $(
217+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
218+ impl fmt:: Display for $t {
219+ fn fmt( & self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
220+ // If it's a signed integer.
221+ $(
222+ let is_nonnegative = * self >= 0 ;
223+
224+ #[ cfg( not( feature = "optimize_for_size" ) ) ]
225+ {
226+ if !is_nonnegative {
227+ // convert the negative num to positive by summing 1 to its 2s complement
228+ return $other( ( !self as $positive) . wrapping_add( 1 ) , false , f) ;
229+ }
230+ }
231+ #[ cfg( feature = "optimize_for_size" ) ]
232+ {
233+ if !is_nonnegative {
234+ // convert the negative num to positive by summing 1 to its 2s complement
235+ return $other( ( !self . $conv_fn( ) ) . wrapping_add( 1 ) , false , f) ;
236+ }
237+ }
238+ ) ?
239+ // If it's a positive integer.
240+ #[ cfg( not( feature = "optimize_for_size" ) ) ]
241+ {
242+ $name( * self , true , f)
243+ }
244+ #[ cfg( feature = "optimize_for_size" ) ]
245+ {
246+ $gen_name( * self , true , f)
247+ }
248+ }
249+ }
250+
215251 #[ cfg( not( feature = "optimize_for_size" ) ) ]
216- fn $name( mut n: $u, is_nonnegative: bool , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
217- // 2^128 is about 3*10^38, so 39 gives an extra byte of space
218- let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; 39 ] ;
252+ fn $name( mut n: $t, is_nonnegative: bool , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
253+ let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; $size] ;
219254 let mut curr = buf. len( ) ;
220255 let buf_ptr = MaybeUninit :: slice_as_mut_ptr( & mut buf) ;
221256 let lut_ptr = DEC_DIGITS_LUT . as_ptr( ) ;
@@ -229,22 +264,26 @@ macro_rules! impl_Display {
229264 // is safe to access.
230265 unsafe {
231266 // need at least 16 bits for the 4-characters-at-a-time to work.
232- assert!( crate :: mem:: size_of:: <$u>( ) >= 2 ) ;
233-
234- // eagerly decode 4 characters at a time
235- while n >= 10000 {
236- let rem = ( n % 10000 ) as usize ;
237- n /= 10000 ;
238-
239- let d1 = ( rem / 100 ) << 1 ;
240- let d2 = ( rem % 100 ) << 1 ;
241- curr -= 4 ;
242-
243- // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
244- // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
245- // which is `10^40 > 2^128 > n`.
246- ptr:: copy_nonoverlapping( lut_ptr. add( d1) , buf_ptr. add( curr) , 2 ) ;
247- ptr:: copy_nonoverlapping( lut_ptr. add( d2) , buf_ptr. add( curr + 2 ) , 2 ) ;
267+ #[ allow( overflowing_literals) ]
268+ #[ allow( unused_comparisons) ]
269+ // This block should be removed for smaller types at compile time so it
270+ // should be ok.
271+ if core:: mem:: size_of:: <$t>( ) >= 2 {
272+ // eagerly decode 4 characters at a time
273+ while n >= 10000 {
274+ let rem = ( n % 10000 ) as usize ;
275+ n /= 10000 ;
276+
277+ let d1 = ( rem / 100 ) << 1 ;
278+ let d2 = ( rem % 100 ) << 1 ;
279+ curr -= 4 ;
280+
281+ // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
282+ // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
283+ // which is `10^40 > 2^128 > n`.
284+ ptr:: copy_nonoverlapping( lut_ptr. add( d1 as usize ) , buf_ptr. add( curr) , 2 ) ;
285+ ptr:: copy_nonoverlapping( lut_ptr. add( d2 as usize ) , buf_ptr. add( curr + 2 ) , 2 ) ;
286+ }
248287 }
249288
250289 // if we reach here numbers are <= 9999, so at most 4 chars long
@@ -258,6 +297,8 @@ macro_rules! impl_Display {
258297 ptr:: copy_nonoverlapping( lut_ptr. add( d1) , buf_ptr. add( curr) , 2 ) ;
259298 }
260299
300+ // if we reach here numbers are <= 100, so at most 2 chars long
301+ // The biggest it can be is 99, and 99 << 1 == 198, so a `u8` is enough.
261302 // decode last 1 or 2 chars
262303 if n < 10 {
263304 curr -= 1 ;
@@ -276,11 +317,10 @@ macro_rules! impl_Display {
276317 slice:: from_raw_parts( buf_ptr. add( curr) , buf. len( ) - curr) )
277318 } ;
278319 f. pad_integral( is_nonnegative, "" , buf_slice)
279- }
320+ } ) *
280321
281322 #[ cfg( feature = "optimize_for_size" ) ]
282- fn $name( mut n: $u, is_nonnegative: bool , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
283- // 2^128 is about 3*10^38, so 39 gives an extra byte of space
323+ fn $gen_name( mut n: $u, is_nonnegative: bool , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
284324 let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; 39 ] ;
285325 let mut curr = buf. len( ) ;
286326 let buf_ptr = MaybeUninit :: slice_as_mut_ptr( & mut buf) ;
@@ -309,27 +349,12 @@ macro_rules! impl_Display {
309349 } ;
310350 f. pad_integral( is_nonnegative, "" , buf_slice)
311351 }
312-
313- $( #[ stable( feature = "rust1" , since = "1.0.0" ) ]
314- impl fmt:: Display for $t {
315- #[ allow( unused_comparisons) ]
316- fn fmt( & self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
317- let is_nonnegative = * self >= 0 ;
318- let n = if is_nonnegative {
319- self . $conv_fn( )
320- } else {
321- // convert the negative num to positive by summing 1 to it's 2 complement
322- ( !self . $conv_fn( ) ) . wrapping_add( 1 )
323- } ;
324- $name( n, is_nonnegative, f)
325- }
326- } ) *
327352 } ;
328353}
329354
330355macro_rules! impl_Exp {
331- ( $( $t: ident) , * as $u: ident via $conv_fn: ident named $name: ident) => {
332- fn $name(
356+ ( $( $t: ident => $size : literal , ) * ; as $u: ident via $conv_fn: ident named $name: ident) => {
357+ fn $name< const SIZE : usize > (
333358 mut n: $u,
334359 is_nonnegative: bool ,
335360 upper: bool ,
@@ -377,10 +402,9 @@ macro_rules! impl_Exp {
377402 ( n, exponent, exponent, added_precision)
378403 } ;
379404
380- // 39 digits (worst case u128) + . = 40
381405 // Since `curr` always decreases by the number of digits copied, this means
382406 // that `curr >= 0`.
383- let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; 40 ] ;
407+ let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; SIZE ] ;
384408 let mut curr = buf. len( ) ; //index for buf
385409 let buf_ptr = MaybeUninit :: slice_as_mut_ptr( & mut buf) ;
386410 let lut_ptr = DEC_DIGITS_LUT . as_ptr( ) ;
@@ -472,10 +496,10 @@ macro_rules! impl_Exp {
472496 let n = if is_nonnegative {
473497 self . $conv_fn( )
474498 } else {
475- // convert the negative num to positive by summing 1 to it's 2 complement
499+ // convert the negative num to positive by summing 1 to its 2s complement
476500 ( !self . $conv_fn( ) ) . wrapping_add( 1 )
477501 } ;
478- $name( n, is_nonnegative, false , f)
502+ $name:: <$size> ( n, is_nonnegative, false , f)
479503 }
480504 } ) *
481505 $(
@@ -487,10 +511,10 @@ macro_rules! impl_Exp {
487511 let n = if is_nonnegative {
488512 self . $conv_fn( )
489513 } else {
490- // convert the negative num to positive by summing 1 to it's 2 complement
514+ // convert the negative num to positive by summing 1 to its 2s complement
491515 ( !self . $conv_fn( ) ) . wrapping_add( 1 )
492516 } ;
493- $name( n, is_nonnegative, true , f)
517+ $name:: <$size> ( n, is_nonnegative, true , f)
494518 }
495519 } ) *
496520 } ;
@@ -502,24 +526,70 @@ macro_rules! impl_Exp {
502526mod imp {
503527 use super :: * ;
504528 impl_Display ! (
505- i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , usize , isize
506- as u64 via to_u64 named fmt_u64
529+ i8 => 3 as u8 in fmt_u8 => named fmt_i8,
530+ u8 => 3 => named fmt_u8,
531+ i16 => 5 as u16 in fmt_u16 => named fmt_i16,
532+ u16 => 5 => named fmt_u16,
533+ i32 => 10 as u32 in fmt_u32 => named fmt_i32,
534+ u32 => 10 => named fmt_u32,
535+ i64 => 20 as u64 in fmt_u64 => named fmt_i64,
536+ u64 => 20 => named fmt_u64,
537+ isize => 20 as usize in fmt_usize => named fmt_isize,
538+ usize => 20 => named fmt_usize,
539+ ; as u64 via to_u64 named fmt_u64
507540 ) ;
508541 impl_Exp ! (
509- i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , usize , isize
510- as u64 via to_u64 named exp_u64
542+ i8 => 5 ,
543+ u8 => 4 ,
544+ i16 => 7 ,
545+ u16 => 6 ,
546+ i32 => 11 ,
547+ u32 => 10 ,
548+ i64 => 21 ,
549+ u64 => 21 ,
550+ isize => 21 ,
551+ usize => 21 ,
552+ ; as u64 via to_u64 named exp_u64
511553 ) ;
512554}
513555
514556#[ cfg( not( any( target_pointer_width = "64" , target_arch = "wasm32" ) ) ) ]
515557mod imp {
516558 use super :: * ;
517- impl_Display ! ( i8 , u8 , i16 , u16 , i32 , u32 , isize , usize as u32 via to_u32 named fmt_u32) ;
518- impl_Display ! ( i64 , u64 as u64 via to_u64 named fmt_u64) ;
519- impl_Exp ! ( i8 , u8 , i16 , u16 , i32 , u32 , isize , usize as u32 via to_u32 named exp_u32) ;
520- impl_Exp ! ( i64 , u64 as u64 via to_u64 named exp_u64) ;
559+ impl_Display ! (
560+ i8 => 3 as u8 in fmt_u8 => named fmt_i8,
561+ u8 => 3 => named fmt_u8,
562+ i16 => 5 as u16 in fmt_u16 => named fmt_i16,
563+ u16 => 5 => named fmt_u16,
564+ i32 => 10 as u32 in fmt_u32 => named fmt_i32,
565+ u32 => 10 => named fmt_u32,
566+ isize => 10 as usize in fmt_usize => named fmt_isize,
567+ usize => 10 => named fmt_usize,
568+ ; as u32 via to_u32 named fmt_u32) ;
569+ impl_Display ! (
570+ i64 => 20 as u64 in fmt_u64 => named fmt_i64,
571+ u64 => 20 => named fmt_u64,
572+ ; as u64 via to_u64 named fmt_u64) ;
573+
574+ impl_Exp ! (
575+ i8 => 5 ,
576+ u8 => 4 ,
577+ i16 => 7 ,
578+ u16 => 6 ,
579+ i32 => 11 ,
580+ u32 => 10 ,
581+ isize => 11 ,
582+ usize => 10 ,
583+ ; as u32 via to_u32 named exp_u32) ;
584+ impl_Exp ! (
585+ i64 => 21 ,
586+ u64 => 21 ,
587+ ; as u64 via to_u64 named exp_u64) ;
521588}
522- impl_Exp ! ( i128 , u128 as u128 via to_u128 named exp_u128) ;
589+ impl_Exp ! (
590+ i128 => 40 ,
591+ u128 => 39 ,
592+ ; as u128 via to_u128 named exp_u128) ;
523593
524594/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
525595fn parse_u64_into < const N : usize > ( mut n : u64 , buf : & mut [ MaybeUninit < u8 > ; N ] , curr : & mut usize ) {
@@ -622,7 +692,7 @@ impl fmt::Display for i128 {
622692 let n = if is_nonnegative {
623693 self . to_u128 ( )
624694 } else {
625- // convert the negative num to positive by summing 1 to it's 2 complement
695+ // convert the negative num to positive by summing 1 to its 2s complement
626696 ( !self . to_u128 ( ) ) . wrapping_add ( 1 )
627697 } ;
628698 fmt_u128 ( n, is_nonnegative, f)
0 commit comments