Skip to content

Commit e83378b

Browse files
committed
vec![0;4] is a fast path.
After much tweaking found a way to get similar asm size as the u8 to_string implementation.
1 parent a678b9a commit e83378b

File tree

1 file changed

+20
-22
lines changed

1 file changed

+20
-22
lines changed

library/alloc/src/string.rs

+20-22
Original file line numberDiff line numberDiff line change
@@ -2243,39 +2243,37 @@ impl ToString for u8 {
22432243
}
22442244
}
22452245

2246-
// 2 digit decimal look up table
2247-
static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
2248-
2021222324252627282930313233343536373839\
2249-
4041424344454647484950515253545556575859\
2250-
6061626364656667686970717273747576777879\
2251-
8081828384858687888990919293949596979899";
2252-
22532246
#[stable(feature = "i8_to_string_specialization", since = "1.999.0")]
22542247
impl ToString for i8 {
22552248
#[inline]
22562249
fn to_string(&self) -> String {
2257-
let mut n = *self;
2258-
let mut vec: Vec<u8> = if n < 0 {
2259-
// convert the negative num to positive by summing 1 to it's 2 complement
2260-
// ( -128u8.abs() would panic )
2261-
n = (!n).wrapping_add(1);
2262-
let mut v = Vec::with_capacity(4);
2263-
v.push(b'-');
2264-
v
2250+
let mut vec = vec![0; 4];
2251+
let n = *self;
2252+
let mut free = 0;
2253+
let mut n: u8 = if n.is_negative() {
2254+
vec[free] = b'-';
2255+
free += 1;
2256+
i8::unsigned_abs(n)
22652257
} else {
2266-
Vec::with_capacity(3)
2258+
n as u8
22672259
};
2268-
let mut n = n as u8;
22692260
if n >= 10 {
22702261
if n >= 100 {
22712262
n -= 100;
2272-
vec.push(b'1');
2263+
vec[free] = b'1';
2264+
free += 1;
22732265
}
2274-
let nn = n * 2;
2275-
vec.extend_from_slice(&DEC_DIGITS_LUT[nn as usize..=nn as usize + 1]);
2276-
} else {
2277-
vec.push(b'0' + (n as u8));
2266+
debug_assert!(n < 100);
2267+
vec[free] = b'0' + n / 10;
2268+
free += 1;
2269+
n %= 10;
22782270
}
2271+
debug_assert!(n < 10);
2272+
vec[free] = b'0' + n;
2273+
free += 1;
2274+
vec.truncate(free);
2275+
2276+
// SAFETY: Vec only contains ascii so valid utf8
22792277
unsafe { String::from_utf8_unchecked(vec) }
22802278
}
22812279
}

0 commit comments

Comments
 (0)