C9: saturate Timeframe::floor instead of overflowing at i64::MIN
Timeframe::floor computed `ts - ts.rem_euclid(bucket)`. For a timestamp within one bucket of i64::MIN the subtrahend is a positive remainder and the true boundary lies below i64::MIN, so the subtraction overflowed and panicked in debug builds. Switch to saturating_sub: the result clamps to i64::MIN in that practically unreachable case and stays exact everywhere else. floor keeps its infallible `-> i64` signature, so neither push path changes.
This commit is contained in:
@@ -48,8 +48,14 @@ impl Timeframe {
|
||||
}
|
||||
|
||||
/// Floor a raw timestamp to this timeframe's bucket boundary.
|
||||
///
|
||||
/// For a timestamp within one bucket of [`i64::MIN`] the mathematically
|
||||
/// exact boundary lies below `i64::MIN` and cannot be represented; in that
|
||||
/// (practically unreachable) case the result saturates at `i64::MIN`
|
||||
/// rather than overflowing and panicking in debug builds. `bucket` is
|
||||
/// always positive, so `rem_euclid` itself cannot panic.
|
||||
pub fn floor(self, ts: i64) -> i64 {
|
||||
ts - ts.rem_euclid(self.bucket)
|
||||
ts.saturating_sub(ts.rem_euclid(self.bucket))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +244,20 @@ mod tests {
|
||||
assert_eq!(tf.floor(100), 100);
|
||||
assert_eq!(tf.floor(150), 100);
|
||||
assert_eq!(tf.floor(250), 200);
|
||||
// Negative timestamps still floor toward negative infinity.
|
||||
assert_eq!(tf.floor(-1), -100);
|
||||
assert_eq!(tf.floor(-100), -100);
|
||||
assert_eq!(tf.floor(-101), -200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn floor_saturates_instead_of_overflowing_at_min() {
|
||||
let tf = Timeframe::new(100).unwrap();
|
||||
// The exact boundary lies below i64::MIN — must not panic.
|
||||
assert_eq!(tf.floor(i64::MIN), i64::MIN);
|
||||
// i64::MAX must not overflow either (subtracting a non-negative).
|
||||
let hi = tf.floor(i64::MAX);
|
||||
assert!(hi > i64::MAX - 100 && hi % 100 == 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user