Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: duration_checked_sub RFC #1640

Merged
merged 3 commits into from
Aug 18, 2016
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions text/0000-duration-checked-sub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
- Feature Name: duration_checked_sub
- Start Date: 2016-06-04
- RFC PR:
- Rust Issue:

# Summary
[summary]: #summary

This RFC adds the `checked_*` methods already known from primitives like
`usize` to `Duration`.

# Motivation
[motivation]: #motivation

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:

```rust

// 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.

# Detailed design
[design]: #detailed-design

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:

```rust
impl Duration {
fn checked_sub(self, rhs: Duration) -> Duration {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the signature here should return Option<Duration>, right?

(similarly Some(Duration) below)

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);
Duration { secs: secs, nanos: nanos }
}
else {
None
}
}
}
```

The same accounts for all other added methods, namely:

- `checked_add()`
- `checked_sub()`
- `checked_mul()`
- `checked_div()`

# Drawbacks
[drawbacks]: #drawbacks

`None`.

# Alternatives
[alternatives]: #alternatives

The alternatives are simply not doing this and forcing the programmer to code
the check on their behalf.
This is not what you want.

# Unresolved questions
[unresolved]: #unresolved-questions

`None`.