3
3
use crate :: fmt;
4
4
use crate :: mem:: MaybeUninit ;
5
5
use crate :: num:: flt2dec;
6
+ use crate :: ops:: { Div , Rem , Sub } ;
6
7
use crate :: ptr;
7
8
use crate :: slice;
8
9
use crate :: str;
9
10
10
11
#[ 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 ;
12
17
fn to_u8 ( & self ) -> u8 ;
13
18
fn to_u16 ( & self ) -> u16 ;
14
19
fn to_u32 ( & self ) -> u32 ;
15
20
fn to_u64 ( & self ) -> u64 ;
16
21
fn to_u128 ( & self ) -> u128 ;
17
-
18
- fn fmt_int < R : GenericRadix > ( self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ;
19
22
}
20
23
21
24
macro_rules! impl_int {
22
25
( $( $t: ident) * ) => (
23
26
$( impl DisplayInt for $t {
27
+ fn zero( ) -> Self { 0 }
28
+ fn from_u8( u: u8 ) -> Self { u as Self }
24
29
fn to_u8( & self ) -> u8 { * self as u8 }
25
30
fn to_u16( & self ) -> u16 { * self as u16 }
26
31
fn to_u32( & self ) -> u32 { * self as u32 }
27
32
fn to_u64( & self ) -> u64 { * self as u64 }
28
33
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
- }
71
34
} ) *
72
35
)
73
36
}
74
37
macro_rules! impl_uint {
75
38
( $( $t: ident) * ) => (
76
39
$( impl DisplayInt for $t {
40
+ fn zero( ) -> Self { 0 }
41
+ fn from_u8( u: u8 ) -> Self { u as Self }
77
42
fn to_u8( & self ) -> u8 { * self as u8 }
78
43
fn to_u16( & self ) -> u16 { * self as u16 }
79
44
fn to_u32( & self ) -> u32 { * self as u32 }
80
45
fn to_u64( & self ) -> u64 { * self as u64 }
81
46
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
- }
109
47
} ) *
110
48
)
111
49
}
@@ -126,8 +64,47 @@ trait GenericRadix: Sized {
126
64
fn digit ( x : u8 ) -> u8 ;
127
65
128
66
/// 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)
131
108
}
132
109
}
133
110
@@ -624,11 +601,17 @@ fn fmt_u128_2(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt:
624
601
fmt_u64_2 ( rem, & mut buf, & mut curr) ;
625
602
626
603
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;
627
608
let ( n, rem) = udiv_1e9 ( n) ;
628
609
fmt_u64_2 ( rem, & mut buf, & mut curr) ;
629
610
// Should this following branch be annotated with unlikely?
630
611
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 ;
632
615
* buf_ptr. offset ( curr) = ( n as u8 ) + b'0' ;
633
616
}
634
617
}
0 commit comments