use crate::{ffi, mem};
pub mod format {
pub const UNIX: &str = "unix";
pub const MILLIS: &str = "ms";
pub const NANOS: &str = "ns";
pub const RFC3339: &str = "rfc3339";
pub const HTTP: &str = "http";
pub const ISO8601: &str = "iso8601";
}
pub fn now(fmt: &str) -> String {
let args = serde_json::json!({ "format": fmt });
let args_str = args.to_string();
let (args_ptr, args_len) = mem::host_arg_str(&args_str);
let result = unsafe { ffi::timestamp(args_ptr, args_len) };
unsafe { mem::read_packed_string(result) }.unwrap_or_default()
}
pub fn now_ms() -> u64 {
now(format::MILLIS).parse().unwrap_or(0)
}
pub fn now_unix() -> u64 {
now(format::UNIX).parse().unwrap_or(0)
}
pub fn now_rfc3339() -> String {
now(format::RFC3339)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ffi::test_host;
#[test]
fn now_passes_format_in_args() {
test_host::reset();
test_host::with_mock(|m| m.timestamp_response = Some("2026-04-07T11:12:13Z".into()));
let s = now(format::RFC3339);
assert_eq!(s, "2026-04-07T11:12:13Z");
let captured = test_host::read_mock(|m| m.last_timestamp_args.clone()).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&captured).unwrap();
assert_eq!(parsed["format"], "rfc3339");
}
#[test]
fn now_ms_parses_decimal_response() {
test_host::reset();
test_host::with_mock(|m| m.timestamp_response = Some("1759839133000".into()));
assert_eq!(now_ms(), 1_759_839_133_000);
}
#[test]
fn now_unix_parses_decimal_response() {
test_host::reset();
test_host::with_mock(|m| m.timestamp_response = Some("1759839133".into()));
assert_eq!(now_unix(), 1_759_839_133);
}
#[test]
fn now_unparseable_response_zero() {
test_host::reset();
test_host::with_mock(|m| m.timestamp_response = Some("not-a-number".into()));
assert_eq!(now_ms(), 0);
assert_eq!(now_unix(), 0);
}
#[test]
fn now_rfc3339_uses_rfc3339_format() {
test_host::reset();
test_host::with_mock(|m| m.timestamp_response = Some("2026-04-07T00:00:00Z".into()));
let s = now_rfc3339();
assert_eq!(s, "2026-04-07T00:00:00Z");
let captured = test_host::read_mock(|m| m.last_timestamp_args.clone()).unwrap();
assert!(captured.contains("rfc3339"));
}
#[test]
fn format_constants_match_expected_strings() {
assert_eq!(format::UNIX, "unix");
assert_eq!(format::MILLIS, "ms");
assert_eq!(format::NANOS, "ns");
assert_eq!(format::RFC3339, "rfc3339");
assert_eq!(format::HTTP, "http");
assert_eq!(format::ISO8601, "iso8601");
}
}