Skip to content
Snippets Groups Projects
Verified Commit bd3445c2 authored by Louis's avatar Louis :fire:
Browse files

Implement full Instant interface

parent 6e030925
No related branches found
No related tags found
No related merge requests found
/target /target
/Cargo.lock /Cargo.lock
.idea/
\ No newline at end of file
[package] [package]
name = "web_instant" name = "web_instant"
version = "0.1.0" version = "0.2.0"
edition = "2021" edition = "2021"
description = "Cross platform impl of Instant" description = "Cross platform impl of Instant"
authors = [ authors = [
......
use std::ops::Sub; use std::fmt::{Debug, Formatter};
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] #[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Spot { pub struct Spot {
inner: Instant, inner: Instant,
} }
impl Debug for Spot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl Spot { impl Spot {
pub fn now() -> Self { pub fn now() -> Self {
Spot { Spot {
inner: Instant::now(), inner: Instant::now(),
} }
} }
pub fn as_secs(&self) -> u64 { /// Returns the amount of time elapsed since this instant was created.
self.as_duration().as_secs() pub fn elapsed(&self) -> Duration {
Spot::now() - *self
}
/// Returns the amount of time elapsed from another instant to this one,
/// or zero duration if that instant is later than this one.
pub fn duration_since(&self, earlier: Spot) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
}
/// Returns the amount of time elapsed from another instant to this one,
/// or None if that instant is later than this one.
///
/// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s,
/// this method can return `None`.
pub fn checked_duration_since(&self, earlier: Spot) -> Option<Duration> {
self.inner.checked_duration_since(earlier.inner)
} }
pub fn as_duration(&self) -> Duration { /// Returns the amount of time elapsed from another instant to this one,
self.inner.elapsed() /// or zero duration if that instant is later than this one.
pub fn saturating_duration_since(&self, earlier: Spot) -> Duration {
self.inner.saturating_duration_since(earlier.inner).unwrap_or_default()
} }
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
pub fn checked_add(&self, duration: Duration) -> Option<Spot> {
self.inner.checked_add(duration).map(|inner| Spot { inner })
}
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
pub fn checked_sub(&self, duration: Duration) -> Option<Spot> {
self.inner.checked_sub(duration).map(|inner| Spot { inner })
}
}
pub fn elapsed(&self) -> Duration { impl Add<Duration> for Spot {
self.as_duration() type Output = Spot;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`Spot::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Spot {
self.checked_add(other).expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for Spot {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}
impl Sub<Duration> for Spot {
type Output = Spot;
fn sub(self, other: Duration) -> Spot {
self.checked_sub(other).expect("overflow when subtracting duration from instant")
}
}
impl SubAssign<Duration> for Spot {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
} }
} }
impl Sub<Spot> for Spot { impl Sub<Spot> for Spot {
type Output = Duration; type Output = Duration;
fn sub(self, rhs: Spot) -> Self::Output { /// Returns the amount of time elapsed from another instant to this one,
self.inner - rhs.inner /// or zero duration if that instant is later than this one.
fn sub(self, other: Spot) -> Duration {
self.duration_since(other)
} }
} }
use std::ops::Sub; use std::fmt::{Debug, Formatter};
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::Duration; use std::time::Duration;
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)] #[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Spot { pub struct Spot {
/// Millisecond offset from the Unix Epoch - equivalent to Date.now() /// Millisecond offset from the Unix Epoch - equivalent to Date.now()
inner: f64, inner: f64,
} }
impl Debug for Spot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl Spot { impl Spot {
pub fn now() -> Self { pub fn now() -> Self {
Spot { Spot {
inner: js_sys::Date::now(), inner: js_sys::Date::now(),
} }
} }
pub fn as_secs(&self) -> u64 { /// Returns the amount of time elapsed since this instant was created.
self.as_duration().as_secs() pub fn elapsed(&self) -> Duration {
Spot::now() - *self
} }
pub fn as_duration(&self) -> Duration { /// Returns the amount of time elapsed from another instant to this one,
Self::now() - *self /// or zero duration if that instant is later than this one.
pub fn duration_since(&self, earlier: Spot) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
} }
pub fn elapsed(&self) -> Duration { /// Returns the amount of time elapsed from another instant to this one,
self.as_duration() /// or None if that instant is later than this one.
///
/// Due to [monotonicity bugs], even under correct logical ordering of the passed `Instant`s,
/// this method can return `None`.
pub fn checked_duration_since(&self, earlier: Spot) -> Option<Duration> {
if earlier.inner > self.inner {
None
} else {
let millis = (self.inner - earlier.inner);
Some(Duration::from_secs_f64(millis * 1000.0))
}
}
/// Returns the amount of time elapsed from another instant to this one,
/// or zero duration if that instant is later than this one.
pub fn saturating_duration_since(&self, earlier: Spot) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
}
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
pub fn checked_add(&self, duration: Duration) -> Option<Spot> {
let duration_millis = duration.as_secs_f64() / 1000.0;
Some(Spot { inner: self.inner + duration_millis })
}
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
/// otherwise.
pub fn checked_sub(&self, duration: Duration) -> Option<Spot> {
let duration_millis = duration.as_secs_f64() / 1000.0;
if duration_millis > self.inner {
None
} else {
Some(Spot { inner: self.inner - duration_millis })
}
}
}
impl Add<Duration> for Spot {
type Output = Spot;
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`Spot::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Spot {
self.checked_add(other).expect("overflow when adding duration to instant")
}
}
impl AddAssign<Duration> for Spot {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
} }
} }
impl Sub<Duration> for Spot {
type Output = Spot;
fn sub(self, other: Duration) -> Spot {
self.checked_sub(other).expect("overflow when subtracting duration from instant")
}
}
impl SubAssign<Duration> for Spot {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
}
}
impl Sub<Spot> for Spot { impl Sub<Spot> for Spot {
type Output = Duration; type Output = Duration;
fn sub(self, rhs: Spot) -> Self::Output { /// Returns the amount of time elapsed from another instant to this one,
let diff = (self.inner - rhs.inner).max(0.0); /// or zero duration if that instant is later than this one.
let secs = (diff as u64) / 1_000; fn sub(self, other: Spot) -> Duration {
let nanos = (((diff as u64) % 1_000) as u32) * 1_000_000; self.duration_since(other)
Duration::new(secs, nanos)
} }
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_family = "wasm"))]
mod instant_desktop; mod instant_desktop;
#[cfg(target_arch = "wasm32")] // #[cfg(target_family = "wasm")]
mod instant_web; mod instant_web;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment