Skip to main content

universal_time/
global.rs

1use crate::{Instant, SystemTime};
2
3/// Source of wall-clock timestamps.
4pub trait WallClock {
5    /// Returns the current wall-clock time.
6    fn system_time(&self) -> SystemTime;
7}
8
9/// Source of monotonic instants.
10pub trait MonotonicClock {
11    /// Returns the current monotonic instant.
12    fn instant(&self) -> Instant;
13}
14
15/// A full time context that can provide wall-clock and monotonic time.
16pub trait TimeProvider: WallClock + MonotonicClock + Sync {}
17
18impl<T> TimeProvider for T where T: WallClock + MonotonicClock + Sync {}
19
20#[doc(hidden)]
21#[macro_export]
22macro_rules! __time_provider_link_name {
23    () => {
24        concat!(
25            "\n\nerror: a time provider is required.\n       \
26             Use `define_time_provider!(YourProvider)` in your binary crate.\n       \
27             See: ",
28            env!("CARGO_PKG_HOMEPAGE"),
29            "\n"
30        )
31    };
32}
33
34// On platforms without std, users must provide the time provider symbol via define_time_provider! macro
35extern "Rust" {
36    #[link_name = __time_provider_link_name!()]
37    static TIME_PROVIDER: &'static dyn TimeProvider;
38}
39
40#[inline(always)]
41pub(crate) fn get_time_provider() -> &'static dyn TimeProvider {
42    unsafe { TIME_PROVIDER }
43}
44
45/// Macro to define a custom time provider for no_std platforms.
46///
47/// This macro must be called in your binary crate when using this library on no_std
48/// or WASM unknown targets. Pass a static instance of your time provider.
49///
50/// # Example
51///
52/// ```
53/// use core::time::Duration;
54///
55/// use universal_time::{define_time_provider, Instant, MonotonicClock, SystemTime, WallClock};
56///
57/// struct MyTimeProvider;
58///
59/// impl WallClock for MyTimeProvider {
60///     fn system_time(&self) -> SystemTime {
61///         SystemTime::from_unix_duration(Duration::from_secs(0))
62///     }
63/// }
64///
65/// impl MonotonicClock for MyTimeProvider {
66///     fn instant(&self) -> Instant {
67///         Instant::from_ticks(Duration::from_secs(0))
68///     }
69/// }
70///
71/// define_time_provider!(MyTimeProvider);
72/// ```
73#[cfg_attr(
74    docsrs,
75    doc(cfg(any(
76        not(feature = "std"),
77        all(feature = "std", target_family = "wasm", target_os = "unknown")
78    )))
79)]
80#[macro_export]
81macro_rules! define_time_provider {
82    ($provider_instance:expr) => {
83        #[export_name = $crate::__time_provider_link_name!()]
84        static __UNIVERSAL_TIME_PROVIDER: &dyn $crate::TimeProvider = &$provider_instance;
85    };
86}