@@ -1049,11 +1049,16 @@ impl fmt::Debug for Duration {
10491049 /// `divisor` must not be above 100_000_000. It also should be a power
10501050 /// of 10, everything else doesn't make sense. `fractional_part` has
10511051 /// 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.
10521055 fn fmt_decimal (
10531056 f : & mut fmt:: Formatter < ' _ > ,
10541057 mut integer_part : u64 ,
10551058 mut fractional_part : u32 ,
10561059 mut divisor : u32 ,
1060+ prefix : & str ,
1061+ postfix : & str ,
10571062 ) -> fmt:: Result {
10581063 // Encode the fractional part into a temporary buffer. The buffer
10591064 // only need to hold 9 elements, because `fractional_part` has to
@@ -1114,48 +1119,91 @@ impl fmt::Debug for Duration {
11141119 // set, we only use all digits up to the last non-zero one.
11151120 let end = f. precision ( ) . map ( |p| crate :: cmp:: min ( p, 9 ) ) . unwrap_or ( pos) ;
11161121
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+ }
11251137
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+ }
11291179 }
11301180 }
11311181
11321182 // Print leading '+' sign if requested
1133- if f. sign_plus ( ) {
1134- write ! ( f, "+" ) ?;
1135- }
1183+ let prefix = if f. sign_plus ( ) { "+" } else { "" } ;
11361184
11371185 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" )
11401187 } else if self . nanos >= NANOS_PER_MILLI {
11411188 fmt_decimal (
11421189 f,
11431190 ( self . nanos / NANOS_PER_MILLI ) as u64 ,
11441191 self . nanos % NANOS_PER_MILLI ,
11451192 NANOS_PER_MILLI / 10 ,
1146- ) ?;
1147- f. write_str ( "ms" )
1193+ prefix,
1194+ "ms" ,
1195+ )
11481196 } else if self . nanos >= NANOS_PER_MICRO {
11491197 fmt_decimal (
11501198 f,
11511199 ( self . nanos / NANOS_PER_MICRO ) as u64 ,
11521200 self . nanos % NANOS_PER_MICRO ,
11531201 NANOS_PER_MICRO / 10 ,
1154- ) ?;
1155- f. write_str ( "µs" )
1202+ prefix,
1203+ "µs" ,
1204+ )
11561205 } 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" )
11591207 }
11601208 }
11611209}
0 commit comments