• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Integer and floating-point number formatting
2 
3 use crate::fmt;
4 use crate::mem::MaybeUninit;
5 use crate::num::fmt as numfmt;
6 use crate::ops::{Div, Rem, Sub};
7 use crate::ptr;
8 use crate::slice;
9 use crate::str;
10 
11 #[doc(hidden)]
12 trait DisplayInt:
13     PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
14 {
zero() -> Self15     fn zero() -> Self;
from_u8(u: u8) -> Self16     fn from_u8(u: u8) -> Self;
to_u8(&self) -> u817     fn to_u8(&self) -> u8;
to_u16(&self) -> u1618     fn to_u16(&self) -> u16;
to_u32(&self) -> u3219     fn to_u32(&self) -> u32;
to_u64(&self) -> u6420     fn to_u64(&self) -> u64;
to_u128(&self) -> u12821     fn to_u128(&self) -> u128;
22 }
23 
24 macro_rules! impl_int {
25     ($($t:ident)*) => (
26       $(impl DisplayInt for $t {
27           fn zero() -> Self { 0 }
28           fn from_u8(u: u8) -> Self { u as Self }
29           fn to_u8(&self) -> u8 { *self as u8 }
30           fn to_u16(&self) -> u16 { *self as u16 }
31           fn to_u32(&self) -> u32 { *self as u32 }
32           fn to_u64(&self) -> u64 { *self as u64 }
33           fn to_u128(&self) -> u128 { *self as u128 }
34       })*
35     )
36 }
37 macro_rules! impl_uint {
38     ($($t:ident)*) => (
39       $(impl DisplayInt for $t {
40           fn zero() -> Self { 0 }
41           fn from_u8(u: u8) -> Self { u as Self }
42           fn to_u8(&self) -> u8 { *self as u8 }
43           fn to_u16(&self) -> u16 { *self as u16 }
44           fn to_u32(&self) -> u32 { *self as u32 }
45           fn to_u64(&self) -> u64 { *self as u64 }
46           fn to_u128(&self) -> u128 { *self as u128 }
47       })*
48     )
49 }
50 
51 impl_int! { i8 i16 i32 i64 i128 isize }
52 impl_uint! { u8 u16 u32 u64 u128 usize }
53 
54 /// A type that represents a specific radix
55 ///
56 /// # Safety
57 ///
58 /// `digit` must return an ASCII character.
59 #[doc(hidden)]
60 unsafe trait GenericRadix: Sized {
61     /// The number of digits.
62     const BASE: u8;
63 
64     /// A radix-specific prefix string.
65     const PREFIX: &'static str;
66 
67     /// Converts an integer to corresponding radix digit.
digit(x: u8) -> u868     fn digit(x: u8) -> u8;
69 
70     /// Format an integer using the radix using a formatter.
fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result71     fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72         // The radix can be as low as 2, so we need a buffer of at least 128
73         // characters for a base 2 number.
74         let zero = T::zero();
75         let is_nonnegative = x >= zero;
76         let mut buf = [MaybeUninit::<u8>::uninit(); 128];
77         let mut curr = buf.len();
78         let base = T::from_u8(Self::BASE);
79         if is_nonnegative {
80             // Accumulate each digit of the number from the least significant
81             // to the most significant figure.
82             for byte in buf.iter_mut().rev() {
83                 let n = x % base; // Get the current place value.
84                 x = x / base; // Deaccumulate the number.
85                 byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
86                 curr -= 1;
87                 if x == zero {
88                     // No more digits left to accumulate.
89                     break;
90                 };
91             }
92         } else {
93             // Do the same as above, but accounting for two's complement.
94             for byte in buf.iter_mut().rev() {
95                 let n = zero - (x % base); // Get the current place value.
96                 x = x / base; // Deaccumulate the number.
97                 byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
98                 curr -= 1;
99                 if x == zero {
100                     // No more digits left to accumulate.
101                     break;
102                 };
103             }
104         }
105         let buf = &buf[curr..];
106         // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
107         // valid UTF-8
108         let buf = unsafe {
109             str::from_utf8_unchecked(slice::from_raw_parts(
110                 MaybeUninit::slice_as_ptr(buf),
111                 buf.len(),
112             ))
113         };
114         f.pad_integral(is_nonnegative, Self::PREFIX, buf)
115     }
116 }
117 
118 /// A binary (base 2) radix
119 #[derive(Clone, PartialEq)]
120 struct Binary;
121 
122 /// An octal (base 8) radix
123 #[derive(Clone, PartialEq)]
124 struct Octal;
125 
126 /// A hexadecimal (base 16) radix, formatted with lower-case characters
127 #[derive(Clone, PartialEq)]
128 struct LowerHex;
129 
130 /// A hexadecimal (base 16) radix, formatted with upper-case characters
131 #[derive(Clone, PartialEq)]
132 struct UpperHex;
133 
134 macro_rules! radix {
135     ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
136         unsafe impl GenericRadix for $T {
137             const BASE: u8 = $base;
138             const PREFIX: &'static str = $prefix;
139             fn digit(x: u8) -> u8 {
140                 match x {
141                     $($x => $conv,)+
142                     x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x),
143                 }
144             }
145         }
146     }
147 }
148 
149 radix! { Binary,    2, "0b", x @  0 ..=  1 => b'0' + x }
150 radix! { Octal,     8, "0o", x @  0 ..=  7 => b'0' + x }
151 radix! { LowerHex, 16, "0x", x @  0 ..=  9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) }
152 radix! { UpperHex, 16, "0x", x @  0 ..=  9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
153 
154 macro_rules! int_base {
155     (fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
156         #[stable(feature = "rust1", since = "1.0.0")]
157         impl fmt::$Trait for $T {
158             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159                 $Radix.fmt_int(*self as $U, f)
160             }
161         }
162     };
163 }
164 
165 macro_rules! integer {
166     ($Int:ident, $Uint:ident) => {
167         int_base! { fmt::Binary   for $Int as $Uint  -> Binary }
168         int_base! { fmt::Octal    for $Int as $Uint  -> Octal }
169         int_base! { fmt::LowerHex for $Int as $Uint  -> LowerHex }
170         int_base! { fmt::UpperHex for $Int as $Uint  -> UpperHex }
171 
172         int_base! { fmt::Binary   for $Uint as $Uint -> Binary }
173         int_base! { fmt::Octal    for $Uint as $Uint -> Octal }
174         int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
175         int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
176     };
177 }
178 integer! { isize, usize }
179 integer! { i8, u8 }
180 integer! { i16, u16 }
181 integer! { i32, u32 }
182 integer! { i64, u64 }
183 integer! { i128, u128 }
184 macro_rules! debug {
185     ($($T:ident)*) => {$(
186         #[stable(feature = "rust1", since = "1.0.0")]
187         impl fmt::Debug for $T {
188             #[inline]
189             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190                 if f.debug_lower_hex() {
191                     fmt::LowerHex::fmt(self, f)
192                 } else if f.debug_upper_hex() {
193                     fmt::UpperHex::fmt(self, f)
194                 } else {
195                     fmt::Display::fmt(self, f)
196                 }
197             }
198         }
199     )*};
200 }
201 debug! {
202   i8 i16 i32 i64 i128 isize
203   u8 u16 u32 u64 u128 usize
204 }
205 
206 // 2 digit decimal look up table
207 static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
208       2021222324252627282930313233343536373839\
209       4041424344454647484950515253545556575859\
210       6061626364656667686970717273747576777879\
211       8081828384858687888990919293949596979899";
212 
213 macro_rules! impl_Display {
214     ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
215         fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216             // 2^128 is about 3*10^38, so 39 gives an extra byte of space
217             let mut buf = [MaybeUninit::<u8>::uninit(); 39];
218             let mut curr = buf.len();
219             let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
220             let lut_ptr = DEC_DIGITS_LUT.as_ptr();
221 
222             // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
223             // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
224             // that it's OK to copy into `buf_ptr`, notice that at the beginning
225             // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
226             // each step this is kept the same as `n` is divided. Since `n` is always
227             // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
228             // is safe to access.
229             unsafe {
230                 // need at least 16 bits for the 4-characters-at-a-time to work.
231                 assert!(crate::mem::size_of::<$u>() >= 2);
232 
233                 // eagerly decode 4 characters at a time
234                 while n >= 10000 {
235                     let rem = (n % 10000) as usize;
236                     n /= 10000;
237 
238                     let d1 = (rem / 100) << 1;
239                     let d2 = (rem % 100) << 1;
240                     curr -= 4;
241 
242                     // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
243                     // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
244                     // which is `10^40 > 2^128 > n`.
245                     ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
246                     ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
247                 }
248 
249                 // if we reach here numbers are <= 9999, so at most 4 chars long
250                 let mut n = n as usize; // possibly reduce 64bit math
251 
252                 // decode 2 more chars, if > 2 chars
253                 if n >= 100 {
254                     let d1 = (n % 100) << 1;
255                     n /= 100;
256                     curr -= 2;
257                     ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
258                 }
259 
260                 // decode last 1 or 2 chars
261                 if n < 10 {
262                     curr -= 1;
263                     *buf_ptr.add(curr) = (n as u8) + b'0';
264                 } else {
265                     let d1 = n << 1;
266                     curr -= 2;
267                     ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
268                 }
269             }
270 
271             // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
272             // UTF-8 since `DEC_DIGITS_LUT` is
273             let buf_slice = unsafe {
274                 str::from_utf8_unchecked(
275                     slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
276             };
277             f.pad_integral(is_nonnegative, "", buf_slice)
278         }
279 
280         $(#[stable(feature = "rust1", since = "1.0.0")]
281         impl fmt::Display for $t {
282             #[allow(unused_comparisons)]
283             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
284                 let is_nonnegative = *self >= 0;
285                 let n = if is_nonnegative {
286                     self.$conv_fn()
287                 } else {
288                     // convert the negative num to positive by summing 1 to it's 2 complement
289                     (!self.$conv_fn()).wrapping_add(1)
290                 };
291                 $name(n, is_nonnegative, f)
292             }
293         })*
294     };
295 }
296 
297 macro_rules! impl_Exp {
298     ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
299         fn $name(
300             mut n: $u,
301             is_nonnegative: bool,
302             upper: bool,
303             f: &mut fmt::Formatter<'_>
304         ) -> fmt::Result {
305             let (mut n, mut exponent, trailing_zeros, added_precision) = {
306                 let mut exponent = 0;
307                 // count and remove trailing decimal zeroes
308                 while n % 10 == 0 && n >= 10 {
309                     n /= 10;
310                     exponent += 1;
311                 }
312 
313                 let (added_precision, subtracted_precision) = match f.precision() {
314                     Some(fmt_prec) => {
315                         // number of decimal digits minus 1
316                         let mut tmp = n;
317                         let mut prec = 0;
318                         while tmp >= 10 {
319                             tmp /= 10;
320                             prec += 1;
321                         }
322                         (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec))
323                     }
324                     None => (0, 0)
325                 };
326                 for _ in 1..subtracted_precision {
327                     n /= 10;
328                     exponent += 1;
329                 }
330                 if subtracted_precision != 0 {
331                     let rem = n % 10;
332                     n /= 10;
333                     exponent += 1;
334                     // round up last digit
335                     if rem >= 5 {
336                         n += 1;
337                     }
338                 }
339                 (n, exponent, exponent, added_precision)
340             };
341 
342             // 39 digits (worst case u128) + . = 40
343             // Since `curr` always decreases by the number of digits copied, this means
344             // that `curr >= 0`.
345             let mut buf = [MaybeUninit::<u8>::uninit(); 40];
346             let mut curr = buf.len(); //index for buf
347             let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
348             let lut_ptr = DEC_DIGITS_LUT.as_ptr();
349 
350             // decode 2 chars at a time
351             while n >= 100 {
352                 let d1 = ((n % 100) as usize) << 1;
353                 curr -= 2;
354                 // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
355                 // `DEC_DIGITS_LUT` has a length of 200.
356                 unsafe {
357                     ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
358                 }
359                 n /= 100;
360                 exponent += 2;
361             }
362             // n is <= 99, so at most 2 chars long
363             let mut n = n as isize; // possibly reduce 64bit math
364             // decode second-to-last character
365             if n >= 10 {
366                 curr -= 1;
367                 // SAFETY: Safe since `40 > curr >= 0` (see comment)
368                 unsafe {
369                     *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0';
370                 }
371                 n /= 10;
372                 exponent += 1;
373             }
374             // add decimal point iff >1 mantissa digit will be printed
375             if exponent != trailing_zeros || added_precision != 0 {
376                 curr -= 1;
377                 // SAFETY: Safe since `40 > curr >= 0`
378                 unsafe {
379                     *buf_ptr.add(curr) = b'.';
380                 }
381             }
382 
383             // SAFETY: Safe since `40 > curr >= 0`
384             let buf_slice = unsafe {
385                 // decode last character
386                 curr -= 1;
387                 *buf_ptr.add(curr) = (n as u8) + b'0';
388 
389                 let len = buf.len() - curr as usize;
390                 slice::from_raw_parts(buf_ptr.add(curr), len)
391             };
392 
393             // stores 'e' (or 'E') and the up to 2-digit exponent
394             let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
395             let exp_ptr = MaybeUninit::slice_as_mut_ptr(&mut exp_buf);
396             // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
397             // is contained within `exp_buf` since `len <= 3`.
398             let exp_slice = unsafe {
399                 *exp_ptr.add(0) = if upper { b'E' } else { b'e' };
400                 let len = if exponent < 10 {
401                     *exp_ptr.add(1) = (exponent as u8) + b'0';
402                     2
403                 } else {
404                     let off = exponent << 1;
405                     ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2);
406                     3
407                 };
408                 slice::from_raw_parts(exp_ptr, len)
409             };
410 
411             let parts = &[
412                 numfmt::Part::Copy(buf_slice),
413                 numfmt::Part::Zero(added_precision),
414                 numfmt::Part::Copy(exp_slice),
415             ];
416             let sign = if !is_nonnegative {
417                 "-"
418             } else if f.sign_plus() {
419                 "+"
420             } else {
421                 ""
422             };
423             let formatted = numfmt::Formatted { sign, parts };
424             // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters.
425             unsafe { f.pad_formatted_parts(&formatted) }
426         }
427 
428         $(
429             #[stable(feature = "integer_exp_format", since = "1.42.0")]
430             impl fmt::LowerExp for $t {
431                 #[allow(unused_comparisons)]
432                 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433                     let is_nonnegative = *self >= 0;
434                     let n = if is_nonnegative {
435                         self.$conv_fn()
436                     } else {
437                         // convert the negative num to positive by summing 1 to it's 2 complement
438                         (!self.$conv_fn()).wrapping_add(1)
439                     };
440                     $name(n, is_nonnegative, false, f)
441                 }
442             })*
443         $(
444             #[stable(feature = "integer_exp_format", since = "1.42.0")]
445             impl fmt::UpperExp for $t {
446                 #[allow(unused_comparisons)]
447                 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448                     let is_nonnegative = *self >= 0;
449                     let n = if is_nonnegative {
450                         self.$conv_fn()
451                     } else {
452                         // convert the negative num to positive by summing 1 to it's 2 complement
453                         (!self.$conv_fn()).wrapping_add(1)
454                     };
455                     $name(n, is_nonnegative, true, f)
456                 }
457             })*
458     };
459 }
460 
461 // Include wasm32 in here since it doesn't reflect the native pointer size, and
462 // often cares strongly about getting a smaller code size.
463 #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
464 mod imp {
465     use super::*;
466     impl_Display!(
467         i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
468             as u64 via to_u64 named fmt_u64
469     );
470     impl_Exp!(
471         i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
472             as u64 via to_u64 named exp_u64
473     );
474 }
475 
476 #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
477 mod imp {
478     use super::*;
479     impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
480     impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
481     impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
482     impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
483 }
484 impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
485 
486 /// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut usize)487 fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut usize) {
488     let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
489     let lut_ptr = DEC_DIGITS_LUT.as_ptr();
490     assert!(*curr > 19);
491 
492     // SAFETY:
493     // Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most
494     // 198, so will never OOB. There is a check above that there are at least 19 characters
495     // remaining.
496     unsafe {
497         if n >= 1e16 as u64 {
498             let to_parse = n % 1e16 as u64;
499             n /= 1e16 as u64;
500 
501             // Some of these are nops but it looks more elegant this way.
502             let d1 = ((to_parse / 1e14 as u64) % 100) << 1;
503             let d2 = ((to_parse / 1e12 as u64) % 100) << 1;
504             let d3 = ((to_parse / 1e10 as u64) % 100) << 1;
505             let d4 = ((to_parse / 1e8 as u64) % 100) << 1;
506             let d5 = ((to_parse / 1e6 as u64) % 100) << 1;
507             let d6 = ((to_parse / 1e4 as u64) % 100) << 1;
508             let d7 = ((to_parse / 1e2 as u64) % 100) << 1;
509             let d8 = ((to_parse / 1e0 as u64) % 100) << 1;
510 
511             *curr -= 16;
512 
513             ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
514             ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
515             ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2);
516             ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2);
517             ptr::copy_nonoverlapping(lut_ptr.add(d5 as usize), buf_ptr.add(*curr + 8), 2);
518             ptr::copy_nonoverlapping(lut_ptr.add(d6 as usize), buf_ptr.add(*curr + 10), 2);
519             ptr::copy_nonoverlapping(lut_ptr.add(d7 as usize), buf_ptr.add(*curr + 12), 2);
520             ptr::copy_nonoverlapping(lut_ptr.add(d8 as usize), buf_ptr.add(*curr + 14), 2);
521         }
522         if n >= 1e8 as u64 {
523             let to_parse = n % 1e8 as u64;
524             n /= 1e8 as u64;
525 
526             // Some of these are nops but it looks more elegant this way.
527             let d1 = ((to_parse / 1e6 as u64) % 100) << 1;
528             let d2 = ((to_parse / 1e4 as u64) % 100) << 1;
529             let d3 = ((to_parse / 1e2 as u64) % 100) << 1;
530             let d4 = ((to_parse / 1e0 as u64) % 100) << 1;
531             *curr -= 8;
532 
533             ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
534             ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
535             ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2);
536             ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2);
537         }
538         // `n` < 1e8 < (1 << 32)
539         let mut n = n as u32;
540         if n >= 1e4 as u32 {
541             let to_parse = n % 1e4 as u32;
542             n /= 1e4 as u32;
543 
544             let d1 = (to_parse / 100) << 1;
545             let d2 = (to_parse % 100) << 1;
546             *curr -= 4;
547 
548             ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
549             ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
550         }
551 
552         // `n` < 1e4 < (1 << 16)
553         let mut n = n as u16;
554         if n >= 100 {
555             let d1 = (n % 100) << 1;
556             n /= 100;
557             *curr -= 2;
558             ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2);
559         }
560 
561         // decode last 1 or 2 chars
562         if n < 10 {
563             *curr -= 1;
564             *buf_ptr.add(*curr) = (n as u8) + b'0';
565         } else {
566             let d1 = n << 1;
567             *curr -= 2;
568             ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2);
569         }
570     }
571 }
572 
573 #[stable(feature = "rust1", since = "1.0.0")]
574 impl fmt::Display for u128 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result575     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
576         fmt_u128(*self, true, f)
577     }
578 }
579 
580 #[stable(feature = "rust1", since = "1.0.0")]
581 impl fmt::Display for i128 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result582     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583         let is_nonnegative = *self >= 0;
584         let n = if is_nonnegative {
585             self.to_u128()
586         } else {
587             // convert the negative num to positive by summing 1 to it's 2 complement
588             (!self.to_u128()).wrapping_add(1)
589         };
590         fmt_u128(n, is_nonnegative, f)
591     }
592 }
593 
594 /// Specialized optimization for u128. Instead of taking two items at a time, it splits
595 /// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
596 /// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
597 /// 10^20 > 2^64 > 10^19.
fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result598 fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599     // 2^128 is about 3*10^38, so 39 gives an extra byte of space
600     let mut buf = [MaybeUninit::<u8>::uninit(); 39];
601     let mut curr = buf.len();
602 
603     let (n, rem) = udiv_1e19(n);
604     parse_u64_into(rem, &mut buf, &mut curr);
605 
606     if n != 0 {
607         // 0 pad up to point
608         let target = buf.len() - 19;
609         // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
610         // remaining since it has length 39
611         unsafe {
612             ptr::write_bytes(
613                 MaybeUninit::slice_as_mut_ptr(&mut buf).add(target),
614                 b'0',
615                 curr - target,
616             );
617         }
618         curr = target;
619 
620         let (n, rem) = udiv_1e19(n);
621         parse_u64_into(rem, &mut buf, &mut curr);
622         // Should this following branch be annotated with unlikely?
623         if n != 0 {
624             let target = buf.len() - 38;
625             // The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
626             // buf `buf` is not used in this scope so we are good.
627             let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
628             // SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
629             // There can only be at most 1 digit remaining.
630             unsafe {
631                 ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
632                 curr = target - 1;
633                 *buf_ptr.add(curr) = (n as u8) + b'0';
634             }
635         }
636     }
637 
638     // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
639     // UTF-8 since `DEC_DIGITS_LUT` is
640     let buf_slice = unsafe {
641         str::from_utf8_unchecked(slice::from_raw_parts(
642             MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr),
643             buf.len() - curr,
644         ))
645     };
646     f.pad_integral(is_nonnegative, "", buf_slice)
647 }
648 
649 /// Partition of `n` into n > 1e19 and rem <= 1e19
650 ///
651 /// Integer division algorithm is based on the following paper:
652 ///
653 ///   T. Granlund and P. Montgomery, “Division by Invariant Integers Using Multiplication”
654 ///   in Proc. of the SIGPLAN94 Conference on Programming Language Design and
655 ///   Implementation, 1994, pp. 61–72
656 ///
udiv_1e19(n: u128) -> (u128, u64)657 fn udiv_1e19(n: u128) -> (u128, u64) {
658     const DIV: u64 = 1e19 as u64;
659     const FACTOR: u128 = 156927543384667019095894735580191660403;
660 
661     let quot = if n < 1 << 83 {
662         ((n >> 19) as u64 / (DIV >> 19)) as u128
663     } else {
664         u128_mulhi(n, FACTOR) >> 62
665     };
666 
667     let rem = (n - quot * DIV as u128) as u64;
668     (quot, rem)
669 }
670 
671 /// Multiply unsigned 128 bit integers, return upper 128 bits of the result
672 #[inline]
u128_mulhi(x: u128, y: u128) -> u128673 fn u128_mulhi(x: u128, y: u128) -> u128 {
674     let x_lo = x as u64;
675     let x_hi = (x >> 64) as u64;
676     let y_lo = y as u64;
677     let y_hi = (y >> 64) as u64;
678 
679     // handle possibility of overflow
680     let carry = (x_lo as u128 * y_lo as u128) >> 64;
681     let m = x_lo as u128 * y_hi as u128 + carry;
682     let high1 = m >> 64;
683 
684     let m_lo = m as u64;
685     let high2 = (x_hi as u128 * y_lo as u128 + m_lo as u128) >> 64;
686 
687     x_hi as u128 * y_hi as u128 + high1 + high2
688 }
689