@@ -208,11 +208,46 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
208
208
8081828384858687888990919293949596979899";
209
209
210
210
macro_rules! impl_Display {
211
- ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
211
+ ($($t:ident => $size:literal $(as $positive:ident in $other:ident)? => named $name:ident,)* ; as $u:ident via $conv_fn:ident named $gen_name:ident) => {
212
+
213
+ $(
214
+ #[stable(feature = "rust1", since = "1.0.0")]
215
+ impl fmt::Display for $t {
216
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217
+ // If it's a signed integer.
218
+ $(
219
+ let is_nonnegative = *self >= 0;
220
+
221
+ #[cfg(not(feature = "optimize_for_size"))]
222
+ {
223
+ if !is_nonnegative {
224
+ // convert the negative num to positive by summing 1 to its 2s complement
225
+ return $other((!self as $positive).wrapping_add(1), false, f);
226
+ }
227
+ }
228
+ #[cfg(feature = "optimize_for_size")]
229
+ {
230
+ if !is_nonnegative {
231
+ // convert the negative num to positive by summing 1 to its 2s complement
232
+ return $other((!self.$conv_fn()).wrapping_add(1), false, f);
233
+ }
234
+ }
235
+ )?
236
+ // If it's a positive integer.
237
+ #[cfg(not(feature = "optimize_for_size"))]
238
+ {
239
+ $name(*self, true, f)
240
+ }
241
+ #[cfg(feature = "optimize_for_size")]
242
+ {
243
+ $gen_name(*self, true, f)
244
+ }
245
+ }
246
+ }
247
+
212
248
#[cfg(not(feature = "optimize_for_size"))]
213
- fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214
- // 2^128 is about 3*10^38, so 39 gives an extra byte of space
215
- let mut buf = [MaybeUninit::<u8>::uninit(); 39];
249
+ fn $name(mut n: $t, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250
+ let mut buf = [MaybeUninit::<u8>::uninit(); $size];
216
251
let mut curr = buf.len();
217
252
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
218
253
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
@@ -226,22 +261,26 @@ macro_rules! impl_Display {
226
261
// is safe to access.
227
262
unsafe {
228
263
// need at least 16 bits for the 4-characters-at-a-time to work.
229
- assert!(crate::mem::size_of::<$u>() >= 2);
230
-
231
- // eagerly decode 4 characters at a time
232
- while n >= 10000 {
233
- let rem = (n % 10000) as usize;
234
- n /= 10000;
235
-
236
- let d1 = (rem / 100) << 1;
237
- let d2 = (rem % 100) << 1;
238
- curr -= 4;
239
-
240
- // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
241
- // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
242
- // which is `10^40 > 2^128 > n`.
243
- ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
244
- ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
264
+ #[allow(overflowing_literals)]
265
+ #[allow(unused_comparisons)]
266
+ // This block will be removed for smaller types at compile time and in the worst
267
+ // case, it will prevent to have the `10000` literal to overflow for `i8` and `u8`.
268
+ if core::mem::size_of::<$t>() >= 2 {
269
+ // eagerly decode 4 characters at a time
270
+ while n >= 10000 {
271
+ let rem = (n % 10000) as usize;
272
+ n /= 10000;
273
+
274
+ let d1 = (rem / 100) << 1;
275
+ let d2 = (rem % 100) << 1;
276
+ curr -= 4;
277
+
278
+ // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
279
+ // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
280
+ // which is `10^40 > 2^128 > n`.
281
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(curr), 2);
282
+ ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(curr + 2), 2);
283
+ }
245
284
}
246
285
247
286
// if we reach here numbers are <= 9999, so at most 4 chars long
@@ -255,6 +294,8 @@ macro_rules! impl_Display {
255
294
ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
256
295
}
257
296
297
+ // if we reach here numbers are <= 100, so at most 2 chars long
298
+ // The biggest it can be is 99, and 99 << 1 == 198, so a `u8` is enough.
258
299
// decode last 1 or 2 chars
259
300
if n < 10 {
260
301
curr -= 1;
@@ -273,11 +314,10 @@ macro_rules! impl_Display {
273
314
slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
274
315
};
275
316
f.pad_integral(is_nonnegative, "", buf_slice)
276
- }
317
+ })*
277
318
278
319
#[cfg(feature = "optimize_for_size")]
279
- fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280
- // 2^128 is about 3*10^38, so 39 gives an extra byte of space
320
+ fn $gen_name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281
321
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
282
322
let mut curr = buf.len();
283
323
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
@@ -306,21 +346,6 @@ macro_rules! impl_Display {
306
346
};
307
347
f.pad_integral(is_nonnegative, "", buf_slice)
308
348
}
309
-
310
- $(#[stable(feature = "rust1", since = "1.0.0")]
311
- impl fmt::Display for $t {
312
- #[allow(unused_comparisons)]
313
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314
- let is_nonnegative = *self >= 0;
315
- let n = if is_nonnegative {
316
- self.$conv_fn()
317
- } else {
318
- // convert the negative num to positive by summing 1 to it's 2 complement
319
- (!self.$conv_fn()).wrapping_add(1)
320
- };
321
- $name(n, is_nonnegative, f)
322
- }
323
- })*
324
349
};
325
350
}
326
351
@@ -374,7 +399,6 @@ macro_rules! impl_Exp {
374
399
(n, exponent, exponent, added_precision)
375
400
};
376
401
377
- // 39 digits (worst case u128) + . = 40
378
402
// Since `curr` always decreases by the number of digits copied, this means
379
403
// that `curr >= 0`.
380
404
let mut buf = [MaybeUninit::<u8>::uninit(); 40];
@@ -469,7 +493,7 @@ macro_rules! impl_Exp {
469
493
let n = if is_nonnegative {
470
494
self.$conv_fn()
471
495
} else {
472
- // convert the negative num to positive by summing 1 to it's 2 complement
496
+ // convert the negative num to positive by summing 1 to its 2s complement
473
497
(!self.$conv_fn()).wrapping_add(1)
474
498
};
475
499
$name(n, is_nonnegative, false, f)
@@ -484,7 +508,7 @@ macro_rules! impl_Exp {
484
508
let n = if is_nonnegative {
485
509
self.$conv_fn()
486
510
} else {
487
- // convert the negative num to positive by summing 1 to it's 2 complement
511
+ // convert the negative num to positive by summing 1 to its 2s complement
488
512
(!self.$conv_fn()).wrapping_add(1)
489
513
};
490
514
$name(n, is_nonnegative, true, f)
@@ -499,8 +523,17 @@ macro_rules! impl_Exp {
499
523
mod imp {
500
524
use super::*;
501
525
impl_Display!(
502
- i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
503
- as u64 via to_u64 named fmt_u64
526
+ i8 => 3 as u8 in fmt_u8 => named fmt_i8,
527
+ u8 => 3 => named fmt_u8,
528
+ i16 => 5 as u16 in fmt_u16 => named fmt_i16,
529
+ u16 => 5 => named fmt_u16,
530
+ i32 => 10 as u32 in fmt_u32 => named fmt_i32,
531
+ u32 => 10 => named fmt_u32,
532
+ i64 => 19 as u64 in fmt_u64 => named fmt_i64,
533
+ u64 => 20 => named fmt_u64,
534
+ isize => 19 as usize in fmt_usize => named fmt_isize,
535
+ usize => 20 => named fmt_usize,
536
+ ; as u64 via to_u64 named fmt_u64
504
537
);
505
538
impl_Exp!(
506
539
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
@@ -511,8 +544,21 @@ mod imp {
511
544
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
512
545
mod imp {
513
546
use super::*;
514
- impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
515
- impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
547
+ impl_Display!(
548
+ i8 => 3 as u8 in fmt_u8 => named fmt_i8,
549
+ u8 => 3 => named fmt_u8,
550
+ i16 => 5 as u16 in fmt_u16 => named fmt_i16,
551
+ u16 => 5 => named fmt_u16,
552
+ i32 => 10 as u32 in fmt_u32 => named fmt_i32,
553
+ u32 => 10 => named fmt_u32,
554
+ isize => 10 as usize in fmt_usize => named fmt_isize,
555
+ usize => 10 => named fmt_usize,
556
+ ; as u32 via to_u32 named fmt_u32);
557
+ impl_Display!(
558
+ i64 => 19 as u64 in fmt_u64 => named fmt_i64,
559
+ u64 => 20 => named fmt_u64,
560
+ ; as u64 via to_u64 named fmt_u64);
561
+
516
562
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
517
563
impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
518
564
}
@@ -619,7 +665,7 @@ impl fmt::Display for i128 {
619
665
let n = if is_nonnegative {
620
666
self.to_u128()
621
667
} else {
622
- // convert the negative num to positive by summing 1 to it's 2 complement
668
+ // convert the negative num to positive by summing 1 to its 2s complement
623
669
(!self.to_u128()).wrapping_add(1)
624
670
};
625
671
fmt_u128(n, is_nonnegative, f)
0 commit comments