Skip to content

Commit 19e56cb

Browse files
committed
Add zero padding
1 parent 515b3b6 commit 19e56cb

File tree

1 file changed

+58
-75
lines changed

1 file changed

+58
-75
lines changed

library/core/src/fmt/num.rs

+58-75
Original file line numberDiff line numberDiff line change
@@ -3,109 +3,47 @@
33
use crate::fmt;
44
use crate::mem::MaybeUninit;
55
use crate::num::flt2dec;
6+
use crate::ops::{Div, Rem, Sub};
67
use crate::ptr;
78
use crate::slice;
89
use crate::str;
910

1011
#[doc(hidden)]
11-
trait DisplayInt {
12+
trait DisplayInt:
13+
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
14+
{
15+
fn zero() -> Self;
16+
fn from_u8(u: u8) -> Self;
1217
fn to_u8(&self) -> u8;
1318
fn to_u16(&self) -> u16;
1419
fn to_u32(&self) -> u32;
1520
fn to_u64(&self) -> u64;
1621
fn to_u128(&self) -> u128;
17-
18-
fn fmt_int<R: GenericRadix>(self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
1922
}
2023

2124
macro_rules! impl_int {
2225
($($t:ident)*) => (
2326
$(impl DisplayInt for $t {
27+
fn zero() -> Self { 0 }
28+
fn from_u8(u: u8) -> Self { u as Self }
2429
fn to_u8(&self) -> u8 { *self as u8 }
2530
fn to_u16(&self) -> u16 { *self as u16 }
2631
fn to_u32(&self) -> u32 { *self as u32 }
2732
fn to_u64(&self) -> u64 { *self as u64 }
2833
fn to_u128(&self) -> u128 { *self as u128 }
29-
/// Format an integer using the radix using a formatter.
30-
fn fmt_int<R: GenericRadix>(mut self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31-
// The radix can be as low as 2, so we need a buffer of at least 128
32-
// characters for a base 2 number.
33-
let is_nonnegative = self >= 0;
34-
let mut buf = [MaybeUninit::<u8>::uninit(); crate::mem::size_of::<$t>()];
35-
let mut curr = buf.len();
36-
let base = R::BASE as Self;
37-
if is_nonnegative {
38-
// Accumulate each digit of the number from the least significant
39-
// to the most significant figure.
40-
for byte in buf.iter_mut().rev() {
41-
let n = self % base; // Get the current place value.
42-
self /= base; // Deaccumulate the number.
43-
byte.write(R::digit(n.to_u8())); // Store the digit in the buffer.
44-
curr -= 1;
45-
if self == 0 {
46-
// No more digits left to accumulate.
47-
break;
48-
};
49-
}
50-
} else {
51-
// Do the same as above, but accounting for two's complement.
52-
for byte in buf.iter_mut().rev() {
53-
let n = - (self % base); // Get the current place value.
54-
self /= base; // Deaccumulate the number.
55-
byte.write(R::digit(n.to_u8())); // Store the digit in the buffer.
56-
curr -= 1;
57-
if self == 0 {
58-
// No more digits left to accumulate.
59-
break;
60-
};
61-
}
62-
}
63-
let buf = &buf[curr..];
64-
// SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
65-
// valid UTF-8
66-
let buf = unsafe {
67-
str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
68-
};
69-
f.pad_integral(is_nonnegative, R::PREFIX, buf)
70-
}
7134
})*
7235
)
7336
}
7437
macro_rules! impl_uint {
7538
($($t:ident)*) => (
7639
$(impl DisplayInt for $t {
40+
fn zero() -> Self { 0 }
41+
fn from_u8(u: u8) -> Self { u as Self }
7742
fn to_u8(&self) -> u8 { *self as u8 }
7843
fn to_u16(&self) -> u16 { *self as u16 }
7944
fn to_u32(&self) -> u32 { *self as u32 }
8045
fn to_u64(&self) -> u64 { *self as u64 }
8146
fn to_u128(&self) -> u128 { *self as u128 }
82-
/// Format an integer using the radix using a formatter.
83-
fn fmt_int<R: GenericRadix>(mut self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84-
// The radix can be as low as 2, so we need a buffer of at least 128
85-
// characters for a base 2 number.
86-
let mut buf = [MaybeUninit::<u8>::uninit(); crate::mem::size_of::<$t>()];
87-
let mut curr = buf.len();
88-
let base = R::BASE as Self;
89-
// Accumulate each digit of the number from the least significant
90-
// to the most significant figure.
91-
for byte in buf.iter_mut().rev() {
92-
let n = self % base; // Get the current place value.
93-
self /= base; // Deaccumulate the number.
94-
byte.write(R::digit(n.to_u8())); // Store the digit in the buffer.
95-
curr -= 1;
96-
if self == 0 {
97-
// No more digits left to accumulate.
98-
break;
99-
};
100-
}
101-
let buf = &buf[curr..];
102-
// SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
103-
// valid UTF-8
104-
let buf = unsafe {
105-
str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
106-
};
107-
f.pad_integral(true, R::PREFIX, buf)
108-
}
10947
})*
11048
)
11149
}
@@ -126,8 +64,47 @@ trait GenericRadix: Sized {
12664
fn digit(x: u8) -> u8;
12765

12866
/// Format an integer using the radix using a formatter.
129-
fn fmt_int<T: DisplayInt>(&self, x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130-
x.fmt_int::<Self>(f)
67+
fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68+
// The radix can be as low as 2, so we need a buffer of at least 128
69+
// characters for a base 2 number.
70+
let zero = T::zero();
71+
let is_nonnegative = x >= zero;
72+
let mut buf = [MaybeUninit::<u8>::uninit(); 128];
73+
let mut curr = buf.len();
74+
let base = T::from_u8(Self::BASE);
75+
if is_nonnegative {
76+
// Accumulate each digit of the number from the least significant
77+
// to the most significant figure.
78+
for byte in buf.iter_mut().rev() {
79+
let n = x % base; // Get the current place value.
80+
x = x / base; // Deaccumulate the number.
81+
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
82+
curr -= 1;
83+
if x == zero {
84+
// No more digits left to accumulate.
85+
break;
86+
};
87+
}
88+
} else {
89+
// Do the same as above, but accounting for two's complement.
90+
for byte in buf.iter_mut().rev() {
91+
let n = zero - (x % base); // Get the current place value.
92+
x = x / base; // Deaccumulate the number.
93+
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
94+
curr -= 1;
95+
if x == zero {
96+
// No more digits left to accumulate.
97+
break;
98+
};
99+
}
100+
}
101+
let buf = &buf[curr..];
102+
// SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
103+
// valid UTF-8
104+
let buf = unsafe {
105+
str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len()))
106+
};
107+
f.pad_integral(is_nonnegative, Self::PREFIX, buf)
131108
}
132109
}
133110

@@ -624,11 +601,17 @@ fn fmt_u128_2(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt:
624601
fmt_u64_2(rem, &mut buf, &mut curr);
625602

626603
if n != 0 {
604+
// 0 pad up to point
605+
let target = (buf.len() - 19) as isize;
606+
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
607+
curr = target;
627608
let (n, rem) = udiv_1e9(n);
628609
fmt_u64_2(rem, &mut buf, &mut curr);
629610
// Should this following branch be annotated with unlikely?
630611
if n != 0 {
631-
curr -= 1;
612+
let target = (buf.len() - 38) as isize;
613+
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
614+
curr = target - 1;
632615
*buf_ptr.offset(curr) = (n as u8) + b'0';
633616
}
634617
}

0 commit comments

Comments
 (0)