@@ -566,7 +566,7 @@ mod imp {
566
566
impl_Exp ! ( i128 , u128 as u128 via to_u128 named exp_u128) ;
567
567
568
568
/// 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 ) {
570
570
let buf_ptr = MaybeUninit :: slice_as_mut_ptr ( buf) ;
571
571
let lut_ptr = DEC_DIGITS_LUT . as_ptr ( ) ;
572
572
assert ! ( * curr > 19 ) ;
@@ -655,77 +655,90 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
655
655
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
656
656
impl fmt:: Display for u128 {
657
657
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) )
659
662
}
660
663
}
661
664
662
665
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
663
666
impl fmt:: Display for i128 {
664
667
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
+
665
673
let is_nonnegative = * self >= 0 ;
666
674
let n = if is_nonnegative {
667
675
self . to_u128 ( )
668
676
} else {
669
677
// convert the negative num to positive by summing 1 to its 2s complement
670
678
( !self . to_u128 ( ) ) . wrapping_add ( 1 )
671
679
} ;
672
- fmt_u128 ( n , is_nonnegative , f )
680
+ f . pad_integral ( is_nonnegative , "" , n . _fmt ( & mut buf ) )
673
681
}
674
682
}
675
683
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) ;
701
700
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?
705
701
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
712
706
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
+ }
716
730
}
717
731
}
718
- }
719
732
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
+ }
729
742
}
730
743
731
744
/// Partition of `n` into n > 1e19 and rem <= 1e19
0 commit comments