Skip to main content

devela/lang/prog/ffi/js/
instant.rs

1// devela::lang::prog::ffi::js::instant
2//
3//! Defines [`JsInstant`], [`JsTimeout`].
4//
5
6use crate::{Display, TimeDelta, impl_trait};
7use crate::{js_number, js_uint32};
8
9#[doc = crate::_tags!(runtime time)]
10/// A high-resolution timestamp based on JavaScript's `performance.now()`.
11#[doc = crate::_doc_meta!{
12    location("lang/prog/ffi/js"),
13    test_size_of(JsInstant = 8|64),
14}]
15///
16/// The internal representation is a double-precision floating-point millisecond value.
17#[repr(C)]
18#[derive(Clone, Copy, Debug, PartialEq)]
19pub struct JsInstant {
20    /// Milliseconds since `performance.timeOrigin`.
21    pub ms: js_number,
22}
23#[rustfmt::skip]
24impl JsInstant {
25    /// Returns the time in milliseconds.
26    pub const fn as_millis_f64(self) -> js_number { self.ms }
27    /// Returns a new `JsInstant` from a timestamp in milliseconds.
28    pub const fn from_millis_f64(millis: js_number) -> Self { Self { ms: millis } }
29    /// Returns the time in `f64` seconds.
30    pub const fn as_secs_f64(self) -> js_number { self.ms / 1_000.0 }
31    /// Returns a new `JsInstant` from a timestamp in milliseconds.
32    pub const fn from_secs_f64(secs: js_number) -> Self { Self { ms: secs * 1_000.0 } }
33
34    /// Returns the duration between this and an earlier `JsInstant`.
35    pub const fn since(self, earlier: Self) -> Self { Self::from_millis_f64(self.ms - earlier.ms) }
36
37    /// Returns the duration between this and an earlier instant as a `TimeDelta`.
38    pub const fn delta_since(self, earlier: Self) -> TimeDelta { TimeDelta::from_js(self.since(earlier)) }
39}
40
41impl_trait![fmt::Display for JsInstant |self, f| Display::fmt(&self.ms, f)];
42
43#[rustfmt::skip]
44#[cfg(feature = "event")]
45mod impls {
46    pub use super::JsInstant;
47    pub use crate::EventTimestamp;
48
49    impl EventTimestamp {
50        /// Converts a `JsInstant` to an `EventTimestamp`, ensuring a valid value.
51        pub const fn from_js(from: JsInstant) -> EventTimestamp {
52            EventTimestamp::from_millis_f32(from.as_millis_f64() as f32)
53        }
54        /// Converts an `EventTimestamp` to a `JsInstant`.
55        pub const fn to_js(self) -> JsInstant {
56            JsInstant::from_millis_f64(self.as_millis_f32() as f64)
57        }
58    }
59    impl From<JsInstant> for EventTimestamp {
60        fn from(from: JsInstant) -> Self { EventTimestamp::from_js(from) }
61    }
62    impl From<EventTimestamp> for JsInstant {
63        fn from(from: EventTimestamp) -> Self { from.to_js() }
64    }
65}
66
67#[doc = crate::_tags!(runtime time uid)]
68/// A handle to a JavaScript timeout.
69#[doc = crate::_doc_meta!{
70    location("lang/prog/ffi/js"),
71    test_size_of(JsTimeout = 4|32),
72}]
73///
74/// - <https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout#return_value>.
75#[repr(C)]
76#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub struct JsTimeout {
78    pub(crate) id: js_uint32,
79}
80
81impl JsTimeout {
82    /// Returns a new invalid handle.
83    pub const fn invalid() -> Self {
84        JsTimeout { id: 0 }
85    }
86    /// Returns the numeric ID of the handle.
87    pub const fn id(self) -> js_uint32 {
88        self.id
89    }
90}