@@ -211,11 +211,46 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
211
211
8081828384858687888990919293949596979899";
212
212
213
213
macro_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
+
215
251
#[ 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] ;
219
254
let mut curr = buf. len( ) ;
220
255
let buf_ptr = MaybeUninit :: slice_as_mut_ptr( & mut buf) ;
221
256
let lut_ptr = DEC_DIGITS_LUT . as_ptr( ) ;
@@ -229,22 +264,26 @@ macro_rules! impl_Display {
229
264
// is safe to access.
230
265
unsafe {
231
266
// 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
+ }
248
287
}
249
288
250
289
// if we reach here numbers are <= 9999, so at most 4 chars long
@@ -258,6 +297,8 @@ macro_rules! impl_Display {
258
297
ptr:: copy_nonoverlapping( lut_ptr. add( d1) , buf_ptr. add( curr) , 2 ) ;
259
298
}
260
299
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.
261
302
// decode last 1 or 2 chars
262
303
if n < 10 {
263
304
curr -= 1 ;
@@ -276,11 +317,10 @@ macro_rules! impl_Display {
276
317
slice:: from_raw_parts( buf_ptr. add( curr) , buf. len( ) - curr) )
277
318
} ;
278
319
f. pad_integral( is_nonnegative, "" , buf_slice)
279
- }
320
+ } ) *
280
321
281
322
#[ 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 {
284
324
let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; 39 ] ;
285
325
let mut curr = buf. len( ) ;
286
326
let buf_ptr = MaybeUninit :: slice_as_mut_ptr( & mut buf) ;
@@ -309,21 +349,6 @@ macro_rules! impl_Display {
309
349
} ;
310
350
f. pad_integral( is_nonnegative, "" , buf_slice)
311
351
}
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
- } ) *
327
352
} ;
328
353
}
329
354
@@ -377,7 +402,6 @@ macro_rules! impl_Exp {
377
402
( n, exponent, exponent, added_precision)
378
403
} ;
379
404
380
- // 39 digits (worst case u128) + . = 40
381
405
// Since `curr` always decreases by the number of digits copied, this means
382
406
// that `curr >= 0`.
383
407
let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; 40 ] ;
@@ -472,7 +496,7 @@ macro_rules! impl_Exp {
472
496
let n = if is_nonnegative {
473
497
self . $conv_fn( )
474
498
} 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
476
500
( !self . $conv_fn( ) ) . wrapping_add( 1 )
477
501
} ;
478
502
$name( n, is_nonnegative, false , f)
@@ -487,7 +511,7 @@ macro_rules! impl_Exp {
487
511
let n = if is_nonnegative {
488
512
self . $conv_fn( )
489
513
} 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
491
515
( !self . $conv_fn( ) ) . wrapping_add( 1 )
492
516
} ;
493
517
$name( n, is_nonnegative, true , f)
@@ -502,8 +526,17 @@ macro_rules! impl_Exp {
502
526
mod imp {
503
527
use super :: * ;
504
528
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
507
540
) ;
508
541
impl_Exp ! (
509
542
i8 , u8 , i16 , u16 , i32 , u32 , i64 , u64 , usize , isize
@@ -514,8 +547,21 @@ mod imp {
514
547
#[ cfg( not( any( target_pointer_width = "64" , target_arch = "wasm32" ) ) ) ]
515
548
mod imp {
516
549
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) ;
550
+ impl_Display ! (
551
+ i8 => 3 as u8 in fmt_u8 => named fmt_i8,
552
+ u8 => 3 => named fmt_u8,
553
+ i16 => 5 as u16 in fmt_u16 => named fmt_i16,
554
+ u16 => 5 => named fmt_u16,
555
+ i32 => 10 as u32 in fmt_u32 => named fmt_i32,
556
+ u32 => 10 => named fmt_u32,
557
+ isize => 10 as usize in fmt_usize => named fmt_isize,
558
+ usize => 10 => named fmt_usize,
559
+ ; as u32 via to_u32 named fmt_u32) ;
560
+ impl_Display ! (
561
+ i64 => 20 as u64 in fmt_u64 => named fmt_i64,
562
+ u64 => 20 => named fmt_u64,
563
+ ; as u64 via to_u64 named fmt_u64) ;
564
+
519
565
impl_Exp ! ( i8 , u8 , i16 , u16 , i32 , u32 , isize , usize as u32 via to_u32 named exp_u32) ;
520
566
impl_Exp ! ( i64 , u64 as u64 via to_u64 named exp_u64) ;
521
567
}
@@ -622,7 +668,7 @@ impl fmt::Display for i128 {
622
668
let n = if is_nonnegative {
623
669
self . to_u128 ( )
624
670
} else {
625
- // convert the negative num to positive by summing 1 to it's 2 complement
671
+ // convert the negative num to positive by summing 1 to its 2s complement
626
672
( !self . to_u128 ( ) ) . wrapping_add ( 1 )
627
673
} ;
628
674
fmt_u128 ( n, is_nonnegative, f)
0 commit comments