@@ -1049,11 +1049,16 @@ impl fmt::Debug for Duration {
1049
1049
/// `divisor` must not be above 100_000_000. It also should be a power
1050
1050
/// of 10, everything else doesn't make sense. `fractional_part` has
1051
1051
/// to be less than `10 * divisor`!
1052
+ ///
1053
+ /// A prefix and postfix may be added. The whole thing is padded
1054
+ /// to the formatter's `width`, if specified.
1052
1055
fn fmt_decimal (
1053
1056
f : & mut fmt:: Formatter < ' _ > ,
1054
1057
mut integer_part : u64 ,
1055
1058
mut fractional_part : u32 ,
1056
1059
mut divisor : u32 ,
1060
+ prefix : & str ,
1061
+ postfix : & str ,
1057
1062
) -> fmt:: Result {
1058
1063
// Encode the fractional part into a temporary buffer. The buffer
1059
1064
// only need to hold 9 elements, because `fractional_part` has to
@@ -1114,48 +1119,91 @@ impl fmt::Debug for Duration {
1114
1119
// set, we only use all digits up to the last non-zero one.
1115
1120
let end = f. precision ( ) . map ( |p| crate :: cmp:: min ( p, 9 ) ) . unwrap_or ( pos) ;
1116
1121
1117
- // If we haven't emitted a single fractional digit and the precision
1118
- // wasn't set to a non-zero value, we don't print the decimal point.
1119
- if end == 0 {
1120
- write ! ( f, "{}" , integer_part)
1121
- } else {
1122
- // SAFETY: We are only writing ASCII digits into the buffer and it was
1123
- // initialized with '0's, so it contains valid UTF8.
1124
- let s = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..end] ) } ;
1122
+ // This closure emits the formatted duration without emitting any
1123
+ // padding (padding is calculated below).
1124
+ let emit_without_padding = |f : & mut fmt:: Formatter < ' _ > | {
1125
+ write ! ( f, "{}{}" , prefix, integer_part) ?;
1126
+
1127
+ // Write the decimal point and the fractional part (if any).
1128
+ if end > 0 {
1129
+ // SAFETY: We are only writing ASCII digits into the buffer and
1130
+ // it was initialized with '0's, so it contains valid UTF8.
1131
+ let s = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..end] ) } ;
1132
+
1133
+ // If the user request a precision > 9, we pad '0's at the end.
1134
+ let w = f. precision ( ) . unwrap_or ( pos) ;
1135
+ write ! ( f, ".{:0<width$}" , s, width = w) ?;
1136
+ }
1125
1137
1126
- // If the user request a precision > 9, we pad '0's at the end.
1127
- let w = f. precision ( ) . unwrap_or ( pos) ;
1128
- write ! ( f, "{}.{:0<width$}" , integer_part, s, width = w)
1138
+ write ! ( f, "{}" , postfix)
1139
+ } ;
1140
+
1141
+ match f. width ( ) {
1142
+ None => {
1143
+ // No `width` specified. There's no need to calculate the
1144
+ // length of the output in this case, just emit it.
1145
+ emit_without_padding ( f)
1146
+ }
1147
+ Some ( requested_w) => {
1148
+ // A `width` was specified. Calculate the actual width of
1149
+ // the output in order to calculate the required padding.
1150
+ // It consists of 4 parts:
1151
+ // 1. The prefix: is either "+" or "", so we can just use len().
1152
+ // 2. The postfix: can be "µs" so we have to count UTF8 characters.
1153
+ let mut actual_w = prefix. len ( ) + postfix. chars ( ) . count ( ) ;
1154
+ // 3. The integer part:
1155
+ if let Some ( log) = integer_part. checked_log10 ( ) {
1156
+ // integer_part is > 0, so has length log10(x)+1
1157
+ actual_w += 1 + log as usize ;
1158
+ } else {
1159
+ // integer_part is 0, so has length 1.
1160
+ actual_w += 1 ;
1161
+ }
1162
+ // 4. The fractional part (if any):
1163
+ if end > 0 {
1164
+ let frac_part_w = f. precision ( ) . unwrap_or ( pos) ;
1165
+ actual_w += 1 + frac_part_w;
1166
+ }
1167
+
1168
+ if requested_w <= actual_w {
1169
+ // Output is already longer than `width`, so don't pad.
1170
+ emit_without_padding ( f)
1171
+ } else {
1172
+ // We need to add padding. Use the `Formatter::padding` helper function.
1173
+ let default_align = crate :: fmt:: rt:: v1:: Alignment :: Left ;
1174
+ let post_padding = f. padding ( requested_w - actual_w, default_align) ?;
1175
+ emit_without_padding ( f) ?;
1176
+ post_padding. write ( f)
1177
+ }
1178
+ }
1129
1179
}
1130
1180
}
1131
1181
1132
1182
// Print leading '+' sign if requested
1133
- if f. sign_plus ( ) {
1134
- write ! ( f, "+" ) ?;
1135
- }
1183
+ let prefix = if f. sign_plus ( ) { "+" } else { "" } ;
1136
1184
1137
1185
if self . secs > 0 {
1138
- fmt_decimal ( f, self . secs , self . nanos , NANOS_PER_SEC / 10 ) ?;
1139
- f. write_str ( "s" )
1186
+ fmt_decimal ( f, self . secs , self . nanos , NANOS_PER_SEC / 10 , prefix, "s" )
1140
1187
} else if self . nanos >= NANOS_PER_MILLI {
1141
1188
fmt_decimal (
1142
1189
f,
1143
1190
( self . nanos / NANOS_PER_MILLI ) as u64 ,
1144
1191
self . nanos % NANOS_PER_MILLI ,
1145
1192
NANOS_PER_MILLI / 10 ,
1146
- ) ?;
1147
- f. write_str ( "ms" )
1193
+ prefix,
1194
+ "ms" ,
1195
+ )
1148
1196
} else if self . nanos >= NANOS_PER_MICRO {
1149
1197
fmt_decimal (
1150
1198
f,
1151
1199
( self . nanos / NANOS_PER_MICRO ) as u64 ,
1152
1200
self . nanos % NANOS_PER_MICRO ,
1153
1201
NANOS_PER_MICRO / 10 ,
1154
- ) ?;
1155
- f. write_str ( "µs" )
1202
+ prefix,
1203
+ "µs" ,
1204
+ )
1156
1205
} else {
1157
- fmt_decimal ( f, self . nanos as u64 , 0 , 1 ) ?;
1158
- f. write_str ( "ns" )
1206
+ fmt_decimal ( f, self . nanos as u64 , 0 , 1 , prefix, "ns" )
1159
1207
}
1160
1208
}
1161
1209
}
0 commit comments