Skip to content

Commit 3a9cbee

Browse files
committed
Merge branch 'checked_sub' of https://github.com/benaryorg/rfcs
2 parents 30221dc + bde7d91 commit 3a9cbee

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

text/0000-duration-checked-sub.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
- Feature Name: duration_checked_sub
2+
- Start Date: 2016-06-04
3+
- RFC PR:
4+
- Rust Issue:
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
This RFC adds the `checked_*` methods already known from primitives like
10+
`usize` to `Duration`.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
Generally this helps when subtracting `Duration`s which can be the case quite
16+
often.
17+
18+
One abstract example would be executing a specific piece of code repeatedly
19+
after a constant amount of time.
20+
21+
Specific examples would be a network service or a rendering process emitting a
22+
constant amount of frames per second.
23+
24+
Example code would be as follows:
25+
26+
```rust
27+
28+
// This function is called repeatedly
29+
fn render() {
30+
// 10ms delay results in 100 frames per second
31+
let wait_time = Duration::from_millis(10);
32+
33+
// `Instant` for elapsed time
34+
let start = Instant::now();
35+
36+
// execute code here
37+
render_and_output_frame();
38+
39+
// there are no negative `Duration`s so this does nothing if the elapsed
40+
// time is longer than the defined `wait_time`
41+
start.elapsed().checked_sub(wait_time).and_then(std::thread::sleep);
42+
}
43+
```
44+
45+
Of course it is also suitable to not introduce `panic!()`s when adding
46+
`Duration`s.
47+
48+
# Detailed design
49+
[design]: #detailed-design
50+
51+
The detailed design would be exactly as the current `sub()` method, just
52+
returning an `Option<Duration>` and passing possible `None` values from the
53+
underlying primitive types:
54+
55+
```rust
56+
impl Duration {
57+
fn checked_sub(self, rhs: Duration) -> Option<Duration> {
58+
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
59+
let nanos = if self.nanos >= rhs.nanos {
60+
self.nanos - rhs.nanos
61+
} else {
62+
if let Some(secs) = secs.checked_sub(1) {
63+
self.nanos + NANOS_PER_SEC - rhs.nanos
64+
}
65+
else {
66+
return None;
67+
}
68+
};
69+
debug_assert!(nanos < NANOS_PER_SEC);
70+
Some(Duration { secs: secs, nanos: nanos })
71+
}
72+
else {
73+
None
74+
}
75+
}
76+
}
77+
```
78+
79+
The same accounts for all other added methods, namely:
80+
81+
- `checked_add()`
82+
- `checked_sub()`
83+
- `checked_mul()`
84+
- `checked_div()`
85+
86+
# Drawbacks
87+
[drawbacks]: #drawbacks
88+
89+
`None`.
90+
91+
# Alternatives
92+
[alternatives]: #alternatives
93+
94+
The alternatives are simply not doing this and forcing the programmer to code
95+
the check on their behalf.
96+
This is not what you want.
97+
98+
# Unresolved questions
99+
[unresolved]: #unresolved-questions
100+
101+
`None`.
102+

0 commit comments

Comments
 (0)