Skip to content

Commit e919cb0

Browse files
authored
Introducing new methods for instance (#16)
* Introducing new methods for instance * Fixed recursion issues and add checked_duration_since method * Added tests for micro seconds precision
1 parent f369eb6 commit e919cb0

File tree

3 files changed

+58
-20
lines changed

3 files changed

+58
-20
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ serde = ["serde_crate"]
2828
wasm-bindgen-test = "0.3.0"
2929
wasm-bindgen-futures = "0.4"
3030
serde_json = "^1.0"
31+
32+
[lib]
33+
crate-type = ["cdylib", "rlib"]

src/std.rs

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,13 @@ use std::time::Duration;
2626
use crate::js::performance_now;
2727

2828
#[derive(Debug, Copy, Clone)]
29-
pub struct Instant {
30-
/// Unit is milliseconds.
31-
inner: f64,
32-
}
29+
pub struct Instant(Duration);
3330

3431
impl PartialEq for Instant {
3532
fn eq(&self, other: &Instant) -> bool {
3633
// Note that this will most likely only compare equal if we clone an `Instant`,
3734
// but that's ok.
38-
self.inner == other.inner
35+
self.0 == other.0
3936
}
4037
}
4138

@@ -49,7 +46,7 @@ impl PartialOrd for Instant {
4946

5047
impl Ord for Instant {
5148
fn cmp(&self, other: &Self) -> Ordering {
52-
self.inner.partial_cmp(&other.inner).unwrap()
49+
self.0.partial_cmp(&other.0).unwrap()
5350
}
5451
}
5552

@@ -65,56 +62,84 @@ impl Instant {
6562
}
6663

6764
pub(crate) fn now_js() -> Instant {
68-
let val = performance_now();
69-
Instant { inner: val }
65+
let val = (performance_now() * 1000.0) as u64;
66+
Instant(Duration::from_micros(val))
7067
}
7168

7269
pub fn duration_since(&self, earlier: Instant) -> Duration {
73-
*self - earlier
70+
self.checked_duration_since(earlier).unwrap_or_default()
7471
}
7572

7673
pub fn elapsed(&self) -> Duration {
7774
Instant::now() - *self
7875
}
76+
77+
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
78+
self.0.checked_sub(earlier.0)
79+
}
80+
81+
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
82+
self.checked_duration_since(earlier).unwrap_or_default()
83+
}
84+
85+
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
86+
self.0.checked_add(duration).map(Instant)
87+
}
88+
89+
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
90+
self.0.checked_sub(duration).map(Instant)
91+
}
7992
}
8093

8194
impl Add<Duration> for Instant {
8295
type Output = Instant;
8396

97+
/// # Panics
98+
///
99+
/// This function may panic if the resulting point in time cannot be represented by the
100+
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
84101
fn add(self, other: Duration) -> Instant {
85-
let new_val = self.inner + other.as_millis() as f64;
86-
Instant { inner: new_val }
102+
self.checked_add(other)
103+
.expect("overflow when adding duration to instant")
87104
}
88105
}
89106

90107
impl AddAssign<Duration> for Instant {
91-
fn add_assign(&mut self, rhs: Duration) {
92-
self.inner += rhs.as_millis() as f64;
108+
fn add_assign(&mut self, other: Duration) {
109+
*self = *self + other;
93110
}
94111
}
95112

96113
impl Sub<Duration> for Instant {
97114
type Output = Instant;
98115

99116
fn sub(self, other: Duration) -> Instant {
100-
let new_val = self.inner - other.as_millis() as f64;
101-
Instant { inner: new_val }
117+
self.checked_sub(other)
118+
.expect("overflow when subtracting duration from instant")
102119
}
103120
}
104121

105122
impl SubAssign<Duration> for Instant {
106-
fn sub_assign(&mut self, rhs: Duration) {
107-
self.inner -= rhs.as_millis() as f64;
123+
fn sub_assign(&mut self, other: Duration) {
124+
*self = *self - other;
108125
}
109126
}
110127

111128
impl Sub<Instant> for Instant {
112129
type Output = Duration;
113130

131+
/// Returns the amount of time elapsed from another instant to this one,
132+
/// or zero duration if that instant is later than this one.
133+
///
134+
/// # Panics
135+
///
136+
/// Previous Rust versions panicked when `other` was later than `self`. Currently this
137+
/// method saturates. Future versions may reintroduce the panic in some circumstances.
138+
/// See [Monotonicity].
139+
///
140+
/// [Monotonicity]: Instant#monotonicity
114141
fn sub(self, other: Instant) -> Duration {
115-
let ms = self.inner - other.inner;
116-
assert!(ms >= 0.0);
117-
Duration::from_millis(ms as u64)
142+
self.duration_since(other)
118143
}
119144
}
120145

tests/web.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ pub mod tokio_tests {
3131
});
3232
}
3333

34+
#[wasm_bindgen_test]
35+
pub async fn test_micro_second_precision() {
36+
initialize();
37+
let a = Instant::now();
38+
advance(Duration::from_micros(435)).await;
39+
let b = Instant::now();
40+
let diff = b - a;
41+
assert_eq!(diff.as_micros(), 435);
42+
}
43+
3444
pub mod sleep_tests {
3545

3646
use super::*;

0 commit comments

Comments
 (0)