Skip to content

Commit 246caf9

Browse files
committed
fmt of non-decimals is always non-negative due to the two's-complement output
1 parent 119574f commit 246caf9

File tree

1 file changed

+48
-40
lines changed

1 file changed

+48
-40
lines changed

library/core/src/fmt/num.rs

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -54,44 +54,31 @@ unsafe trait GenericRadix: Sized {
5454
/// Converts an integer to corresponding radix digit.
5555
fn digit(x: u8) -> u8;
5656

57-
/// Format an integer using the radix using a formatter.
57+
/// Format an unsigned integer using the radix using a formatter.
5858
fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5959
// The radix can be as low as 2, so we need a buffer of at least 128
6060
// characters for a base 2 number.
6161
let zero = T::zero();
62-
let is_nonnegative = x >= zero;
6362
let mut buf = [MaybeUninit::<u8>::uninit(); 128];
6463
let mut offset = buf.len();
6564
let base = T::from_u8(Self::BASE);
66-
if is_nonnegative {
67-
// Accumulate each digit of the number from the least significant
68-
// to the most significant figure.
69-
loop {
70-
let n = x % base; // Get the current place value.
71-
x = x / base; // Deaccumulate the number.
72-
offset -= 1;
73-
buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
74-
if x == zero {
75-
// No more digits left to accumulate.
76-
break;
77-
};
78-
}
79-
} else {
80-
// Do the same as above, but accounting for two's complement.
81-
loop {
82-
let n = zero - (x % base); // Get the current place value.
83-
x = x / base; // Deaccumulate the number.
84-
offset -= 1;
85-
buf[offset].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
86-
if x == zero {
87-
// No more digits left to accumulate.
88-
break;
89-
};
90-
}
65+
66+
// Accumulate each digit of the number from the least significant
67+
// to the most significant figure.
68+
loop {
69+
let n = x % base; // Get the current place value.
70+
x = x / base; // Deaccumulate the number.
71+
curr -= 1;
72+
buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
73+
if x == zero {
74+
// No more digits left to accumulate.
75+
break;
76+
};
9177
}
78+
9279
// SAFETY: Starting from `offset`, all elements of the slice have been set.
93-
let buf_slice = unsafe { slice_buffer_to_str(&buf, offset) };
94-
f.pad_integral(is_nonnegative, Self::PREFIX, buf_slice)
80+
let digits = unsafe { slice_buffer_to_str(&buf, offset) };
81+
f.pad_integral(is_nonnegative, Self::PREFIX, digits)
9582
}
9683
}
9784

@@ -132,27 +119,48 @@ radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' +
132119
radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
133120

134121
macro_rules! int_base {
135-
(fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
122+
(fmt::$Trait:ident for $T:ident -> $Radix:ident) => {
136123
#[stable(feature = "rust1", since = "1.0.0")]
137124
impl fmt::$Trait for $T {
138125
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139-
$Radix.fmt_int(*self as $U, f)
126+
$Radix.fmt_int(*self, f)
140127
}
141128
}
142129
};
143130
}
144131

145132
macro_rules! integer {
146133
($Int:ident, $Uint:ident) => {
147-
int_base! { fmt::Binary for $Int as $Uint -> Binary }
148-
int_base! { fmt::Octal for $Int as $Uint -> Octal }
149-
int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex }
150-
int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex }
151-
152-
int_base! { fmt::Binary for $Uint as $Uint -> Binary }
153-
int_base! { fmt::Octal for $Uint as $Uint -> Octal }
154-
int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
155-
int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
134+
int_base! { fmt::Binary for $Uint -> Binary }
135+
int_base! { fmt::Octal for $Uint -> Octal }
136+
int_base! { fmt::LowerHex for $Uint -> LowerHex }
137+
int_base! { fmt::UpperHex for $Uint -> UpperHex }
138+
139+
// Format signed integers as unsigned (two’s complement representation).
140+
#[stable(feature = "rust1", since = "1.0.0")]
141+
impl fmt::Binary for $Int {
142+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143+
fmt::Binary::fmt(&(*self as $Uint), f)
144+
}
145+
}
146+
#[stable(feature = "rust1", since = "1.0.0")]
147+
impl fmt::Octal for $Int {
148+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149+
fmt::Octal::fmt(&(*self as $Uint), f)
150+
}
151+
}
152+
#[stable(feature = "rust1", since = "1.0.0")]
153+
impl fmt::LowerHex for $Int {
154+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155+
fmt::LowerHex::fmt(&(*self as $Uint), f)
156+
}
157+
}
158+
#[stable(feature = "rust1", since = "1.0.0")]
159+
impl fmt::UpperHex for $Int {
160+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161+
fmt::UpperHex::fmt(&(*self as $Uint), f)
162+
}
163+
}
156164
};
157165
}
158166
integer! { isize, usize }

0 commit comments

Comments
 (0)