33use crate :: fmt;
44use crate :: mem:: MaybeUninit ;
55use crate :: num:: flt2dec;
6+ use crate :: ops:: { Div , Rem , Sub } ;
67use crate :: ptr;
78use crate :: slice;
89use crate :: str;
910
1011#[ doc( hidden) ]
11- trait DisplayInt {
12+ trait DisplayInt :
13+ PartialEq + PartialOrd + Div < Output = Self > + Rem < Output = Self > + Sub < Output = Self > + Copy
14+ {
15+ fn zero ( ) -> Self ;
16+ fn from_u8 ( u : u8 ) -> Self ;
1217 fn to_u8 ( & self ) -> u8 ;
1318 fn to_u16 ( & self ) -> u16 ;
1419 fn to_u32 ( & self ) -> u32 ;
1520 fn to_u64 ( & self ) -> u64 ;
1621 fn to_u128 ( & self ) -> u128 ;
17-
18- fn fmt_int < R : GenericRadix > ( self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ;
1922}
2023
2124macro_rules! impl_int {
2225 ( $( $t: ident) * ) => (
2326 $( impl DisplayInt for $t {
27+ fn zero( ) -> Self { 0 }
28+ fn from_u8( u: u8 ) -> Self { u as Self }
2429 fn to_u8( & self ) -> u8 { * self as u8 }
2530 fn to_u16( & self ) -> u16 { * self as u16 }
2631 fn to_u32( & self ) -> u32 { * self as u32 }
2732 fn to_u64( & self ) -> u64 { * self as u64 }
2833 fn to_u128( & self ) -> u128 { * self as u128 }
29- /// Format an integer using the radix using a formatter.
30- fn fmt_int<R : GenericRadix >( mut self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
31- // The radix can be as low as 2, so we need a buffer of at least 128
32- // characters for a base 2 number.
33- let is_nonnegative = self >= 0 ;
34- let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; crate :: mem:: size_of:: <$t>( ) ] ;
35- let mut curr = buf. len( ) ;
36- let base = R :: BASE as Self ;
37- if is_nonnegative {
38- // Accumulate each digit of the number from the least significant
39- // to the most significant figure.
40- for byte in buf. iter_mut( ) . rev( ) {
41- let n = self % base; // Get the current place value.
42- self /= base; // Deaccumulate the number.
43- byte. write( R :: digit( n. to_u8( ) ) ) ; // Store the digit in the buffer.
44- curr -= 1 ;
45- if self == 0 {
46- // No more digits left to accumulate.
47- break ;
48- } ;
49- }
50- } else {
51- // Do the same as above, but accounting for two's complement.
52- for byte in buf. iter_mut( ) . rev( ) {
53- let n = - ( self % base) ; // Get the current place value.
54- self /= base; // Deaccumulate the number.
55- byte. write( R :: digit( n. to_u8( ) ) ) ; // Store the digit in the buffer.
56- curr -= 1 ;
57- if self == 0 {
58- // No more digits left to accumulate.
59- break ;
60- } ;
61- }
62- }
63- let buf = & buf[ curr..] ;
64- // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
65- // valid UTF-8
66- let buf = unsafe {
67- str :: from_utf8_unchecked( slice:: from_raw_parts( MaybeUninit :: first_ptr( buf) , buf. len( ) ) )
68- } ;
69- f. pad_integral( is_nonnegative, R :: PREFIX , buf)
70- }
7134 } ) *
7235 )
7336}
7437macro_rules! impl_uint {
7538 ( $( $t: ident) * ) => (
7639 $( impl DisplayInt for $t {
40+ fn zero( ) -> Self { 0 }
41+ fn from_u8( u: u8 ) -> Self { u as Self }
7742 fn to_u8( & self ) -> u8 { * self as u8 }
7843 fn to_u16( & self ) -> u16 { * self as u16 }
7944 fn to_u32( & self ) -> u32 { * self as u32 }
8045 fn to_u64( & self ) -> u64 { * self as u64 }
8146 fn to_u128( & self ) -> u128 { * self as u128 }
82- /// Format an integer using the radix using a formatter.
83- fn fmt_int<R : GenericRadix >( mut self , f: & mut fmt:: Formatter <' _>) -> fmt:: Result {
84- // The radix can be as low as 2, so we need a buffer of at least 128
85- // characters for a base 2 number.
86- let mut buf = [ MaybeUninit :: <u8 >:: uninit( ) ; crate :: mem:: size_of:: <$t>( ) ] ;
87- let mut curr = buf. len( ) ;
88- let base = R :: BASE as Self ;
89- // Accumulate each digit of the number from the least significant
90- // to the most significant figure.
91- for byte in buf. iter_mut( ) . rev( ) {
92- let n = self % base; // Get the current place value.
93- self /= base; // Deaccumulate the number.
94- byte. write( R :: digit( n. to_u8( ) ) ) ; // Store the digit in the buffer.
95- curr -= 1 ;
96- if self == 0 {
97- // No more digits left to accumulate.
98- break ;
99- } ;
100- }
101- let buf = & buf[ curr..] ;
102- // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
103- // valid UTF-8
104- let buf = unsafe {
105- str :: from_utf8_unchecked( slice:: from_raw_parts( MaybeUninit :: first_ptr( buf) , buf. len( ) ) )
106- } ;
107- f. pad_integral( true , R :: PREFIX , buf)
108- }
10947 } ) *
11048 )
11149}
@@ -126,8 +64,47 @@ trait GenericRadix: Sized {
12664 fn digit ( x : u8 ) -> u8 ;
12765
12866 /// Format an integer using the radix using a formatter.
129- fn fmt_int < T : DisplayInt > ( & self , x : T , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
130- x. fmt_int :: < Self > ( f)
67+ fn fmt_int < T : DisplayInt > ( & self , mut x : T , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
68+ // The radix can be as low as 2, so we need a buffer of at least 128
69+ // characters for a base 2 number.
70+ let zero = T :: zero ( ) ;
71+ let is_nonnegative = x >= zero;
72+ let mut buf = [ MaybeUninit :: < u8 > :: uninit ( ) ; 128 ] ;
73+ let mut curr = buf. len ( ) ;
74+ let base = T :: from_u8 ( Self :: BASE ) ;
75+ if is_nonnegative {
76+ // Accumulate each digit of the number from the least significant
77+ // to the most significant figure.
78+ for byte in buf. iter_mut ( ) . rev ( ) {
79+ let n = x % base; // Get the current place value.
80+ x = x / base; // Deaccumulate the number.
81+ byte. write ( Self :: digit ( n. to_u8 ( ) ) ) ; // Store the digit in the buffer.
82+ curr -= 1 ;
83+ if x == zero {
84+ // No more digits left to accumulate.
85+ break ;
86+ } ;
87+ }
88+ } else {
89+ // Do the same as above, but accounting for two's complement.
90+ for byte in buf. iter_mut ( ) . rev ( ) {
91+ let n = zero - ( x % base) ; // Get the current place value.
92+ x = x / base; // Deaccumulate the number.
93+ byte. write ( Self :: digit ( n. to_u8 ( ) ) ) ; // Store the digit in the buffer.
94+ curr -= 1 ;
95+ if x == zero {
96+ // No more digits left to accumulate.
97+ break ;
98+ } ;
99+ }
100+ }
101+ let buf = & buf[ curr..] ;
102+ // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
103+ // valid UTF-8
104+ let buf = unsafe {
105+ str:: from_utf8_unchecked ( slice:: from_raw_parts ( MaybeUninit :: first_ptr ( buf) , buf. len ( ) ) )
106+ } ;
107+ f. pad_integral ( is_nonnegative, Self :: PREFIX , buf)
131108 }
132109}
133110
@@ -624,11 +601,17 @@ fn fmt_u128_2(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt:
624601 fmt_u64_2 ( rem, & mut buf, & mut curr) ;
625602
626603 if n != 0 {
604+ // 0 pad up to point
605+ let target = ( buf. len ( ) - 19 ) as isize ;
606+ ptr:: write_bytes ( buf_ptr. offset ( target) , b'0' , ( curr - target) as usize ) ;
607+ curr = target;
627608 let ( n, rem) = udiv_1e9 ( n) ;
628609 fmt_u64_2 ( rem, & mut buf, & mut curr) ;
629610 // Should this following branch be annotated with unlikely?
630611 if n != 0 {
631- curr -= 1 ;
612+ let target = ( buf. len ( ) - 38 ) as isize ;
613+ ptr:: write_bytes ( buf_ptr. offset ( target) , b'0' , ( curr - target) as usize ) ;
614+ curr = target - 1 ;
632615 * buf_ptr. offset ( curr) = ( n as u8 ) + b'0' ;
633616 }
634617 }
0 commit comments