Skip to content

Commit fb14963

Browse files
committed
fmt of non-decimals is always non-negative due to the two's-complement output
1 parent 36b2163 commit fb14963

File tree

1 file changed

+47
-39
lines changed

1 file changed

+47
-39
lines changed

library/core/src/fmt/num.rs

Lines changed: 47 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -53,41 +53,28 @@ unsafe trait GenericRadix: Sized {
5353
/// Converts an integer to corresponding radix digit.
5454
fn digit(x: u8) -> u8;
5555

56-
/// Format an integer using the radix using a formatter.
56+
/// Format an unsigned integer using the radix using a formatter.
5757
fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5858
// The radix can be as low as 2, so we need a buffer of at least 128
5959
// characters for a base 2 number.
6060
let zero = T::zero();
61-
let is_nonnegative = x >= zero;
6261
let mut buf = [MaybeUninit::<u8>::uninit(); 128];
6362
let mut curr = buf.len();
6463
let base = T::from_u8(Self::BASE);
65-
if is_nonnegative {
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-
};
77-
}
78-
} else {
79-
// Do the same as above, but accounting for two's complement.
80-
loop {
81-
let n = zero - (x % base); // Get the current place value.
82-
x = x / base; // Deaccumulate the number.
83-
curr -= 1;
84-
buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
85-
if x == zero {
86-
// No more digits left to accumulate.
87-
break;
88-
};
89-
}
64+
65+
// Accumulate each digit of the number from the least significant
66+
// to the most significant figure.
67+
loop {
68+
let n = x % base; // Get the current place value.
69+
x = x / base; // Deaccumulate the number.
70+
curr -= 1;
71+
buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
72+
if x == zero {
73+
// No more digits left to accumulate.
74+
break;
75+
};
9076
}
77+
9178
// SAFETY: `curr` is initialized to `buf.len()` and is only decremented, so it can't overflow. It is
9279
// decremented exactly once for each digit. Since u128 is the widest fixed width integer format supported,
9380
// the maximum number of digits (bits) is 128 for base-2, so `curr` won't underflow as well.
@@ -100,7 +87,7 @@ unsafe trait GenericRadix: Sized {
10087
buf.len(),
10188
))
10289
};
103-
f.pad_integral(is_nonnegative, Self::PREFIX, buf)
90+
f.pad_integral(true, Self::PREFIX, buf)
10491
}
10592
}
10693

@@ -141,27 +128,48 @@ radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' +
141128
radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
142129

143130
macro_rules! int_base {
144-
(fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
131+
(fmt::$Trait:ident for $T:ident -> $Radix:ident) => {
145132
#[stable(feature = "rust1", since = "1.0.0")]
146133
impl fmt::$Trait for $T {
147134
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148-
$Radix.fmt_int(*self as $U, f)
135+
$Radix.fmt_int(*self, f)
149136
}
150137
}
151138
};
152139
}
153140

154141
macro_rules! integer {
155142
($Int:ident, $Uint:ident) => {
156-
int_base! { fmt::Binary for $Int as $Uint -> Binary }
157-
int_base! { fmt::Octal for $Int as $Uint -> Octal }
158-
int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex }
159-
int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex }
160-
161-
int_base! { fmt::Binary for $Uint as $Uint -> Binary }
162-
int_base! { fmt::Octal for $Uint as $Uint -> Octal }
163-
int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
164-
int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
143+
int_base! { fmt::Binary for $Uint -> Binary }
144+
int_base! { fmt::Octal for $Uint -> Octal }
145+
int_base! { fmt::LowerHex for $Uint -> LowerHex }
146+
int_base! { fmt::UpperHex for $Uint -> UpperHex }
147+
148+
// Format signed integers as unsigned (two’s complement representation).
149+
#[stable(feature = "rust1", since = "1.0.0")]
150+
impl fmt::Binary for $Int {
151+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152+
fmt::Binary::fmt(&(*self as $Uint), f)
153+
}
154+
}
155+
#[stable(feature = "rust1", since = "1.0.0")]
156+
impl fmt::Octal for $Int {
157+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158+
fmt::Octal::fmt(&(*self as $Uint), f)
159+
}
160+
}
161+
#[stable(feature = "rust1", since = "1.0.0")]
162+
impl fmt::LowerHex for $Int {
163+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164+
fmt::LowerHex::fmt(&(*self as $Uint), f)
165+
}
166+
}
167+
#[stable(feature = "rust1", since = "1.0.0")]
168+
impl fmt::UpperHex for $Int {
169+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170+
fmt::UpperHex::fmt(&(*self as $Uint), f)
171+
}
172+
}
165173
};
166174
}
167175
integer! { isize, usize }

0 commit comments

Comments
 (0)