@@ -73,7 +73,7 @@ pub enum NumberAlignment {
73
73
74
74
pub struct SignedInt {
75
75
pub width : usize ,
76
- pub precision : usize ,
76
+ pub precision : Option < usize > ,
77
77
pub positive_sign : PositiveSign ,
78
78
pub alignment : NumberAlignment ,
79
79
}
@@ -82,8 +82,14 @@ impl Formatter<i64> for SignedInt {
82
82
fn fmt ( & self , writer : impl Write , x : i64 ) -> std:: io:: Result < ( ) > {
83
83
// -i64::MIN is actually 1 larger than i64::MAX, so we need to cast to i128 first.
84
84
let abs =( xas i128 ) . abs ( ) ;
85
- let s =if self . precision >0 {
86
- format ! ( "{abs:0>width$}" , width =self . precision)
85
+ let s =if let Some ( prec) =self . precision {
86
+ if prec >0 {
87
+ format ! ( "{abs:0>width$}" , width = prec)
88
+ } else if abs ==0 {
89
+ String :: from ( "" )
90
+ } else {
91
+ abs. to_string ( )
92
+ }
87
93
} else {
88
94
abs. to_string ( )
89
95
} ;
@@ -112,8 +118,8 @@ impl Formatter<i64> for SignedInt {
112
118
} ;
113
119
114
120
let precision =match precision{
115
- Some ( CanAsterisk :: Fixed ( x) ) =>x ,
116
- None =>0 ,
121
+ Some ( CanAsterisk :: Fixed ( x) ) =>Some ( x ) ,
122
+ None =>None ,
117
123
Some ( CanAsterisk :: Asterisk ( _) ) =>return Err ( FormatError :: WrongSpecType ) ,
118
124
} ;
119
125
@@ -129,12 +135,12 @@ impl Formatter<i64> for SignedInt {
129
135
pub struct UnsignedInt {
130
136
pub variant : UnsignedIntVariant ,
131
137
pub width : usize ,
132
- pub precision : usize ,
138
+ pub precision : Option < usize > ,
133
139
pub alignment : NumberAlignment ,
134
140
}
135
141
136
142
impl Formatter < u64 > for UnsignedInt {
137
- fn fmt ( & self , writer : impl Write , x : u64 ) -> std:: io:: Result < ( ) > {
143
+ fn fmt ( & self , mut writer : impl Write , x : u64 ) -> std:: io:: Result < ( ) > {
138
144
let mut s =match self . variant {
139
145
UnsignedIntVariant :: Decimal =>format ! ( "{x}" ) ,
140
146
UnsignedIntVariant :: Octal ( _) =>format ! ( "{x:o}" ) ,
@@ -149,11 +155,27 @@ impl Formatter<u64> for UnsignedInt {
149
155
let prefix =match ( x, self . variant ) {
150
156
( 1 .., UnsignedIntVariant :: Hexadecimal ( Case :: Lowercase , Prefix :: Yes ) ) =>"0x" ,
151
157
( 1 .., UnsignedIntVariant :: Hexadecimal ( Case :: Uppercase , Prefix :: Yes ) ) =>"0X" ,
152
- ( 1 .., UnsignedIntVariant :: Octal ( Prefix :: Yes ) ) if s. len ( ) >=self . precision =>"0" ,
158
+ ( 1 .., UnsignedIntVariant :: Octal ( Prefix :: Yes ) )
159
+ if s. len ( ) >=self . precision . unwrap_or ( 0 ) =>
160
+ {
161
+ "0"
162
+ }
153
163
_ =>"" ,
154
164
} ;
155
165
156
- s =format ! ( "{prefix}{s:0>width$}" , width =self . precision) ;
166
+ if let Some ( prec) =self . precision {
167
+ if prec ==0 && x ==0 {
168
+ s =match self . variant {
169
+ UnsignedIntVariant :: Octal ( Prefix :: Yes ) =>String :: from ( "0" ) ,
170
+ _ =>String :: from ( "" ) ,
171
+ } ;
172
+ } else {
173
+ s =format ! ( "{prefix}{s:0>width$}" , width = prec) ;
174
+ }
175
+ } else {
176
+ s =format ! ( "{prefix}{s:0>width$}" , width =0 ) ;
177
+ }
178
+
157
179
write_output ( writer, String :: new ( ) , s, self . width , self . alignment )
158
180
}
159
181
@@ -196,8 +218,8 @@ impl Formatter<u64> for UnsignedInt {
196
218
} ;
197
219
198
220
let precision =match precision{
199
- Some ( CanAsterisk :: Fixed ( x) ) =>x ,
200
- None =>0 ,
221
+ Some ( CanAsterisk :: Fixed ( x) ) =>Some ( x ) ,
222
+ None =>None ,
201
223
Some ( CanAsterisk :: Asterisk ( _) ) =>return Err ( FormatError :: WrongSpecType ) ,
202
224
} ;
203
225
@@ -726,7 +748,7 @@ mod test {
726
748
UnsignedInt {
727
749
variant : UnsignedIntVariant :: Octal ( Prefix :: Yes ) ,
728
750
width : 0 ,
729
- precision : 0 ,
751
+ precision : Some ( 0 ) ,
730
752
alignment : NumberAlignment :: Left ,
731
753
}
732
754
. fmt ( & mut s, x)
@@ -1165,12 +1187,41 @@ mod test {
1165
1187
}
1166
1188
1167
1189
#[ test]
1168
- #[ ignore ="Need issue #7509 to be fixed" ]
1169
1190
fn format_signed_int_precision_zero ( ) {
1170
1191
let format =Format :: < SignedInt , i64 > :: parse ( "%.0d" ) . unwrap ( ) ;
1171
1192
assert_eq ! ( fmt( & format, 123i64 ) , "123" ) ;
1172
1193
// From cppreference.com: "If both the converted value and the precision are 0 the conversion results in no characters."
1173
1194
assert_eq ! ( fmt( & format, 0i64 ) , "" ) ;
1195
+
1196
+ let format_plus =Format :: < SignedInt , i64 > :: parse ( "%+.0d\n " ) . unwrap ( ) ;
1197
+ assert_eq ! ( fmt( & format_plus, 0i64 ) , "+\n " ) ;
1198
+
1199
+ let format_pad =Format :: < SignedInt , i64 > :: parse ( "X%6.0dX" ) . unwrap ( ) ;
1200
+ assert_eq ! ( fmt( & format_pad, 0i64 ) , "X X" ) ;
1201
+ }
1202
+
1203
+ #[ test]
1204
+ fn format_unsigned_int_precision_zero ( ) {
1205
+ let format =Format :: < UnsignedInt , u64 > :: parse ( "%.0u" ) . unwrap ( ) ;
1206
+ assert_eq ! ( fmt( & format, 123u64 ) , "123" ) ;
1207
+ // From cppreference.com: "If both the converted value and the precision are 0 the conversion results in no characters."
1208
+ assert_eq ! ( fmt( & format, 0u64 ) , "" ) ;
1209
+
1210
+ let format_norm =Format :: < UnsignedInt , u64 > :: parse ( "%u" ) . unwrap ( ) ;
1211
+ assert_eq ! ( fmt( & format_norm, 123u64 ) , "123" ) ;
1212
+ assert_eq ! ( fmt( & format_norm, 0u64 ) , "0" ) ;
1213
+
1214
+ let format_pad =Format :: < UnsignedInt , u64 > :: parse ( "X%6.0uX" ) . unwrap ( ) ;
1215
+ assert_eq ! ( fmt( & format_pad, 0u64 ) , "X X" ) ;
1216
+
1217
+ let format_oct =Format :: < UnsignedInt , u64 > :: parse ( "%#.0o" ) . unwrap ( ) ;
1218
+ assert_eq ! ( fmt( & format_oct, 0u64 ) , "0" ) ;
1219
+
1220
+ let format_pad_oct =Format :: < UnsignedInt , u64 > :: parse ( "X%#6.0oX" ) . unwrap ( ) ;
1221
+ assert_eq ! ( fmt( & format_pad_oct, 0u64 ) , "X 0X" ) ;
1222
+
1223
+ let format_hex =Format :: < UnsignedInt , u64 > :: parse ( "%#.0x" ) . unwrap ( ) ;
1224
+ assert_eq ! ( fmt( & format_hex, 0u64 ) , "" ) ;
1174
1225
}
1175
1226
1176
1227
#[ test]
@@ -1192,7 +1243,7 @@ mod test {
1192
1243
}
1193
1244
1194
1245
#[ test]
1195
- #[ ignore ="Need issues #7509 and #7510 to be fixed" ]
1246
+ #[ ignore ="Needs issue #7510 to be fixed" ]
1196
1247
fn format_unsigned_int_broken ( ) {
1197
1248
// TODO: Merge this back into format_unsigned_int.
1198
1249
let f = |fmt_str : & str , n : u64 |{