libs (time)
duration_checked
This RFC adds the checked_*
methods already known from primitives like
usize
to Duration
.
Generally this helps when subtracting Duration
s which can be the case quite
often.
One abstract example would be executing a specific piece of code repeatedly after a constant amount of time.
Specific examples would be a network service or a rendering process emitting a constant amount of frames per second.
Example code would be as follows:
// This function is called repeatedly
fn render() {
// 10ms delay results in 100 frames per second
let wait_time = Duration::from_millis(10);
// `Instant` for elapsed time
let start = Instant::now();
// execute code here
render_and_output_frame();
// there are no negative `Duration`s so this does nothing if the elapsed
// time is longer than the defined `wait_time`
start.elapsed().checked_sub(wait_time).and_then(std::thread::sleep);
}
Of course it is also suitable to not introduce panic!()
s when adding
Duration
s.
The detailed design would be exactly as the current sub()
method, just
returning an Option<Duration>
and passing possible None
values from the
underlying primitive types:
impl Duration {
fn checked_sub(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
let nanos = if self.nanos >= rhs.nanos {
self.nanos - rhs.nanos
} else {
if let Some(secs) = secs.checked_sub(1) {
self.nanos + NANOS_PER_SEC - rhs.nanos
}
else {
return None;
}
};
debug_assert!(nanos < NANOS_PER_SEC);
Some(Duration { secs: secs, nanos: nanos })
}
else {
None
}
}
}
The same accounts for all other added methods, namely:
checked_add()
checked_sub()
checked_mul()
checked_div()
None
.
The alternatives are simply not doing this and forcing the programmer to code the check on their behalf. This is not what you want.
None
.