selium_kernel/drivers/
time.rs1use std::{
4 future::Future,
5 sync::OnceLock,
6 time::{Duration, Instant, SystemTime, UNIX_EPOCH},
7};
8
9use wasmtime::Caller;
10
11use crate::{
12 guest_data::GuestResult,
13 operation::{Contract, Operation},
14 registry::InstanceRegistry,
15};
16use selium_abi::{TimeNow, TimeSleep};
17
18type TimeOps = (
19 std::sync::Arc<Operation<TimeNowDriver>>,
20 std::sync::Arc<Operation<TimeSleepDriver>>,
21);
22
23pub struct TimeNowDriver;
25pub struct TimeSleepDriver;
27
28impl Contract for TimeNowDriver {
29 type Input = ();
30 type Output = TimeNow;
31
32 fn to_future(
33 &self,
34 _caller: &mut Caller<'_, InstanceRegistry>,
35 _input: Self::Input,
36 ) -> impl Future<Output = GuestResult<Self::Output>> + 'static {
37 std::future::ready(Ok(now()))
38 }
39}
40
41impl Contract for TimeSleepDriver {
42 type Input = TimeSleep;
43 type Output = ();
44
45 fn to_future(
46 &self,
47 _caller: &mut Caller<'_, InstanceRegistry>,
48 input: Self::Input,
49 ) -> impl Future<Output = GuestResult<Self::Output>> + 'static {
50 let duration = Duration::from_millis(input.duration_ms);
51 async move {
52 tokio::time::sleep(duration).await;
53 Ok(())
54 }
55 }
56}
57
58fn now() -> TimeNow {
59 TimeNow {
60 unix_ms: unix_ms(),
61 monotonic_ms: monotonic_ms(),
62 }
63}
64
65fn unix_ms() -> u64 {
66 SystemTime::now()
67 .duration_since(UNIX_EPOCH)
68 .unwrap_or_default()
69 .as_millis() as u64
70}
71
72fn monotonic_ms() -> u64 {
73 static START: OnceLock<Instant> = OnceLock::new();
74 START.get_or_init(Instant::now).elapsed().as_millis() as u64
75}
76
77pub fn operations() -> TimeOps {
79 (
80 Operation::from_hostcall(TimeNowDriver, selium_abi::hostcall_contract!(TIME_NOW)),
81 Operation::from_hostcall(TimeSleepDriver, selium_abi::hostcall_contract!(TIME_SLEEP)),
82 )
83}