use crate::__private::wasip1::*;
use crate::memory::{WasmAccess, WasmAccessName};
pub trait Clock {
fn clock_time_get<Wasm: WasmAccess + WasmAccessName + 'static>(
clock_id: Clockid,
precision: Timestamp,
time_ptr: *mut Timestamp,
) -> Errno;
fn clock_res_get<Wasm: WasmAccess + WasmAccessName + 'static>(
clock_id: Clockid,
resolution_ptr: *mut Timestamp,
) -> Errno;
}
pub struct StandardClock;
impl Clock for StandardClock {
fn clock_time_get<Wasm: WasmAccess + WasmAccessName + 'static>(
clock_id: Clockid,
precision: Timestamp,
time_ptr: *mut Timestamp,
) -> Errno {
#[cfg(target_os = "wasi")]
{
use crate::transporter::non_recursive_clock_time_get;
#[cfg(not(feature = "multi_memory"))]
let adjusted_ptr =
unsafe { Wasm::memory_director_mut(time_ptr as *mut u8) as *mut Timestamp };
#[cfg(feature = "multi_memory")]
let adjusted_ptr = time_ptr;
match unsafe { non_recursive_clock_time_get(clock_id, precision) } {
Ok(timestamp) => {
unsafe { core::ptr::write(adjusted_ptr, timestamp) };
ERRNO_SUCCESS
}
Err(e) => e,
}
}
#[cfg(not(target_os = "wasi"))]
{
let _ = clock_id;
let _ = precision;
let _ = time_ptr;
ERRNO_NOSYS
}
}
fn clock_res_get<Wasm: WasmAccess + WasmAccessName + 'static>(
clock_id: Clockid,
resolution_ptr: *mut Timestamp,
) -> Errno {
#[cfg(target_os = "wasi")]
{
use crate::transporter::non_recursive_clock_res_get;
#[cfg(not(feature = "multi_memory"))]
let adjusted_ptr =
unsafe { Wasm::memory_director_mut(resolution_ptr as *mut u8) as *mut Timestamp };
#[cfg(feature = "multi_memory")]
let adjusted_ptr = resolution_ptr;
match unsafe { non_recursive_clock_res_get(clock_id) } {
Ok(resolution) => {
unsafe { core::ptr::write(adjusted_ptr, resolution) };
ERRNO_SUCCESS
}
Err(e) => e,
}
}
#[cfg(not(target_os = "wasi"))]
{
let _ = clock_id;
let _ = resolution_ptr;
ERRNO_NOSYS
}
}
}
#[macro_export]
macro_rules! plug_clock {
($ty:ty, $($wasm:ident),+) => {
const _ : () = {
type __TYPE = $ty;
};
$crate::__private::paste::paste! {
$(
#[unsafe(no_mangle)]
#[cfg(target_os = "wasi")]
pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _clock_time_get>](
clock_id: $crate::__private::wasip1::Clockid,
precision: $crate::__private::wasip1::Timestamp,
time_ptr: *mut $crate::__private::wasip1::Timestamp,
) -> $crate::__private::wasip1::Errno {
$crate::__as_t!(@as_t, $wasm);
<$ty as $crate::clock::Clock>::clock_time_get::<T>(clock_id, precision, time_ptr)
}
#[unsafe(no_mangle)]
#[cfg(target_os = "wasi")]
pub unsafe extern "C" fn [<__wasip1_vfs_ $wasm _clock_res_get>](
clock_id: $crate::__private::wasip1::Clockid,
resolution_ptr: *mut $crate::__private::wasip1::Timestamp,
) -> $crate::__private::wasip1::Errno {
$crate::__as_t!(@as_t, $wasm);
<$ty as $crate::clock::Clock>::clock_res_get::<T>(clock_id, resolution_ptr)
}
)*
}
};
($($wasm:ident),*) => {
$crate::__as_t!(@through, $($wasm),* => $crate::plug_clock, @inner);
};
(@inner, $($wasm:ident),*) => {
$crate::plug_clock!($crate::clock::StandardClock, $($wasm),*);
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg(not(target_os = "wasi"))]
fn test_standard_clock_non_wasi() {
use crate::memory::WasmAccessFaker;
let mut time_buf = 0u64;
let result = StandardClock::clock_time_get::<WasmAccessFaker>(
CLOCKID_REALTIME,
1000,
&mut time_buf as *mut u64,
);
assert_eq!(result, ERRNO_NOSYS);
}
#[test]
#[cfg(not(target_os = "wasi"))]
fn test_standard_clock_res_get_non_wasi() {
use crate::memory::WasmAccessFaker;
let mut resolution_buf = 0u64;
let result = StandardClock::clock_res_get::<WasmAccessFaker>(
CLOCKID_REALTIME,
&mut resolution_buf as *mut u64,
);
assert_eq!(result, ERRNO_NOSYS);
}
}