1use crate::fmt::NumBuffer;
4use crate::mem::MaybeUninit;
5use crate::num::imp::fmt as numfmt;
6use crate::{fmt, str};
7
8macro_rules! radix_integer {
10 (fmt::$Trait:ident for $Signed:ident and $Unsigned:ident, $prefix:literal, $dig_tab:literal) => {
11 #[stable(feature = "rust1", since = "1.0.0")]
12 impl fmt::$Trait for $Unsigned {
13 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 const {
17 assert!($Unsigned::MIN == 0, "need unsigned");
18 assert!($dig_tab.is_ascii(), "need single-byte entries");
19 }
20
21 const DIG_TAB: &[u8] = $dig_tab;
23 const BASE: $Unsigned = DIG_TAB.len() as $Unsigned;
24 const MAX_DIG_N: usize = $Unsigned::MAX.ilog(BASE) as usize + 1;
25
26 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
28 let mut offset = buf.len();
30
31 let mut remain = *self;
34 loop {
35 let digit = remain % BASE;
36 remain /= BASE;
37
38 offset -= 1;
39 unsafe { core::hint::assert_unchecked(offset < buf.len()) }
41 buf[offset].write(DIG_TAB[digit as usize]);
42 if remain == 0 {
43 break;
44 }
45 }
46
47 let digits = unsafe { slice_buffer_to_str(&buf, offset) };
49 f.pad_integral(true, $prefix, digits)
50 }
51 }
52
53 #[stable(feature = "rust1", since = "1.0.0")]
54 impl fmt::$Trait for $Signed {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 fmt::$Trait::fmt(&self.cast_unsigned(), f)
58 }
59 }
60 };
61}
62
63macro_rules! radix_integers {
65 ($Signed:ident, $Unsigned:ident) => {
66 radix_integer! { fmt::Binary for $Signed and $Unsigned, "0b", b"01" }
67 radix_integer! { fmt::Octal for $Signed and $Unsigned, "0o", b"01234567" }
68 radix_integer! { fmt::LowerHex for $Signed and $Unsigned, "0x", b"0123456789abcdef" }
69 radix_integer! { fmt::UpperHex for $Signed and $Unsigned, "0x", b"0123456789ABCDEF" }
70 };
71}
72#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for usize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(usize::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: usize = DIG_TAB.len() as usize;
const MAX_DIG_N: usize = usize::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for isize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { isize, usize }
73#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for u8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(u8::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: u8 = DIG_TAB.len() as u8;
const MAX_DIG_N: usize = u8::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for i8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { i8, u8 }
74#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for u16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(u16::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: u16 = DIG_TAB.len() as u16;
const MAX_DIG_N: usize = u16::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for i16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { i16, u16 }
75#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for u32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(u32::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: u32 = DIG_TAB.len() as u32;
const MAX_DIG_N: usize = u32::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for i32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { i32, u32 }
76#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for u64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(u64::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: u64 = DIG_TAB.len() as u64;
const MAX_DIG_N: usize = u64::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for i64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { i64, u64 }
77#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for u128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const {
if !(u128::MIN == 0) {
{
crate::panicking::panic_fmt(format_args!("need unsigned"));
}
};
if !b"0123456789ABCDEF".is_ascii() {
{
crate::panicking::panic_fmt(format_args!("need single-byte entries"));
}
};
}
const DIG_TAB: &[u8] = b"0123456789ABCDEF";
const BASE: u128 = DIG_TAB.len() as u128;
const MAX_DIG_N: usize = u128::MAX.ilog(BASE) as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DIG_N];
let mut offset = buf.len();
let mut remain = *self;
loop {
let digit = remain % BASE;
remain /= BASE;
offset -= 1;
unsafe { core::hint::assert_unchecked(offset < buf.len()) }
buf[offset].write(DIG_TAB[digit as usize]);
if remain == 0 { break; }
}
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
f.pad_integral(true, "0x", digits)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::UpperHex for i128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.cast_unsigned(), f)
}
}radix_integers! { i128, u128 }
78
79macro_rules! impl_Debug {
80 ($($T:ident)*) => {
81 $(
82 #[stable(feature = "rust1", since = "1.0.0")]
83 impl fmt::Debug for $T {
84 #[inline]
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 if f.debug_lower_hex() {
87 fmt::LowerHex::fmt(self, f)
88 } else if f.debug_upper_hex() {
89 fmt::UpperHex::fmt(self, f)
90 } else {
91 fmt::Display::fmt(self, f)
92 }
93 }
94 }
95 )*
96 };
97}
98
99static DECIMAL_PAIRS: &[u8; 200] = b"\
101 0001020304050607080910111213141516171819\
102 2021222324252627282930313233343536373839\
103 4041424344454647484950515253545556575859\
104 6061626364656667686970717273747576777879\
105 8081828384858687888990919293949596979899";
106
107unsafe fn slice_buffer_to_str(buf: &[MaybeUninit<u8>], offset: usize) -> &str {
114 let written = unsafe { buf.get_unchecked(offset..) };
116 unsafe { str::from_utf8_unchecked(written.assume_init_ref()) }
119}
120
121macro_rules! impl_Display {
122 ($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
123
124 $(
125 const _: () = {
126 assert!($Signed::MIN < 0, "need signed");
127 assert!($Unsigned::MIN == 0, "need unsigned");
128 assert!($Signed::BITS == $Unsigned::BITS, "need counterparts");
129 assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
130 assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
131 };
132
133 #[stable(feature = "rust1", since = "1.0.0")]
134 impl fmt::Display for $Unsigned {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 #[cfg(not(feature = "optimize_for_size"))]
137 {
138 const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
139 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
141
142 unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) }
144 }
145 #[cfg(feature = "optimize_for_size")]
146 {
147 ${concat($fmt_fn, _small)}(*self as $T, true, f)
150 }
151 }
152 }
153
154 #[stable(feature = "rust1", since = "1.0.0")]
155 impl fmt::Display for $Signed {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 #[cfg(not(feature = "optimize_for_size"))]
158 {
159 const MAX_DEC_N: usize = $Unsigned::MAX.ilog10() as usize + 1;
160 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
162
163 unsafe { f.pad_integral(*self >= 0, "", self.unsigned_abs()._fmt(&mut buf)) }
165 }
166 #[cfg(feature = "optimize_for_size")]
167 {
168 return ${concat($fmt_fn, _small)}(self.unsigned_abs() as $T, *self >= 0, f);
171 }
172 }
173 }
174
175 #[cfg(not(feature = "optimize_for_size"))]
176 impl $Unsigned {
177 #[doc(hidden)]
178 #[unstable(
179 feature = "fmt_internals",
180 reason = "specialized method meant to only be used by `SpecToString` implementation",
181 issue = "none"
182 )]
183 pub unsafe fn _fmt<'a>(self, buf: &'a mut [MaybeUninit::<u8>]) -> &'a str {
184 let offset = unsafe { self._fmt_inner(buf) };
186 unsafe { slice_buffer_to_str(buf, offset) }
188 }
189
190 unsafe fn _fmt_inner(self, buf: &mut [MaybeUninit::<u8>]) -> usize {
191 let mut offset = buf.len();
193 let mut remain = self;
195
196 while size_of::<Self>() > 1 && remain > 999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)") {
199 unsafe { core::hint::assert_unchecked(offset >= 4) }
202 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
205 offset -= 4;
206
207 let scale: Self = 1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
209 let quad = remain % scale;
210 remain /= scale;
211 let pair1 = (quad / 100) as usize;
212 let pair2 = (quad % 100) as usize;
213 buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
214 buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
215 buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
216 buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
217 }
218
219 if remain > 9 {
221 unsafe { core::hint::assert_unchecked(offset >= 2) }
224 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
227 offset -= 2;
228
229 let pair = (remain % 100) as usize;
230 remain /= 100;
231 buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
232 buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
233 }
234
235 if remain != 0 || self == 0 {
237 unsafe { core::hint::assert_unchecked(offset >= 1) }
240 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
243 offset -= 1;
244
245 let last = (remain & 15) as usize;
248 buf[offset].write(DECIMAL_PAIRS[last * 2 + 1]);
249 }
251
252 offset
253 }
254 }
255
256 impl $Signed {
257 #[doc = concat!("let n = 0", stringify!($Signed), ";")]
266 #[doc = concat!("let n1 = 32", stringify!($Signed), ";")]
270 #[doc = concat!("let n2 = ", stringify!($Signed::MAX), ";")]
273 #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Signed::MAX), ".to_string());")]
274 #[stable(feature = "int_format_into", since = "1.98.0")]
276 pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
277 let mut offset;
278
279 #[cfg(not(feature = "optimize_for_size"))]
280 unsafe {
282 offset = self.unsigned_abs()._fmt_inner(&mut buf.buf);
283 }
284 #[cfg(feature = "optimize_for_size")]
285 {
286 offset = ${concat($fmt_fn, _in_buf_small)}(self.unsigned_abs() as $T, &mut buf.buf);
289 }
290 if self < 0 {
292 offset -= 1;
293 buf.buf[offset].write(b'-');
294 }
295 unsafe { slice_buffer_to_str(&buf.buf, offset) }
297 }
298 }
299
300 impl $Unsigned {
301 #[doc = concat!("let n = 0", stringify!($Unsigned), ";")]
310 #[doc = concat!("let n1 = 32", stringify!($Unsigned), ";")]
314 #[doc = concat!("let n2 = ", stringify!($Unsigned::MAX), ";")]
317 #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Unsigned::MAX), ".to_string());")]
318 #[stable(feature = "int_format_into", since = "1.98.0")]
320 pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
321 let offset;
322
323 #[cfg(not(feature = "optimize_for_size"))]
324 unsafe {
326 offset = self._fmt_inner(&mut buf.buf);
327 }
328 #[cfg(feature = "optimize_for_size")]
329 {
330 offset = ${concat($fmt_fn, _in_buf_small)}(self as $T, &mut buf.buf);
333 }
334 unsafe { slice_buffer_to_str(&buf.buf, offset) }
336 }
337 }
338
339 )*
340
341 #[cfg(feature = "optimize_for_size")]
342 fn ${concat($fmt_fn, _in_buf_small)}(mut n: $T, buf: &mut [MaybeUninit::<u8>]) -> usize {
343 let mut curr = buf.len();
344
345 loop {
351 curr -= 1;
352 buf[curr].write((n % 10) as u8 + b'0');
353 n /= 10;
354
355 if n == 0 {
356 break;
357 }
358 }
359 curr
360 }
361
362 #[cfg(feature = "optimize_for_size")]
363 fn ${concat($fmt_fn, _small)}(n: $T, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
364 const MAX_DEC_N: usize = $T::MAX.ilog10() as usize + 1;
365 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
366
367 let offset = ${concat($fmt_fn, _in_buf_small)}(n, &mut buf);
368 let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
370 f.pad_integral(is_nonnegative, "", buf_slice)
371 }
372 };
373}
374
375macro_rules! impl_Exp {
376 ($($Signed:ident, $Unsigned:ident),* ; as $T:ident into $fmt_fn:ident) => {
377 const _: () = assert!($T::MIN == 0, "need unsigned");
378
379 fn $fmt_fn(
380 f: &mut fmt::Formatter<'_>,
381 n: $T,
382 is_nonnegative: bool,
383 letter_e: u8
384 ) -> fmt::Result {
385 debug_assert!(letter_e.is_ascii_alphabetic(), "single-byte character");
386
387 let mut exp = n.checked_ilog10().unwrap_or(0) as usize;
389 debug_assert!(n / (10 as $T).pow(exp as u32) < 10);
390
391 let mut coef_prec = exp;
393 let mut coef = n;
395
396 let more_prec = match f.precision() {
398 None => {
399 while coef_prec != 0 && coef % 10 == 0 {
401 coef /= 10;
402 coef_prec -= 1;
403 }
404 0
405 },
406
407 Some(fmt_prec) if fmt_prec >= coef_prec => {
408 fmt_prec - coef_prec
410 },
411
412 Some(fmt_prec) => {
413 let less_prec = coef_prec - fmt_prec;
415 assert!(less_prec > 0);
416 let scale = unsafe {
424 (10 as $T).checked_pow(less_prec as u32).unwrap_unchecked()
425 };
426 let floor = coef / scale;
427 let over = coef % scale;
429 let half = scale / 2;
430 let round_up = if over < half {
431 0
432 } else if over > half {
433 1
434 } else {
435 floor & 1 };
437 coef = floor + round_up;
439 coef_prec = fmt_prec;
440
441 if round_up != 0 && coef.checked_ilog10().unwrap_or(0) as usize > coef_prec {
445 debug_assert_eq!(coef, (10 as $T).pow(coef_prec as u32 + 1));
446 coef /= 10; exp += 1; }
449 0
450 },
451 };
452
453 const MAX_DEC_N: usize = $T::MAX.ilog10() as usize + 1;
455 const MAX_COEF_LEN: usize = MAX_DEC_N + ".".len();
456 const MAX_TEXT_LEN: usize = MAX_COEF_LEN + "e99".len();
457 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_TEXT_LEN];
458
459 let (lead_dec, coef_len) = if coef_prec == 0 && more_prec == 0 {
461 (coef, 1_usize) } else {
463 buf[1].write(b'.');
464 let fraction_range = 2..(2 + coef_prec);
465
466 let mut remain = coef;
468 #[cfg(feature = "optimize_for_size")] {
469 for i in fraction_range.clone().rev() {
470 let digit = (remain % 10) as usize;
471 remain /= 10;
472 buf[i].write(b'0' + digit as u8);
473 }
474 }
475 #[cfg(not(feature = "optimize_for_size"))] {
476 for i in fraction_range.clone().skip(1).rev().step_by(2) {
478 let pair = (remain % 100) as usize;
479 remain /= 100;
480 buf[i - 1].write(DECIMAL_PAIRS[pair * 2 + 0]);
481 buf[i - 0].write(DECIMAL_PAIRS[pair * 2 + 1]);
482 }
483 if coef_prec & 1 != 0 {
485 let digit = (remain % 10) as usize;
486 remain /= 10;
487 buf[fraction_range.start].write(b'0' + digit as u8);
488 }
489 }
490
491 (remain, fraction_range.end)
492 };
493 debug_assert!(lead_dec < 10);
494 debug_assert!(lead_dec != 0 || coef == 0, "significant digits only");
495 buf[0].write(b'0' + lead_dec as u8);
496
497 unsafe { core::hint::assert_unchecked(coef_len <= MAX_COEF_LEN) }
499 buf[coef_len].write(letter_e);
501 let text_len: usize = match exp {
502 ..10 => {
503 buf[coef_len + 1].write(b'0' + exp as u8);
504 coef_len + 2
505 },
506 10..100 => {
507 #[cfg(feature = "optimize_for_size")] {
508 buf[coef_len + 1].write(b'0' + (exp / 10) as u8);
509 buf[coef_len + 2].write(b'0' + (exp % 10) as u8);
510 }
511 #[cfg(not(feature = "optimize_for_size"))] {
512 buf[coef_len + 1].write(DECIMAL_PAIRS[exp * 2 + 0]);
513 buf[coef_len + 2].write(DECIMAL_PAIRS[exp * 2 + 1]);
514 }
515 coef_len + 3
516 },
517 _ => {
518 const { assert!($T::MAX.ilog10() < 100) };
519 unsafe { core::hint::unreachable_unchecked() }
521 }
522 };
523 let text = unsafe { buf[..text_len].assume_init_ref() };
525
526 if more_prec == 0 {
527 let as_str = unsafe { str::from_utf8_unchecked(text) };
530 f.pad_integral(is_nonnegative, "", as_str)
531 } else {
532 let parts = &[
533 numfmt::Part::Copy(&text[..coef_len]),
534 numfmt::Part::Zero(more_prec),
535 numfmt::Part::Copy(&text[coef_len..]),
536 ];
537 let sign = if !is_nonnegative {
538 "-"
539 } else if f.sign_plus() {
540 "+"
541 } else {
542 ""
543 };
544 unsafe { f.pad_formatted_parts(&numfmt::Formatted { sign, parts }) }
547 }
548 }
549
550 $(
551 const _: () = {
552 assert!($Signed::MIN < 0, "need signed");
553 assert!($Unsigned::MIN == 0, "need unsigned");
554 assert!($Signed::BITS == $Unsigned::BITS, "need counterparts");
555 assert!($Signed::BITS <= $T::BITS, "need lossless conversion");
556 assert!($Unsigned::BITS <= $T::BITS, "need lossless conversion");
557 };
558 #[stable(feature = "integer_exp_format", since = "1.42.0")]
559 impl fmt::LowerExp for $Signed {
560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 $fmt_fn(f, self.unsigned_abs() as $T, *self >= 0, b'e')
562 }
563 }
564 #[stable(feature = "integer_exp_format", since = "1.42.0")]
565 impl fmt::LowerExp for $Unsigned {
566 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567 $fmt_fn(f, *self as $T, true, b'e')
568 }
569 }
570 #[stable(feature = "integer_exp_format", since = "1.42.0")]
571 impl fmt::UpperExp for $Signed {
572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573 $fmt_fn(f, self.unsigned_abs() as $T, *self >= 0, b'E')
574 }
575 }
576 #[stable(feature = "integer_exp_format", since = "1.42.0")]
577 impl fmt::UpperExp for $Unsigned {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 $fmt_fn(f, *self as $T, true, b'E')
580 }
581 }
582 )*
583
584 };
585}
586
587#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for usize {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.debug_lower_hex() {
fmt::LowerHex::fmt(self, f)
} else if f.debug_upper_hex() {
fmt::UpperHex::fmt(self, f)
} else { fmt::Display::fmt(self, f) }
}
}impl_Debug! {
588 i8 i16 i32 i64 i128 isize
589 u8 u16 u32 u64 u128 usize
590}
591
592#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
595#[doc(auto_cfg = false)]
596mod imp {
597 use super::*;
598 const _: () =
{
if !(isize::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(usize::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(isize::BITS == usize::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(isize::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(usize::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for usize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
{
const MAX_DEC_N: usize = usize::MAX.ilog10() as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) }
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for isize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
{
const MAX_DEC_N: usize = usize::MAX.ilog10() as usize + 1;
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
unsafe {
f.pad_integral(*self >= 0, "",
self.unsigned_abs()._fmt(&mut buf))
}
}
}
}
impl usize {
#[doc(hidden)]
#[unstable(feature = "fmt_internals", reason =
"specialized method meant to only be used by `SpecToString` implementation",
issue = "none")]
pub unsafe fn _fmt<'a>(self, buf: &'a mut [MaybeUninit<u8>]) -> &'a str {
let offset = unsafe { self._fmt_inner(buf) };
unsafe { slice_buffer_to_str(buf, offset) }
}
unsafe fn _fmt_inner(self, buf: &mut [MaybeUninit<u8>]) -> usize {
let mut offset = buf.len();
let mut remain = self;
while size_of::<Self>() > 1 &&
remain >
999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)")
{
unsafe { core::hint::assert_unchecked(offset >= 4) }
unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
offset -= 4;
let scale: Self =
1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)");
let quad = remain % scale;
remain /= scale;
let pair1 = (quad / 100) as usize;
let pair2 = (quad % 100) as usize;
buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
}
if remain > 9 {
unsafe { core::hint::assert_unchecked(offset >= 2) }
unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
offset -= 2;
let pair = (remain % 100) as usize;
remain /= 100;
buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
}
if remain != 0 || self == 0 {
unsafe { core::hint::assert_unchecked(offset >= 1) }
unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
offset -= 1;
let last = (remain & 15) as usize;
buf[offset].write(DECIMAL_PAIRS[last * 2 + 1]);
}
offset
}
}
impl isize {
#[doc = "let n = 0isize;"]
#[doc = "let n1 = 32isize;"]
#[doc = "let n2 = isize :: MAX;"]
#[doc = "assert_eq!(n2.format_into(&mut buf), isize :: MAX.to_string());"]
#[stable(feature = "int_format_into", since = "1.98.0")]
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
let mut offset;
unsafe { offset = self.unsigned_abs()._fmt_inner(&mut buf.buf); }
if self < 0 { offset -= 1; buf.buf[offset].write(b'-'); }
unsafe { slice_buffer_to_str(&buf.buf, offset) }
}
}
impl usize {
#[doc = "let n = 0usize;"]
#[doc = "let n1 = 32usize;"]
#[doc = "let n2 = usize :: MAX;"]
#[doc = "assert_eq!(n2.format_into(&mut buf), usize :: MAX.to_string());"]
#[stable(feature = "int_format_into", since = "1.98.0")]
pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
let offset;
unsafe { offset = self._fmt_inner(&mut buf.buf); }
unsafe { slice_buffer_to_str(&buf.buf, offset) }
}
}impl_Display!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into display_u64);
599 const _: () =
if !(u64::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
fn exp_u64(f: &mut fmt::Formatter<'_>, n: u64, is_nonnegative: bool,
letter_e: u8) -> fmt::Result {
if true {
if !letter_e.is_ascii_alphabetic() {
{
crate::panicking::panic_fmt(format_args!("single-byte character"));
}
};
};
let mut exp = n.checked_ilog10().unwrap_or(0) as usize;
if true {
if !(n / (10 as u64).pow(exp as u32) < 10) {
crate::panicking::panic("assertion failed: n / (10 as u64).pow(exp as u32) < 10")
};
};
let mut coef_prec = exp;
let mut coef = n;
let more_prec =
match f.precision() {
None => {
while coef_prec != 0 && coef % 10 == 0 {
coef /= 10;
coef_prec -= 1;
}
0
}
Some(fmt_prec) if fmt_prec >= coef_prec => {
fmt_prec - coef_prec
}
Some(fmt_prec) => {
let less_prec = coef_prec - fmt_prec;
if !(less_prec > 0) {
crate::panicking::panic("assertion failed: less_prec > 0")
};
let scale =
unsafe {
(10 as u64).checked_pow(less_prec as u32).unwrap_unchecked()
};
let floor = coef / scale;
let over = coef % scale;
let half = scale / 2;
let round_up =
if over < half {
0
} else if over > half { 1 } else { floor & 1 };
coef = floor + round_up;
coef_prec = fmt_prec;
if round_up != 0 &&
coef.checked_ilog10().unwrap_or(0) as usize > coef_prec {
if true {
{
match (&coef, &(10 as u64).pow(coef_prec as u32 + 1)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = crate::panicking::AssertKind::Eq;
crate::panicking::assert_failed(kind, &*left_val,
&*right_val, crate::option::Option::None);
}
}
}
};
};
coef /= 10;
exp += 1;
}
0
}
};
const MAX_DEC_N: usize = u64::MAX.ilog10() as usize + 1;
const MAX_COEF_LEN: usize = MAX_DEC_N + ".".len();
const MAX_TEXT_LEN: usize = MAX_COEF_LEN + "e99".len();
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_TEXT_LEN];
let (lead_dec, coef_len) =
if coef_prec == 0 && more_prec == 0 {
(coef, 1_usize)
} else {
buf[1].write(b'.');
let fraction_range = 2..(2 + coef_prec);
let mut remain = coef;
{
for i in fraction_range.clone().skip(1).rev().step_by(2) {
let pair = (remain % 100) as usize;
remain /= 100;
buf[i - 1].write(DECIMAL_PAIRS[pair * 2 + 0]);
buf[i - 0].write(DECIMAL_PAIRS[pair * 2 + 1]);
}
if coef_prec & 1 != 0 {
let digit = (remain % 10) as usize;
remain /= 10;
buf[fraction_range.start].write(b'0' + digit as u8);
}
}
(remain, fraction_range.end)
};
if true {
if !(lead_dec < 10) {
crate::panicking::panic("assertion failed: lead_dec < 10")
};
};
if true {
if !(lead_dec != 0 || coef == 0) {
{
crate::panicking::panic_fmt(format_args!("significant digits only"));
}
};
};
buf[0].write(b'0' + lead_dec as u8);
unsafe { core::hint::assert_unchecked(coef_len <= MAX_COEF_LEN) }
buf[coef_len].write(letter_e);
let text_len: usize =
match exp {
..10 => {
buf[coef_len + 1].write(b'0' + exp as u8);
coef_len + 2
}
10..100 => {
{
buf[coef_len + 1].write(DECIMAL_PAIRS[exp * 2 + 0]);
buf[coef_len + 2].write(DECIMAL_PAIRS[exp * 2 + 1]);
}
coef_len + 3
}
_ => {
const {
if !(u64::MAX.ilog10() < 100) {
crate::panicking::panic("assertion failed: u64::MAX.ilog10() < 100")
}
};
unsafe { core::hint::unreachable_unchecked() }
}
};
let text = unsafe { buf[..text_len].assume_init_ref() };
if more_prec == 0 {
let as_str = unsafe { str::from_utf8_unchecked(text) };
f.pad_integral(is_nonnegative, "", as_str)
} else {
let parts =
&[numfmt::Part::Copy(&text[..coef_len]),
numfmt::Part::Zero(more_prec),
numfmt::Part::Copy(&text[coef_len..])];
let sign =
if !is_nonnegative {
"-"
} else if f.sign_plus() { "+" } else { "" };
unsafe { f.pad_formatted_parts(&numfmt::Formatted { sign, parts }) }
}
}
const _: () =
{
if !(i8::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u8::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i8::BITS == u8::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(i8::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(u8::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for i8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for u8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for i8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for u8 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'E')
}
}
const _: () =
{
if !(i16::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u16::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i16::BITS == u16::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(i16::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(u16::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for i16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for u16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for i16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for u16 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'E')
}
}
const _: () =
{
if !(i32::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u32::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i32::BITS == u32::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(i32::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(u32::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for i32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for u32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for i32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for u32 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'E')
}
}
const _: () =
{
if !(i64::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u64::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i64::BITS == u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(i64::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(u64::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for i64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for u64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for i64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for u64 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'E')
}
}
const _: () =
{
if !(isize::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(usize::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(isize::BITS == usize::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(isize::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(usize::BITS <= u64::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for isize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for usize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for isize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, self.unsigned_abs() as u64, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for usize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u64(f, *self as u64, true, b'E')
}
}impl_Exp!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize; as u64 into exp_u64);
600}
601
602#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
603#[doc(auto_cfg = false)]
604mod imp {
605 use super::*;
606 impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into display_u32);
607 impl_Display!(i64, u64; as u64 into display_u64);
608
609 impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize; as u32 into exp_u32);
610 impl_Exp!(i64, u64; as u64 into exp_u64);
611}
612const _: () =
if !(u128::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
fn exp_u128(f: &mut fmt::Formatter<'_>, n: u128, is_nonnegative: bool,
letter_e: u8) -> fmt::Result {
if true {
if !letter_e.is_ascii_alphabetic() {
{
crate::panicking::panic_fmt(format_args!("single-byte character"));
}
};
};
let mut exp = n.checked_ilog10().unwrap_or(0) as usize;
if true {
if !(n / (10 as u128).pow(exp as u32) < 10) {
crate::panicking::panic("assertion failed: n / (10 as u128).pow(exp as u32) < 10")
};
};
let mut coef_prec = exp;
let mut coef = n;
let more_prec =
match f.precision() {
None => {
while coef_prec != 0 && coef % 10 == 0 {
coef /= 10;
coef_prec -= 1;
}
0
}
Some(fmt_prec) if fmt_prec >= coef_prec => {
fmt_prec - coef_prec
}
Some(fmt_prec) => {
let less_prec = coef_prec - fmt_prec;
if !(less_prec > 0) {
crate::panicking::panic("assertion failed: less_prec > 0")
};
let scale =
unsafe {
(10 as
u128).checked_pow(less_prec as u32).unwrap_unchecked()
};
let floor = coef / scale;
let over = coef % scale;
let half = scale / 2;
let round_up =
if over < half {
0
} else if over > half { 1 } else { floor & 1 };
coef = floor + round_up;
coef_prec = fmt_prec;
if round_up != 0 &&
coef.checked_ilog10().unwrap_or(0) as usize > coef_prec {
if true {
{
match (&coef, &(10 as u128).pow(coef_prec as u32 + 1)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = crate::panicking::AssertKind::Eq;
crate::panicking::assert_failed(kind, &*left_val,
&*right_val, crate::option::Option::None);
}
}
}
};
};
coef /= 10;
exp += 1;
}
0
}
};
const MAX_DEC_N: usize = u128::MAX.ilog10() as usize + 1;
const MAX_COEF_LEN: usize = MAX_DEC_N + ".".len();
const MAX_TEXT_LEN: usize = MAX_COEF_LEN + "e99".len();
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_TEXT_LEN];
let (lead_dec, coef_len) =
if coef_prec == 0 && more_prec == 0 {
(coef, 1_usize)
} else {
buf[1].write(b'.');
let fraction_range = 2..(2 + coef_prec);
let mut remain = coef;
{
for i in fraction_range.clone().skip(1).rev().step_by(2) {
let pair = (remain % 100) as usize;
remain /= 100;
buf[i - 1].write(DECIMAL_PAIRS[pair * 2 + 0]);
buf[i - 0].write(DECIMAL_PAIRS[pair * 2 + 1]);
}
if coef_prec & 1 != 0 {
let digit = (remain % 10) as usize;
remain /= 10;
buf[fraction_range.start].write(b'0' + digit as u8);
}
}
(remain, fraction_range.end)
};
if true {
if !(lead_dec < 10) {
crate::panicking::panic("assertion failed: lead_dec < 10")
};
};
if true {
if !(lead_dec != 0 || coef == 0) {
{
crate::panicking::panic_fmt(format_args!("significant digits only"));
}
};
};
buf[0].write(b'0' + lead_dec as u8);
unsafe { core::hint::assert_unchecked(coef_len <= MAX_COEF_LEN) }
buf[coef_len].write(letter_e);
let text_len: usize =
match exp {
..10 => {
buf[coef_len + 1].write(b'0' + exp as u8);
coef_len + 2
}
10..100 => {
{
buf[coef_len + 1].write(DECIMAL_PAIRS[exp * 2 + 0]);
buf[coef_len + 2].write(DECIMAL_PAIRS[exp * 2 + 1]);
}
coef_len + 3
}
_ => {
const {
if !(u128::MAX.ilog10() < 100) {
crate::panicking::panic("assertion failed: u128::MAX.ilog10() < 100")
}
};
unsafe { core::hint::unreachable_unchecked() }
}
};
let text = unsafe { buf[..text_len].assume_init_ref() };
if more_prec == 0 {
let as_str = unsafe { str::from_utf8_unchecked(text) };
f.pad_integral(is_nonnegative, "", as_str)
} else {
let parts =
&[numfmt::Part::Copy(&text[..coef_len]),
numfmt::Part::Zero(more_prec),
numfmt::Part::Copy(&text[coef_len..])];
let sign =
if !is_nonnegative {
"-"
} else if f.sign_plus() { "+" } else { "" };
unsafe { f.pad_formatted_parts(&numfmt::Formatted { sign, parts }) }
}
}
const _: () =
{
if !(i128::MIN < 0) {
{ crate::panicking::panic_fmt(format_args!("need signed")); }
};
if !(u128::MIN == 0) {
{ crate::panicking::panic_fmt(format_args!("need unsigned")); }
};
if !(i128::BITS == u128::BITS) {
{
crate::panicking::panic_fmt(format_args!("need counterparts"));
}
};
if !(i128::BITS <= u128::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
if !(u128::BITS <= u128::BITS) {
{
crate::panicking::panic_fmt(format_args!("need lossless conversion"));
}
};
};
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for i128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u128(f, self.unsigned_abs() as u128, *self >= 0, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::LowerExp for u128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u128(f, *self as u128, true, b'e')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for i128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u128(f, self.unsigned_abs() as u128, *self >= 0, b'E')
}
}
#[stable(feature = "integer_exp_format", since = "1.42.0")]
impl fmt::UpperExp for u128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
exp_u128(f, *self as u128, true, b'E')
}
}impl_Exp!(i128, u128; as u128 into exp_u128);
613
614const U128_MAX_DEC_N: usize = u128::MAX.ilog10() as usize + 1;
615
616#[stable(feature = "rust1", since = "1.0.0")]
617impl fmt::Display for u128 {
618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619 let mut buf = [MaybeUninit::<u8>::uninit(); U128_MAX_DEC_N];
620
621 unsafe { f.pad_integral(true, "", self._fmt(&mut buf)) }
623 }
624}
625
626#[stable(feature = "rust1", since = "1.0.0")]
627impl fmt::Display for i128 {
628 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
629 let mut buf = [MaybeUninit::<u8>::uninit(); U128_MAX_DEC_N];
632
633 let is_nonnegative = *self >= 0;
634 unsafe { f.pad_integral(is_nonnegative, "", self.unsigned_abs()._fmt(&mut buf)) }
636 }
637}
638
639impl u128 {
640 #[doc(hidden)]
643 #[unstable(
644 feature = "fmt_internals",
645 reason = "specialized method meant to only be used by `SpecToString` implementation",
646 issue = "none"
647 )]
648 pub unsafe fn _fmt<'a>(self, buf: &'a mut [MaybeUninit<u8>]) -> &'a str {
649 let offset = unsafe { self._fmt_inner(buf) };
651 unsafe { slice_buffer_to_str(buf, offset) }
653 }
654
655 unsafe fn _fmt_inner(self, buf: &mut [MaybeUninit<u8>]) -> usize {
656 if self == 0 {
659 let offset = buf.len() - 1;
660 buf[offset].write(b'0');
661 return offset;
662 }
663 let (quot_1e16, mod_1e16) = div_rem_1e16(self);
665 let (mut remain, mut offset) = if quot_1e16 == 0 {
666 (mod_1e16, U128_MAX_DEC_N)
667 } else {
668 enc_16lsd::<{ U128_MAX_DEC_N - 16 }>(buf, mod_1e16);
670
671 let (quot2, mod2) = div_rem_1e16(quot_1e16);
673 if quot2 == 0 {
674 (mod2, U128_MAX_DEC_N - 16)
675 } else {
676 enc_16lsd::<{ U128_MAX_DEC_N - 32 }>(buf, mod2);
678 (quot2 as u64, U128_MAX_DEC_N - 32)
680 }
681 };
682
683 while remain > 999 {
685 unsafe { core::hint::assert_unchecked(offset >= 4) }
688 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
691 offset -= 4;
692
693 let quad = remain % 1_00_00;
695 remain /= 1_00_00;
696 let pair1 = (quad / 100) as usize;
697 let pair2 = (quad % 100) as usize;
698 buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
699 buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
700 buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
701 buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
702 }
703
704 if remain > 9 {
706 unsafe { core::hint::assert_unchecked(offset >= 2) }
709 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
712 offset -= 2;
713
714 let pair = (remain % 100) as usize;
715 remain /= 100;
716 buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
717 buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
718 }
719
720 if remain != 0 {
722 unsafe { core::hint::assert_unchecked(offset >= 1) }
725 unsafe { core::hint::assert_unchecked(offset <= buf.len()) }
728 offset -= 1;
729
730 let last = (remain & 15) as usize;
733 buf[offset].write(DECIMAL_PAIRS[last * 2 + 1]);
734 }
736 offset
737 }
738
739 #[stable(feature = "int_format_into", since = "1.98.0")]
760 pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
761 let diff = buf.buf.len() - U128_MAX_DEC_N;
762 unsafe { self._fmt(buf.buf.get_unchecked_mut(diff..)) }
769 }
770}
771
772impl i128 {
773 #[stable(feature = "int_format_into", since = "1.98.0")]
792 pub fn format_into(self, buf: &mut NumBuffer<Self>) -> &str {
793 let diff = buf.buf.len() - U128_MAX_DEC_N;
794 let mut offset =
800 unsafe { self.unsigned_abs()._fmt_inner(buf.buf.get_unchecked_mut(diff..)) };
802 offset += diff;
804 if self < 0 {
806 offset -= 1;
807 unsafe {
809 buf.buf.get_unchecked_mut(offset).write(b'-');
810 }
811 }
812 unsafe { slice_buffer_to_str(&buf.buf, offset) }
814 }
815}
816
817fn enc_16lsd<const OFFSET: usize>(buf: &mut [MaybeUninit<u8>], n: u64) {
820 let mut remain = n;
822
823 for quad_index in (1..4).rev() {
825 let quad = remain % 1_00_00;
827 remain /= 1_00_00;
828 let pair1 = (quad / 100) as usize;
829 let pair2 = (quad % 100) as usize;
830 buf[quad_index * 4 + OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
831 buf[quad_index * 4 + OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
832 buf[quad_index * 4 + OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
833 buf[quad_index * 4 + OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
834 }
835
836 let pair1 = (remain / 100) as usize;
838 let pair2 = (remain % 100) as usize;
839 buf[OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]);
840 buf[OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]);
841 buf[OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]);
842 buf[OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]);
843}
844
845#[inline]
855fn div_rem_1e16(n: u128) -> (u128, u64) {
856 const D: u128 = 1_0000_0000_0000_0000;
857 if n < D {
859 return (0, n as u64);
860 }
861
862 const M_HIGH: u128 = 76624777043294442917917351357515459181;
865 const SH_POST: u8 = 51;
866
867 let quot = n.carrying_mul(M_HIGH, 0).1 >> SH_POST;
868 let rem = n - quot * D;
869 (quot, rem as u64)
870}