Skip to content

Commit c00da0b

Browse files
authored
Fix issue with negative nanos in Duration::try_from(), and add tests (#803)
* Fix issue with negative nanos in Duration::try_from(), and add a unit test * add proptest for negative nanos * PR comment: remove spurious dbg
1 parent 963a2cf commit c00da0b

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

prost-types/src/lib.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl TryFrom<Duration> for time::Duration {
104104
/// Converts a `Duration` to a `std::time::Duration`, failing if the duration is negative.
105105
fn try_from(mut duration: Duration) -> Result<time::Duration, DurationError> {
106106
duration.normalize();
107-
if duration.seconds >= 0 {
107+
if duration.seconds >= 0 && duration.nanos >= 0 {
108108
Ok(time::Duration::new(
109109
duration.seconds as u64,
110110
duration.nanos as u32,
@@ -454,6 +454,51 @@ mod tests {
454454
)
455455
}
456456
}
457+
458+
#[test]
459+
fn check_duration_roundtrip_nanos(
460+
nanos in u32::arbitrary(),
461+
) {
462+
let seconds = 0;
463+
let std_duration = std::time::Duration::new(seconds, nanos);
464+
let prost_duration = match Duration::try_from(std_duration) {
465+
Ok(duration) => duration,
466+
Err(_) => return Err(TestCaseError::reject("duration out of range")),
467+
};
468+
prop_assert_eq!(time::Duration::try_from(prost_duration.clone()).unwrap(), std_duration);
469+
470+
if std_duration != time::Duration::default() {
471+
let neg_prost_duration = Duration {
472+
seconds: -prost_duration.seconds,
473+
nanos: -prost_duration.nanos,
474+
};
475+
476+
prop_assert!(
477+
matches!(
478+
time::Duration::try_from(neg_prost_duration),
479+
Err(DurationError::NegativeDuration(d)) if d == std_duration,
480+
)
481+
)
482+
}
483+
}
484+
}
485+
486+
#[cfg(feature = "std")]
487+
#[test]
488+
fn check_duration_try_from_negative_nanos() {
489+
let seconds: u64 = 0;
490+
let nanos: u32 = 1;
491+
let std_duration = std::time::Duration::new(seconds, nanos);
492+
493+
let neg_prost_duration = Duration {
494+
seconds: 0,
495+
nanos: -1,
496+
};
497+
498+
assert!(matches!(
499+
time::Duration::try_from(neg_prost_duration),
500+
Err(DurationError::NegativeDuration(d)) if d == std_duration,
501+
))
457502
}
458503

459504
#[cfg(feature = "std")]

0 commit comments

Comments
 (0)