use std::time::{SystemTime, UNIX_EPOCH};
use crate::error::{Error, Result};
pub const VAR: &str = "MMZ_NOW";
#[derive(Debug, Clone, Copy)]
pub struct Clock {
now: u64,
}
impl Clock {
pub fn resolve() -> Result<Self> {
Self::from_pin(pin()?.as_deref())
}
#[must_use]
pub const fn pinned(secs: u64) -> Self {
Self { now: secs }
}
#[must_use]
pub const fn now_secs(self) -> u64 {
self.now
}
fn from_pin(raw: Option<&str>) -> Result<Self> {
let Some(raw) = raw else {
return Ok(Self { now: system_now() });
};
raw.trim()
.parse::<u64>()
.map(|now| Self { now })
.map_err(|_| Error::InvalidNow {
value: raw.to_owned(),
})
}
}
fn pin() -> Result<Option<String>> {
match std::env::var(VAR) {
Ok(raw) => Ok(Some(raw)),
Err(std::env::VarError::NotPresent) => Ok(None),
Err(std::env::VarError::NotUnicode(raw)) => Err(Error::InvalidNow {
value: raw.to_string_lossy().into_owned(),
}),
}
}
fn system_now() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_or(0, |elapsed| elapsed.as_secs())
}
#[cfg(test)]
mod tests {
use super::{Clock, VAR};
#[test]
fn an_unset_pin_reads_the_system_clock() {
let clock = Clock::from_pin(None).expect("system clock");
assert!(
clock.now_secs() > 1_600_000_000,
"an unset MMZ_NOW leaves mmz on the real clock"
);
}
#[test]
fn a_pin_is_taken_verbatim_modulo_whitespace() {
assert_eq!(
Clock::from_pin(Some("1700000000"))
.expect("pinned")
.now_secs(),
1_700_000_000
);
assert_eq!(
Clock::from_pin(Some(" 1700000000\n"))
.expect("pinned")
.now_secs(),
1_700_000_000,
"a captured command substitution keeps its whitespace"
);
assert_eq!(
Clock::from_pin(Some("0")).expect("pinned").now_secs(),
0,
"the epoch itself is a legal pin"
);
}
#[test]
fn a_malformed_pin_is_refused_naming_the_variable() {
for raw in ["", " ", "abc", "-1", "1.5", "1_700_000_000", "2026-08-17"] {
let err = Clock::from_pin(Some(raw)).expect_err("malformed pin is refused");
let text = err.to_string();
assert!(
text.contains(VAR),
"the message names the variable so the misconfiguration is findable: {text}"
);
assert!(
text.contains(raw) || raw.trim().is_empty(),
"and quotes what was actually set: {text}"
);
}
}
#[test]
fn a_pin_past_u64_is_malformed_rather_than_wrapped() {
assert!(
Clock::from_pin(Some("18446744073709551616")).is_err(),
"an overflowing epoch is refused, never silently truncated"
);
}
}