use std::time::{Duration, Instant};
pub trait Hal {
fn operating_system(&self) -> &'static str;
fn architecture(&self) -> &'static str;
fn elapsed_since(&self, origin: Instant) -> Duration;
}
pub trait Platform: Hal {
fn is_unix(&self) -> bool;
fn process_id(&self) -> u32;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct HostPlatform;
impl HostPlatform {
pub const fn new() -> Self {
Self
}
}
impl Hal for HostPlatform {
fn operating_system(&self) -> &'static str {
std::env::consts::OS
}
fn architecture(&self) -> &'static str {
std::env::consts::ARCH
}
fn elapsed_since(&self, origin: Instant) -> Duration {
origin.elapsed()
}
}
impl Platform for HostPlatform {
fn is_unix(&self) -> bool {
cfg!(unix)
}
fn process_id(&self) -> u32 {
std::process::id()
}
}
#[cfg(unix)]
pub mod posix {
use super::{Hal, HostPlatform, Platform};
use std::time::{Duration, Instant};
#[derive(Clone, Copy, Debug, Default)]
pub struct PosixPlatform(HostPlatform);
impl PosixPlatform {
pub const fn new() -> Self {
Self(HostPlatform::new())
}
}
impl Hal for PosixPlatform {
fn operating_system(&self) -> &'static str {
self.0.operating_system()
}
fn architecture(&self) -> &'static str {
self.0.architecture()
}
fn elapsed_since(&self, origin: Instant) -> Duration {
self.0.elapsed_since(origin)
}
}
impl Platform for PosixPlatform {
fn is_unix(&self) -> bool {
true
}
fn process_id(&self) -> u32 {
self.0.process_id()
}
}
}
#[allow(unsafe_code)] pub mod ffi {
#[no_mangle]
pub extern "C" fn dinah_abi_version() -> u32 {
1
}
#[no_mangle]
pub extern "C" fn dinah_abi_features() -> u64 {
1
}
#[no_mangle]
pub extern "C" fn dinah_abi_platform_family() -> u32 {
if cfg!(unix) {
1
} else if cfg!(windows) {
2
} else {
0
}
}
}
#[cfg(test)]
mod tests {
use super::{Hal, HostPlatform, Platform};
use std::time::{Duration, Instant};
#[test]
fn host_provider_reports_target_and_process() {
let host = HostPlatform::new();
assert!(!host.operating_system().is_empty());
assert!(!host.architecture().is_empty());
assert!(host.process_id() > 0);
assert_eq!(host.is_unix(), cfg!(unix));
assert!(
host.elapsed_since(Instant::now() - Duration::from_millis(1))
>= Duration::from_millis(1)
);
}
#[test]
fn c_abi_scalar_queries_are_versioned() {
assert_eq!(super::ffi::dinah_abi_version(), 1);
assert_eq!(super::ffi::dinah_abi_features() & 1, 1);
assert!(super::ffi::dinah_abi_platform_family() <= 2);
}
#[cfg(unix)]
#[test]
fn posix_provider_matches_host_metadata() {
use super::posix::PosixPlatform;
let host = HostPlatform::new();
let posix = PosixPlatform::new();
assert_eq!(posix.operating_system(), host.operating_system());
assert_eq!(posix.architecture(), host.architecture());
assert!(posix.is_unix());
}
}