@@ -566,7 +566,7 @@ mod imp {
566566impl_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" ) ]
656656impl 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" ) ]
663666impl 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