Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • microhacks/web-instant
1 result
Show changes
Commits on Source (2)
/target
/Cargo.lock
.idea/
\ No newline at end of file
[package]
name = "web_instant"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
description = "Cross platform impl of Instant"
authors = [
......
......@@ -3,6 +3,8 @@
Provides `Spot`, a version of `Instant` that works both on desktop and the web. On desktop, the internal representation uses `std::time::Instant`. On the web, the internal representation is an `f64`,
and uses `js_sys::Date` methods to cover functinality where required
All the methods on `Instant` are implemented for `Spot`, so you can just replace uses of `std::time::Instant` with `web_instant::Spot`
## Install
`cargo add web_instant`
......
use std::ops::Sub;
use std::fmt::{Debug, Formatter};
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::{Duration, Instant};
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Spot {
inner: Instant,
}
impl Debug for Spot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl Spot {
pub fn now() -> Self {
Spot {
inner: Instant::now(),
}
}
pub fn as_secs(&self) -> u64 {
self.as_duration().as_secs()
/// Returns the amount of time elapsed since this instant was created.
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 {
self.inner.elapsed()
/// 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.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 {
self.as_duration()
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 {
type Output = Duration;
fn sub(self, rhs: Spot) -> Self::Output {
self.inner - rhs.inner
/// Returns the amount of time elapsed from another instant to this one,
/// 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;
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub struct Spot {
/// Millisecond offset from the Unix Epoch - equivalent to Date.now()
inner: f64,
}
impl Debug for Spot {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl Spot {
pub fn now() -> Self {
Spot {
inner: js_sys::Date::now(),
}
}
pub fn as_secs(&self) -> u64 {
self.as_duration().as_secs()
/// Returns the amount of time elapsed since this instant was created.
pub fn elapsed(&self) -> Duration {
Spot::now() - *self
}
pub fn as_duration(&self) -> Duration {
Self::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()
}
pub fn elapsed(&self) -> Duration {
self.as_duration()
/// 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> {
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 {
type Output = Duration;
fn sub(self, rhs: Spot) -> Self::Output {
let diff = (self.inner - rhs.inner).max(0.0);
let secs = (diff as u64) / 1_000;
let nanos = (((diff as u64) % 1_000) as u32) * 1_000_000;
Duration::new(secs, nanos)
/// Returns the amount of time elapsed from another instant to this one,
/// or zero duration if that instant is later than this one.
fn sub(self, other: Spot) -> Duration {
self.duration_since(other)
}
}
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_family = "wasm"))]
mod instant_desktop;
#[cfg(target_arch = "wasm32")]
// #[cfg(target_family = "wasm")]
mod instant_web;
#[cfg(not(target_arch = "wasm32"))]
......