Skip to content

Commit

Permalink
Fix Debug impl of Duration for precisions > 9
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
LukasKalbertodt committed May 16, 2018
1 parent 2a28ac3 commit 59e7114
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
16 changes: 11 additions & 5 deletions src/libcore/tests/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,8 @@ fn debug_formatting_precision_zero() {

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

assert_eq!(format!("{:.2?}", Duration::new(0, 1_000)), "1.00µs");
assert_eq!(format!("{:.2?}", Duration::new(0, 7_001)), "7.00µs");
Expand All @@ -244,3 +241,12 @@ fn debug_formatting_precision_two() {
assert_eq!(format!("{:.2?}", Duration::new(2, 105_000_000)), "2.11s");
assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s");
}

#[test]
fn debug_formatting_precision_high() {
assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs");

assert_eq!(format!("{:.9?}", Duration::new(1, 000_000_000)), "1.000000000s");
assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
}
19 changes: 13 additions & 6 deletions src/libcore/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,9 @@ impl fmt::Debug for Duration {
// The next digit is written at this position
let mut pos = 0;

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

Expand Down Expand Up @@ -556,9 +556,13 @@ impl fmt::Debug for Duration {
}
}

// Determine the end of the buffer: if precision is set, we just
// use as many digits from the buffer (capped to 9). If it isn't
// set, we only use all digits up to the last non-zero one.
let end = f.precision().map(|p| ::cmp::min(p, 9)).unwrap_or(pos);

// If we haven't emitted a single fractional digit and the precision
// wasn't set to a non-zero value, we don't print the decimal point.
let end = f.precision().unwrap_or(pos);
if end == 0 {
write!(f, "{}", integer_part)
} else {
Expand All @@ -568,7 +572,9 @@ impl fmt::Debug for Duration {
::str::from_utf8_unchecked(&buf[..end])
};

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

Expand All @@ -587,7 +593,8 @@ impl fmt::Debug for Duration {
fmt_decimal(f, self.nanos as u64 / 1_000, self.nanos % 1_000, 100)?;
f.write_str("µs")
} else {
write!(f, "{}ns", self.nanos)
fmt_decimal(f, self.nanos as u64, 0, 1)?;
f.write_str("ns")
}
}
}

0 comments on commit 59e7114

Please sign in to comment.