Skip to content

Commit 59e7114

Browse files
Fix Debug impl of Duration for precisions > 9
Previously, the code would panic for high precision values. Now it has the same behavior as printing normal floating point values: if a high precision is specified, '0's are added.
1 parent 2a28ac3 commit 59e7114

File tree

2 files changed

+24
-11
lines changed

2 files changed

+24
-11
lines changed

src/libcore/tests/time.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,8 @@ fn debug_formatting_precision_zero() {
219219

220220
#[test]
221221
fn debug_formatting_precision_two() {
222-
// This might seem inconsistent with the other units, but printing
223-
// fractional digits for nano seconds would imply more precision than is
224-
// actually stored.
225-
assert_eq!(format!("{:.2?}", Duration::new(0, 0)), "0ns");
226-
assert_eq!(format!("{:.2?}", Duration::new(0, 123)), "123ns");
222+
assert_eq!(format!("{:.2?}", Duration::new(0, 0)), "0.00ns");
223+
assert_eq!(format!("{:.2?}", Duration::new(0, 123)), "123.00ns");
227224

228225
assert_eq!(format!("{:.2?}", Duration::new(0, 1_000)), "1.00µs");
229226
assert_eq!(format!("{:.2?}", Duration::new(0, 7_001)), "7.00µs");
@@ -244,3 +241,12 @@ fn debug_formatting_precision_two() {
244241
assert_eq!(format!("{:.2?}", Duration::new(2, 105_000_000)), "2.11s");
245242
assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s");
246243
}
244+
245+
#[test]
246+
fn debug_formatting_precision_high() {
247+
assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs");
248+
249+
assert_eq!(format!("{:.9?}", Duration::new(1, 000_000_000)), "1.000000000s");
250+
assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
251+
assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
252+
}

src/libcore/time.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,9 @@ impl fmt::Debug for Duration {
511511
// The next digit is written at this position
512512
let mut pos = 0;
513513

514-
// We can stop when there are no non-zero digits left or (when a
515-
// precision was set and we already emitted that many digits).
516-
while fractional_part > 0 && f.precision().map(|p| p > pos).unwrap_or(true) {
514+
// We keep writing digits into the buffer while there are non-zero
515+
// digits left and we haven't written enough digits yet.
516+
while fractional_part > 0 && pos < f.precision().unwrap_or(9) {
517517
// Write new digit into the buffer
518518
buf[pos] = b'0' + (fractional_part / divisor) as u8;
519519

@@ -556,9 +556,13 @@ impl fmt::Debug for Duration {
556556
}
557557
}
558558

559+
// Determine the end of the buffer: if precision is set, we just
560+
// use as many digits from the buffer (capped to 9). If it isn't
561+
// set, we only use all digits up to the last non-zero one.
562+
let end = f.precision().map(|p| ::cmp::min(p, 9)).unwrap_or(pos);
563+
559564
// If we haven't emitted a single fractional digit and the precision
560565
// wasn't set to a non-zero value, we don't print the decimal point.
561-
let end = f.precision().unwrap_or(pos);
562566
if end == 0 {
563567
write!(f, "{}", integer_part)
564568
} else {
@@ -568,7 +572,9 @@ impl fmt::Debug for Duration {
568572
::str::from_utf8_unchecked(&buf[..end])
569573
};
570574

571-
write!(f, "{}.{}", integer_part, s)
575+
// If the user request a precision > 9, we pad '0's at the end.
576+
let w = f.precision().unwrap_or(pos);
577+
write!(f, "{}.{:0<width$}", integer_part, s, width = w)
572578
}
573579
}
574580

@@ -587,7 +593,8 @@ impl fmt::Debug for Duration {
587593
fmt_decimal(f, self.nanos as u64 / 1_000, self.nanos % 1_000, 100)?;
588594
f.write_str("µs")
589595
} else {
590-
write!(f, "{}ns", self.nanos)
596+
fmt_decimal(f, self.nanos as u64, 0, 1)?;
597+
f.write_str("ns")
591598
}
592599
}
593600
}

0 commit comments

Comments
 (0)