Skip to content

Commit 1166a79

Browse files
Implement _fmt on u128
1 parent 40daf23 commit 1166a79

File tree

1 file changed

+63
-50
lines changed

1 file changed

+63
-50
lines changed

library/core/src/fmt/num.rs

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ mod imp {
566566
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
567567

568568
/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
569-
fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut usize) {
569+
fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit<u8>], curr: &mut usize) {
570570
let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
571571
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
572572
assert!(*curr > 19);
@@ -655,77 +655,90 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
655655
#[stable(feature = "rust1", since = "1.0.0")]
656656
impl fmt::Display for u128 {
657657
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
658-
fmt_u128(*self, true, f)
658+
const MAX_DEC_N: usize = u128::MAX.ilog(10) as usize + 1;
659+
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
660+
661+
f.pad_integral(true, "", self._fmt(&mut buf))
659662
}
660663
}
661664

662665
#[stable(feature = "rust1", since = "1.0.0")]
663666
impl fmt::Display for i128 {
664667
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668+
// This is not a typo, we use the maximum number of digits of `u128`, hence why we use
669+
// `u128::MAX`.
670+
const MAX_DEC_N: usize = u128::MAX.ilog(10) as usize + 1;
671+
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
672+
665673
let is_nonnegative = *self >= 0;
666674
let n = if is_nonnegative {
667675
self.to_u128()
668676
} else {
669677
// convert the negative num to positive by summing 1 to its 2s complement
670678
(!self.to_u128()).wrapping_add(1)
671679
};
672-
fmt_u128(n, is_nonnegative, f)
680+
f.pad_integral(is_nonnegative, "", n._fmt(&mut buf))
673681
}
674682
}
675683

676-
/// Specialized optimization for u128. Instead of taking two items at a time, it splits
677-
/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
678-
/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
679-
/// 10^20 > 2^64 > 10^19.
680-
fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681-
const MAX_DEC_N: usize = u128::MAX.ilog(10) as usize + 1;
682-
let mut buf = [MaybeUninit::<u8>::uninit(); MAX_DEC_N];
683-
let mut curr = buf.len();
684-
685-
let (n, rem) = udiv_1e19(n);
686-
parse_u64_into(rem, &mut buf, &mut curr);
687-
688-
if n != 0 {
689-
// 0 pad up to point
690-
let target = buf.len() - 19;
691-
// SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
692-
// remaining since it has length 39
693-
unsafe {
694-
ptr::write_bytes(
695-
MaybeUninit::slice_as_mut_ptr(&mut buf).add(target),
696-
b'0',
697-
curr - target,
698-
);
699-
}
700-
curr = target;
684+
impl u128 {
685+
/// Specialized optimization for u128. Instead of taking two items at a time, it splits
686+
/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
687+
/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
688+
/// 10^20 > 2^64 > 10^19.
689+
#[doc(hidden)]
690+
#[unstable(
691+
feature = "fmt_internals",
692+
reason = "specialized method meant to only be used by `SpecToString` implementation",
693+
issue = "none"
694+
)]
695+
pub fn _fmt<'a>(self, buf: &'a mut [MaybeUninit<u8>]) -> &'a str {
696+
let mut curr = buf.len();
697+
698+
let (n, rem) = udiv_1e19(self);
699+
parse_u64_into(rem, buf, &mut curr);
701700

702-
let (n, rem) = udiv_1e19(n);
703-
parse_u64_into(rem, &mut buf, &mut curr);
704-
// Should this following branch be annotated with unlikely?
705701
if n != 0 {
706-
let target = buf.len() - 38;
707-
// The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
708-
// buf `buf` is not used in this scope so we are good.
709-
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
710-
// SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
711-
// There can only be at most 1 digit remaining.
702+
// 0 pad up to point
703+
let target = buf.len() - 19;
704+
// SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
705+
// remaining since it has length 39
712706
unsafe {
713-
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
714-
curr = target - 1;
715-
*buf_ptr.add(curr) = (n as u8) + b'0';
707+
ptr::write_bytes(
708+
MaybeUninit::slice_as_mut_ptr(buf).add(target),
709+
b'0',
710+
curr - target,
711+
);
712+
}
713+
curr = target;
714+
715+
let (n, rem) = udiv_1e19(n);
716+
parse_u64_into(rem, buf, &mut curr);
717+
// Should this following branch be annotated with unlikely?
718+
if n != 0 {
719+
let target = buf.len() - 38;
720+
// The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
721+
// buf `buf` is not used in this scope so we are good.
722+
let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
723+
// SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
724+
// There can only be at most 1 digit remaining.
725+
unsafe {
726+
ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
727+
curr = target - 1;
728+
*buf_ptr.add(curr) = (n as u8) + b'0';
729+
}
716730
}
717731
}
718-
}
719732

720-
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
721-
// UTF-8 since `DEC_DIGITS_LUT` is
722-
let buf_slice = unsafe {
723-
str::from_utf8_unchecked(slice::from_raw_parts(
724-
MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr),
725-
buf.len() - curr,
726-
))
727-
};
728-
f.pad_integral(is_nonnegative, "", buf_slice)
733+
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
734+
// UTF-8 since `DEC_DIGITS_LUT` is
735+
unsafe {
736+
str::from_utf8_unchecked(slice::from_raw_parts(
737+
MaybeUninit::slice_as_mut_ptr(buf).add(curr),
738+
buf.len() - curr,
739+
))
740+
}
741+
}
729742
}
730743

731744
/// Partition of `n` into n > 1e19 and rem <= 1e19

0 commit comments

Comments
 (0)