1use std::ops::Add;
4use std::time::Duration;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
11pub struct Virtual(u64);
12
13impl Virtual {
14 #[must_use]
16 pub const fn epoch() -> Self {
17 Self(0)
18 }
19
20 #[must_use]
22 pub const fn at_millis(millis: u64) -> Self {
23 Self(millis.saturating_mul(1_000_000))
24 }
25
26 #[must_use]
28 pub const fn at_nanos(nanos: u64) -> Self {
29 Self(nanos)
30 }
31
32 #[must_use]
34 pub const fn millis(self) -> u64 {
35 self.0 / 1_000_000
36 }
37
38 #[must_use]
40 pub const fn nanos(self) -> u64 {
41 self.0
42 }
43}
44
45impl Add<Duration> for Virtual {
46 type Output = Self;
47
48 fn add(self, after: Duration) -> Self {
49 Self(
50 self.0
51 .saturating_add(u64::try_from(after.as_nanos()).unwrap_or(u64::MAX)),
52 )
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn adding_sub_millisecond_time_preserves_every_nanosecond() {
62 let instant = Virtual::epoch() + Duration::from_nanos(999_999);
63
64 assert_eq!(instant.nanos(), 999_999);
65 assert_eq!(instant.millis(), 0);
66 }
67}