]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/hermit/time.rs
Rollup merge of #103065 - aDotInTheVoid:rdj-arg-pattern, r=GuillaumeGomez
[rust.git] / library / std / src / sys / hermit / time.rs
1 #![allow(dead_code)]
2
3 use crate::cmp::Ordering;
4 use crate::sys::hermit::abi;
5 use crate::sys::hermit::abi::timespec;
6 use crate::sys::hermit::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
7 use crate::time::Duration;
8 use core::hash::{Hash, Hasher};
9
10 #[derive(Copy, Clone, Debug)]
11 struct Timespec {
12     t: timespec,
13 }
14
15 impl Timespec {
16     const fn zero() -> Timespec {
17         Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
18     }
19
20     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
21         if self >= other {
22             Ok(if self.t.tv_nsec >= other.t.tv_nsec {
23                 Duration::new(
24                     (self.t.tv_sec - other.t.tv_sec) as u64,
25                     (self.t.tv_nsec - other.t.tv_nsec) as u32,
26                 )
27             } else {
28                 Duration::new(
29                     (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
30                     self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
31                 )
32             })
33         } else {
34             match other.sub_timespec(self) {
35                 Ok(d) => Err(d),
36                 Err(d) => Ok(d),
37             }
38         }
39     }
40
41     fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
42         let mut secs = other
43             .as_secs()
44             .try_into() // <- target type would be `libc::time_t`
45             .ok()
46             .and_then(|secs| self.t.tv_sec.checked_add(secs))?;
47
48         // Nano calculations can't overflow because nanos are <1B which fit
49         // in a u32.
50         let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
51         if nsec >= NSEC_PER_SEC as u32 {
52             nsec -= NSEC_PER_SEC as u32;
53             secs = secs.checked_add(1)?;
54         }
55         Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
56     }
57
58     fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
59         let mut secs = other
60             .as_secs()
61             .try_into() // <- target type would be `libc::time_t`
62             .ok()
63             .and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
64
65         // Similar to above, nanos can't overflow.
66         let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
67         if nsec < 0 {
68             nsec += NSEC_PER_SEC as i32;
69             secs = secs.checked_sub(1)?;
70         }
71         Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
72     }
73 }
74
75 impl PartialEq for Timespec {
76     fn eq(&self, other: &Timespec) -> bool {
77         self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
78     }
79 }
80
81 impl Eq for Timespec {}
82
83 impl PartialOrd for Timespec {
84     fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
85         Some(self.cmp(other))
86     }
87 }
88
89 impl Ord for Timespec {
90     fn cmp(&self, other: &Timespec) -> Ordering {
91         let me = (self.t.tv_sec, self.t.tv_nsec);
92         let other = (other.t.tv_sec, other.t.tv_nsec);
93         me.cmp(&other)
94     }
95 }
96
97 impl Hash for Timespec {
98     fn hash<H: Hasher>(&self, state: &mut H) {
99         self.t.tv_sec.hash(state);
100         self.t.tv_nsec.hash(state);
101     }
102 }
103
104 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
105 pub struct Instant {
106     t: Timespec,
107 }
108
109 impl Instant {
110     pub fn now() -> Instant {
111         let mut time: Timespec = Timespec::zero();
112         let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) };
113
114         Instant { t: time }
115     }
116
117     pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
118         self.t.sub_timespec(&other.t).ok()
119     }
120
121     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
122         Some(Instant { t: self.t.checked_add_duration(other)? })
123     }
124
125     pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
126         Some(Instant { t: self.t.checked_sub_duration(other)? })
127     }
128 }
129
130 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
131 pub struct SystemTime {
132     t: Timespec,
133 }
134
135 pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
136
137 impl SystemTime {
138     pub fn now() -> SystemTime {
139         let mut time: Timespec = Timespec::zero();
140         let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) };
141
142         SystemTime { t: time }
143     }
144
145     pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
146         self.t.sub_timespec(&other.t)
147     }
148
149     pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
150         Some(SystemTime { t: self.t.checked_add_duration(other)? })
151     }
152
153     pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
154         Some(SystemTime { t: self.t.checked_sub_duration(other)? })
155     }
156 }