#![warn(missing_docs)]
#[derive(Copy, Clone)]
pub struct Instant {
#[cfg(target_arch = "wasm32")]
value: f64,
#[cfg(not(target_arch = "wasm32"))]
inner: std::time::Instant,
}
impl Instant {
pub fn now() -> Self {
Self {
#[cfg(target_arch = "wasm32")]
value: {
thread_local! {
static PERFORMANCE: web_sys::Performance = web_sys::window()
.expect("no window")
.performance()
.expect("no performance");
}
PERFORMANCE.with(|performance| performance.now() / 1000.0)
},
#[cfg(not(target_arch = "wasm32"))]
inner: std::time::Instant::now(),
}
}
pub fn duration_since(&self, earlier: Self) -> Duration {
#[cfg(target_arch = "wasm32")]
return Duration::from_secs_f64(self.value - earlier.value);
#[cfg(not(target_arch = "wasm32"))]
return Duration::from_secs_f64(self.inner.duration_since(earlier.inner).as_secs_f64());
}
pub fn elapsed(&self) -> Duration {
Self::now().duration_since(*self)
}
}
#[derive(Copy, Clone)]
pub struct Duration {
secs: f64,
}
impl std::ops::Add for Duration {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
secs: self.secs + rhs.secs,
}
}
}
impl std::fmt::Debug for Duration {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::time::Duration::from(*self).fmt(f)
}
}
impl Duration {
pub fn from_secs_f64(secs: f64) -> Self {
Self { secs }
}
pub fn as_secs_f64(&self) -> f64 {
self.secs
}
}
impl From<Duration> for std::time::Duration {
fn from(value: Duration) -> Self {
std::time::Duration::from_secs_f64(value.as_secs_f64())
}
}
impl From<std::time::Duration> for Duration {
fn from(value: std::time::Duration) -> Self {
Duration::from_secs_f64(value.as_secs_f64())
}
}
pub struct Timer {
start: Instant,
}
impl Timer {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
start: Instant::now(),
}
}
pub fn reset(&mut self) {
self.start = Instant::now();
}
pub fn elapsed(&self) -> Duration {
self.start.elapsed()
}
pub fn tick(&mut self) -> Duration {
let now = Instant::now();
let duration = now.duration_since(self.start);
self.start = now;
duration
}
}
pub async fn sleep(duration: Duration) {
#[cfg(target_arch = "wasm32")]
{
let promise = js_sys::Promise::new(&mut |resolve, _reject| {
web_sys::window()
.unwrap()
.set_timeout_with_callback_and_timeout_and_arguments_0(
&resolve,
(duration.as_secs_f64() * 1000.0).round() as _,
)
.unwrap();
});
let future = wasm_bindgen_futures::JsFuture::from(promise);
future.await.unwrap();
}
#[cfg(not(target_arch = "wasm32"))]
{
async_std::task::sleep(duration.into()).await;
}
}
#[test]
fn test() {
let mut timer = Timer::new();
timer.elapsed();
for _ in 0..100 {
timer.tick();
}
}