@@ -1043,7 +1043,7 @@ impl fmt::Debug for Duration {
1043
1043
/// to the formatter's `width`, if specified.
1044
1044
fn fmt_decimal (
1045
1045
f : & mut fmt:: Formatter < ' _ > ,
1046
- mut integer_part : u64 ,
1046
+ integer_part : u64 ,
1047
1047
mut fractional_part : u32 ,
1048
1048
mut divisor : u32 ,
1049
1049
prefix : & str ,
@@ -1075,7 +1075,7 @@ impl fmt::Debug for Duration {
1075
1075
// normal floating point numbers. However, we only need to do work
1076
1076
// when rounding up. This happens if the first digit of the
1077
1077
// remaining ones is >= 5.
1078
- if fractional_part > 0 && fractional_part >= divisor * 5 {
1078
+ let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
1079
1079
// Round up the number contained in the buffer. We go through
1080
1080
// the buffer backwards and keep track of the carry.
1081
1081
let mut rev_pos = pos;
@@ -1099,9 +1099,18 @@ impl fmt::Debug for Duration {
1099
1099
// the whole buffer to '0's and need to increment the integer
1100
1100
// part.
1101
1101
if carry {
1102
- integer_part += 1 ;
1102
+ // If `integer_part == u64::MAX` and precision < 9, any
1103
+ // carry of the overflow during rounding of the
1104
+ // `fractional_part` into the `integer_part` will cause the
1105
+ // `integer_part` itself to overflow. Avoid this by using an
1106
+ // `Option<u64>`, with `None` representing `u64::MAX + 1`.
1107
+ integer_part. checked_add ( 1 )
1108
+ } else {
1109
+ Some ( integer_part)
1103
1110
}
1104
- }
1111
+ } else {
1112
+ Some ( integer_part)
1113
+ } ;
1105
1114
1106
1115
// Determine the end of the buffer: if precision is set, we just
1107
1116
// use as many digits from the buffer (capped to 9). If it isn't
@@ -1111,7 +1120,12 @@ impl fmt::Debug for Duration {
1111
1120
// This closure emits the formatted duration without emitting any
1112
1121
// padding (padding is calculated below).
1113
1122
let emit_without_padding = |f : & mut fmt:: Formatter < ' _ > | {
1114
- write ! ( f, "{}{}" , prefix, integer_part) ?;
1123
+ if let Some ( integer_part) = integer_part {
1124
+ write ! ( f, "{}{}" , prefix, integer_part) ?;
1125
+ } else {
1126
+ // u64::MAX + 1 == 18446744073709551616
1127
+ write ! ( f, "{}18446744073709551616" , prefix) ?;
1128
+ }
1115
1129
1116
1130
// Write the decimal point and the fractional part (if any).
1117
1131
if end > 0 {
@@ -1141,12 +1155,17 @@ impl fmt::Debug for Duration {
1141
1155
// 2. The postfix: can be "µs" so we have to count UTF8 characters.
1142
1156
let mut actual_w = prefix. len ( ) + postfix. chars ( ) . count ( ) ;
1143
1157
// 3. The integer part:
1144
- if let Some ( log) = integer_part. checked_ilog10 ( ) {
1145
- // integer_part is > 0, so has length log10(x)+1
1146
- actual_w += 1 + log as usize ;
1158
+ if let Some ( integer_part) = integer_part {
1159
+ if let Some ( log) = integer_part. checked_ilog10 ( ) {
1160
+ // integer_part is > 0, so has length log10(x)+1
1161
+ actual_w += 1 + log as usize ;
1162
+ } else {
1163
+ // integer_part is 0, so has length 1.
1164
+ actual_w += 1 ;
1165
+ }
1147
1166
} else {
1148
- // integer_part is 0 , so has length 1.
1149
- actual_w += 1 ;
1167
+ // integer_part is u64::MAX + 1 , so has length 20
1168
+ actual_w += 20 ;
1150
1169
}
1151
1170
// 4. The fractional part (if any):
1152
1171
if end > 0 {
0 commit comments