o192 0.2.2

ORION-192: ordered, resilient, independent, URL-safe 192-bit IDs for distributed systems.
Documentation
//! Hybrid clock: prefer monotonic, follow wall on large forward jumps.

use std::time::{Instant, SystemTime, UNIX_EPOCH};

use crate::alphabet::FORWARD_JUMP_NS;

/// Trait object alias for an injectable Unix-nanosecond clock.
pub(crate) type UnixNanoClock = Box<dyn FnMut() -> u128 + Send>;

/// Build the default hybrid clock for the current process.
///
/// The returned closure samples both the wall clock
/// (`SystemTime::now`) and the monotonic clock (`Instant::now`) on
/// each call, and prefers the monotonic estimate unless the wall
/// clock has jumped forward by more than [`FORWARD_JUMP_NS`].
pub(crate) fn create_hybrid_clock() -> UnixNanoClock {
    let base_wall_ns = system_time_ns();
    let base_instant = Instant::now();
    Box::new(move || {
        let wall_ns = system_time_ns();
        let mono_ns = base_wall_ns.saturating_add(base_instant.elapsed().as_nanos());
        if wall_ns > mono_ns + FORWARD_JUMP_NS {
            wall_ns
        } else {
            mono_ns
        }
    })
}

/// Return the wall clock as Unix nanoseconds, clamped to `0` if the
/// system clock is set before the Unix epoch.
fn system_time_ns() -> u128 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map_or(0, |duration| duration.as_nanos())
}