use core::{
ops::{Add, AddAssign, Sub, SubAssign},
time::Duration,
};
use serde::{Deserialize, Serialize};
use crate::ScriptContext;
mod tortuise {
#[link(wasm_import_module = "tortuise")]
unsafe extern "C" {
pub safe fn system_now(context: u64) -> u64;
pub safe fn monotonic_now(context: u64) -> u64;
pub safe fn delta_time(context: u64) -> u64;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[repr(transparent)]
#[serde(transparent)]
pub struct SystemTime(u128);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[repr(transparent)]
#[serde(transparent)]
pub struct Instant(u128);
impl ScriptContext {
pub fn delta_time(&self) -> Duration {
Duration::from_nanos(tortuise::delta_time(self.0))
}
}
impl SystemTime {
pub const UNIX_EPOCH: Self = Self(0);
pub fn now(context: &ScriptContext) -> Self {
Self(tortuise::system_now(context.0) as u128)
}
pub fn duration_since(self, earlier: SystemTime) -> Option<Duration> {
if self < earlier {
return None;
}
Some(Duration::from_nanos_u128(self.0 - earlier.0))
}
pub fn checked_add(self, duration: Duration) -> Option<Self> {
Some(Self(self.0.checked_add(duration.as_nanos())?))
}
pub fn checked_sub(self, duration: Duration) -> Option<Self> {
Some(Self(self.0.checked_sub(duration.as_nanos())?))
}
}
impl Add<Duration> for SystemTime {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
self.checked_add(rhs).unwrap()
}
}
impl AddAssign<Duration> for SystemTime {
fn add_assign(&mut self, rhs: Duration) {
*self = self.add(rhs);
}
}
impl Sub<Duration> for SystemTime {
type Output = Self;
fn sub(self, rhs: Duration) -> Self::Output {
self.checked_sub(rhs).unwrap()
}
}
impl SubAssign<Duration> for SystemTime {
fn sub_assign(&mut self, rhs: Duration) {
*self = self.sub(rhs)
}
}
impl Instant {
pub fn now(context: &ScriptContext) -> Self {
Self(tortuise::monotonic_now(context.0) as u128)
}
pub fn duration_since(self, earlier: Instant) -> Option<Duration> {
if earlier > self {
return None;
}
Some(Duration::from_nanos_u128(self.0 - earlier.0))
}
pub fn elapsed(self, context: &ScriptContext) -> Duration {
Self::now(context)
.duration_since(self)
.unwrap_or(Duration::ZERO)
}
pub fn checked_add(self, duration: Duration) -> Option<Self> {
Some(Self(self.0.checked_add(duration.as_nanos())?))
}
pub fn checked_sub(self, duration: Duration) -> Option<Self> {
Some(Self(self.0.checked_sub(duration.as_nanos())?))
}
}
impl Add<Duration> for Instant {
type Output = Self;
fn add(self, rhs: Duration) -> Self::Output {
self.checked_add(rhs).unwrap()
}
}
impl AddAssign<Duration> for Instant {
fn add_assign(&mut self, rhs: Duration) {
*self = self.add(rhs);
}
}
impl Sub<Duration> for Instant {
type Output = Self;
fn sub(self, rhs: Duration) -> Self::Output {
self.checked_sub(rhs).unwrap()
}
}
impl SubAssign<Duration> for Instant {
fn sub_assign(&mut self, rhs: Duration) {
*self = self.sub(rhs)
}
}
|