clocksource/precise/
unix_instant.rs1use core::ops::{Add, AddAssign, Sub, SubAssign};
2
3use super::Duration;
4
5#[repr(transparent)]
26#[derive(Copy, Clone, Default, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
27pub struct UnixInstant {
28 pub(crate) ns: u64,
29}
30
31impl UnixInstant {
32 pub const EPOCH: UnixInstant = UnixInstant { ns: 0 };
35
36 pub fn now() -> Self {
38 crate::sys::realtime::precise()
39 }
40
41 pub fn elapsed(&self) -> Duration {
43 Self::now() - *self
44 }
45
46 pub fn duration_since(&self, earlier: Self) -> Duration {
49 *self - earlier
50 }
51
52 pub fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
53 self.ns.checked_sub(earlier.ns).map(|ns| Duration { ns })
54 }
55
56 pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
57 self.ns.checked_sub(duration.ns).map(|ns| Self { ns })
58 }
59}
60
61impl Add<Duration> for UnixInstant {
62 type Output = UnixInstant;
63
64 fn add(self, rhs: Duration) -> Self::Output {
65 UnixInstant {
66 ns: self.ns + rhs.ns,
67 }
68 }
69}
70
71impl Add<core::time::Duration> for UnixInstant {
72 type Output = UnixInstant;
73
74 fn add(self, rhs: core::time::Duration) -> Self::Output {
75 UnixInstant {
76 ns: self.ns + rhs.as_nanos() as u64,
77 }
78 }
79}
80
81impl Sub<UnixInstant> for UnixInstant {
82 type Output = Duration;
83
84 fn sub(self, rhs: UnixInstant) -> Self::Output {
85 Duration {
86 ns: self.ns - rhs.ns,
87 }
88 }
89}
90
91impl AddAssign<Duration> for UnixInstant {
92 fn add_assign(&mut self, rhs: Duration) {
93 self.ns += rhs.ns;
94 }
95}
96
97impl Sub<Duration> for UnixInstant {
98 type Output = UnixInstant;
99
100 fn sub(self, rhs: Duration) -> Self::Output {
101 UnixInstant {
102 ns: self.ns - rhs.ns,
103 }
104 }
105}
106
107impl SubAssign<Duration> for UnixInstant {
108 fn sub_assign(&mut self, rhs: Duration) {
109 self.ns -= rhs.ns;
110 }
111}
112
113impl AddAssign<core::time::Duration> for UnixInstant {
114 fn add_assign(&mut self, rhs: core::time::Duration) {
115 self.ns += rhs.as_nanos() as u64;
116 }
117}
118
119impl Sub<core::time::Duration> for UnixInstant {
120 type Output = UnixInstant;
121
122 fn sub(self, rhs: core::time::Duration) -> Self::Output {
123 UnixInstant {
124 ns: self.ns - rhs.as_nanos() as u64,
125 }
126 }
127}
128
129impl SubAssign<core::time::Duration> for UnixInstant {
130 fn sub_assign(&mut self, rhs: core::time::Duration) {
131 self.ns -= rhs.as_nanos() as u64;
132 }
133}
134
135impl From<crate::coarse::UnixInstant> for UnixInstant {
136 fn from(other: crate::coarse::UnixInstant) -> Self {
137 Self {
138 ns: other.secs as u64 * super::Duration::NANOSECOND.as_nanos(),
139 }
140 }
141}
142
143pub struct TryFromError {
144 kind: TryFromErrorKind,
145}
146
147enum TryFromErrorKind {
148 Overflow,
149 BeforeEpoch,
150}
151
152impl TryFromError {
153 const fn description(&self) -> &'static str {
154 match self.kind {
155 TryFromErrorKind::Overflow => "can not convert to UnixInstant: value is too big",
156 TryFromErrorKind::BeforeEpoch => {
157 "can not convert to UnixInstant: value is before unix epoch"
158 }
159 }
160 }
161}
162
163impl core::fmt::Display for TryFromError {
164 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165 self.description().fmt(f)
166 }
167}
168
169impl TryFrom<std::time::SystemTime> for UnixInstant {
170 type Error = TryFromError;
171
172 fn try_from(other: std::time::SystemTime) -> Result<Self, Self::Error> {
173 let other = other
174 .duration_since(std::time::SystemTime::UNIX_EPOCH)
175 .map_err(|_| TryFromError {
176 kind: TryFromErrorKind::BeforeEpoch,
177 })?
178 .as_nanos();
179 if other > u64::MAX as u128 {
180 Err(TryFromError {
181 kind: TryFromErrorKind::Overflow,
182 })
183 } else {
184 Ok(Self { ns: other as u64 })
185 }
186 }
187}