rusty_model/
common.rs

1//! Common utilities and shared types used across the system
2//!
3//! This module contains types and functions that are used by multiple components
4//! of the HFT system.
5
6use quanta::Clock;
7use serde::{Deserialize, Serialize};
8use std::fmt::{self, Display};
9use std::time::Duration;
10
11/// System-wide log levels
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13pub enum LogLevel {
14    /// Trace level logging.
15    Trace,
16    /// Debug level logging.
17    Debug,
18    /// Info level logging.
19    Info,
20    /// Warn level logging.
21    Warn,
22    /// Error level logging.
23    Error,
24    /// Fatal level logging.
25    Fatal,
26}
27
28impl Display for LogLevel {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Self::Trace => write!(f, "TRACE"),
32            Self::Debug => write!(f, "DEBUG"),
33            Self::Info => write!(f, "INFO"),
34            Self::Warn => write!(f, "WARN"),
35            Self::Error => write!(f, "ERROR"),
36            Self::Fatal => write!(f, "FATAL"),
37        }
38    }
39}
40
41/// Result type for errors with context
42pub type Result<T> = std::result::Result<T, anyhow::Error>;
43
44/// Get current time in nanoseconds using high-precision quanta clock
45#[inline]
46#[must_use]
47pub fn current_time_ns() -> u64 {
48    // Use quanta Clock for high-precision nanosecond timestamps
49    let clock = Clock::new();
50    clock.raw()
51}
52
53/// Convert nanoseconds to milliseconds
54#[inline]
55#[must_use]
56pub const fn nanoseconds_to_milliseconds(nanoseconds: u64) -> u64 {
57    nanoseconds / 1_000_000
58}
59
60/// Convert milliseconds to nanoseconds
61#[inline]
62#[must_use]
63pub const fn milliseconds_to_nanoseconds(milliseconds: u64) -> u64 {
64    milliseconds * 1_000_000
65}
66
67/// Check if a timestamp is older than specified duration using high-precision clock
68#[inline]
69#[must_use]
70pub fn is_stale(timestamp_ns: u64, max_age: Duration) -> bool {
71    let clock = Clock::new();
72    let now = clock.raw();
73    let age_ns = now.saturating_sub(timestamp_ns);
74
75    age_ns > u64::try_from(max_age.as_nanos()).unwrap_or(u64::MAX)
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_time_conversions() {
84        // Test nanoseconds to milliseconds
85        assert_eq!(nanoseconds_to_milliseconds(0), 0);
86        assert_eq!(nanoseconds_to_milliseconds(1_000_000), 1);
87        assert_eq!(nanoseconds_to_milliseconds(1_500_000), 1); // Truncates
88        assert_eq!(nanoseconds_to_milliseconds(1_000_000_000), 1_000);
89
90        // Test milliseconds to nanoseconds
91        assert_eq!(milliseconds_to_nanoseconds(0), 0);
92        assert_eq!(milliseconds_to_nanoseconds(1), 1_000_000);
93        assert_eq!(milliseconds_to_nanoseconds(1_000), 1_000_000_000);
94    }
95
96    #[test]
97    fn test_time_conversions_const_context() {
98        // Verify that time conversion functions can be used in const contexts
99        const ZERO_NANOS: u64 = 0;
100        const MILLION_NANOS: u64 = 1_000_000;
101        const BILLION_NANOS: u64 = 1_000_000_000;
102
103        const ZERO_MILLIS: u64 = nanoseconds_to_milliseconds(ZERO_NANOS);
104        const ONE_MILLI: u64 = nanoseconds_to_milliseconds(MILLION_NANOS);
105        const THOUSAND_MILLIS: u64 = nanoseconds_to_milliseconds(BILLION_NANOS);
106
107        assert_eq!(ZERO_MILLIS, 0);
108        assert_eq!(ONE_MILLI, 1);
109        assert_eq!(THOUSAND_MILLIS, 1_000);
110
111        const BACK_TO_NANOS: u64 = milliseconds_to_nanoseconds(ONE_MILLI);
112        const BACK_TO_BILLION: u64 = milliseconds_to_nanoseconds(THOUSAND_MILLIS);
113
114        assert_eq!(BACK_TO_NANOS, 1_000_000);
115        assert_eq!(BACK_TO_BILLION, 1_000_000_000);
116    }
117}