]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/vxworks/time.rs
Rollup merge of #63004 - JohnTitor:add-tests-for-54062, r=Centril
[rust.git] / src / libstd / sys / vxworks / time.rs
1 use crate::cmp::Ordering;
2 use libc;
3 use crate::time::Duration;
4 use ::core::hash::{Hash, Hasher};
5
6 pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
7 use crate::convert::TryInto;
8
9 const NSEC_PER_SEC: u64 = 1_000_000_000;
10
11 #[derive(Copy, Clone)]
12 struct Timespec {
13     t: libc::timespec,
14 }
15
16 impl Timespec {
17     const fn zero() -> Timespec {
18         Timespec {
19             t: libc::timespec { tv_sec: 0, tv_nsec: 0 },
20         }
21     }
22     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
23         if self >= other {
24             Ok(if self.t.tv_nsec >= other.t.tv_nsec {
25                 Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
26                                 (self.t.tv_nsec - other.t.tv_nsec) as u32)
27                 } else {
28                     Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
29                         self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
30                         other.t.tv_nsec as u32)
31                 })
32         } else {
33             match other.sub_timespec(self) {
34                 Ok(d) => Err(d),
35                 Err(d) => Ok(d),
36             }
37         }
38     }
39
40     fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
41         let mut secs = other
42             .as_secs()
43             .try_into() // <- target type would be `libc::time_t`
44             .ok()
45             .and_then(|secs| self.t.tv_sec.checked_add(secs))?;
46
47         // Nano calculations can't overflow because nanos are <1B which fit
48         // in a u32.
49         let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
50         if nsec >= NSEC_PER_SEC as u32 {
51             nsec -= NSEC_PER_SEC as u32;
52             secs = secs.checked_add(1)?;
53         }
54         Some(Timespec {
55             t: libc::timespec {
56                 tv_sec: secs,
57                 tv_nsec: nsec as _,
58             },
59         })
60     }
61
62     fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
63         let mut secs = other
64             .as_secs()
65             .try_into() // <- target type would be `libc::time_t`
66             .ok()
67             .and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
68
69         // Similar to above, nanos can't overflow.
70         let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
71         if nsec < 0 {
72             nsec += NSEC_PER_SEC as i32;
73             secs = secs.checked_sub(1)?;
74         }
75         Some(Timespec {
76             t: libc::timespec {
77                 tv_sec: secs,
78                 tv_nsec: nsec as _,
79             },
80         })
81     }
82 }
83
84 impl PartialEq for Timespec {
85     fn eq(&self, other: &Timespec) -> bool {
86         self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
87     }
88 }
89
90 impl Eq for Timespec {}
91
92 impl PartialOrd for Timespec {
93     fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
94         Some(self.cmp(other))
95     }
96 }
97
98 impl Ord for Timespec {
99     fn cmp(&self, other: &Timespec) -> Ordering {
100         let me = (self.t.tv_sec, self.t.tv_nsec);
101         let other = (other.t.tv_sec, other.t.tv_nsec);
102         me.cmp(&other)
103     }
104 }
105
106 impl Hash for Timespec {
107     fn hash<H : Hasher>(&self, state: &mut H) {
108         self.t.tv_sec.hash(state);
109         self.t.tv_nsec.hash(state);
110     }
111 }
112 mod inner {
113     use crate::fmt;
114     use libc;
115     use crate::sys::cvt;
116     use crate::time::Duration;
117
118     use super::Timespec;
119
120     #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
121     pub struct Instant {
122         t: Timespec,
123     }
124
125     #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
126     pub struct SystemTime {
127         t: Timespec,
128     }
129
130     pub const UNIX_EPOCH: SystemTime = SystemTime {
131         t: Timespec {
132             t: libc::timespec {
133                 tv_sec: 0,
134                 tv_nsec: 0,
135             },
136         },
137     };
138
139     impl Instant {
140         pub fn now() -> Instant {
141             Instant { t: now(libc::CLOCK_MONOTONIC) }
142         }
143
144         pub const fn zero() -> Instant {
145             Instant {
146                 t: Timespec::zero(),
147             }
148         }
149
150         pub fn actually_monotonic() -> bool {
151             true
152         }
153
154         pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
155             self.t.sub_timespec(&other.t).ok()
156         }
157
158         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
159             Some(Instant { t: self.t.checked_add_duration(other)? })
160         }
161
162         pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
163             Some(Instant { t: self.t.checked_sub_duration(other)? })
164         }
165     }
166
167     impl fmt::Debug for Instant {
168         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169             f.debug_struct("Instant")
170              .field("tv_sec", &self.t.t.tv_sec)
171              .field("tv_nsec", &self.t.t.tv_nsec)
172              .finish()
173         }
174     }
175
176     impl SystemTime {
177         pub fn now() -> SystemTime {
178             SystemTime { t: now(libc::CLOCK_REALTIME) }
179         }
180
181         pub fn sub_time(&self, other: &SystemTime)
182                         -> Result<Duration, Duration> {
183             self.t.sub_timespec(&other.t)
184         }
185
186         pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
187             Some(SystemTime { t: self.t.checked_add_duration(other)? })
188         }
189
190         pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
191             Some(SystemTime { t: self.t.checked_sub_duration(other)? })
192         }
193     }
194
195     impl From<libc::timespec> for SystemTime {
196         fn from(t: libc::timespec) -> SystemTime {
197             SystemTime { t: Timespec { t: t } }
198         }
199     }
200
201     impl fmt::Debug for SystemTime {
202         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203             f.debug_struct("SystemTime")
204              .field("tv_sec", &self.t.t.tv_sec)
205              .field("tv_nsec", &self.t.t.tv_nsec)
206              .finish()
207         }
208     }
209
210     pub type clock_t = libc::c_int;
211
212     fn now(clock: clock_t) -> Timespec {
213         let mut t = Timespec {
214             t: libc::timespec {
215                 tv_sec: 0,
216                 tv_nsec: 0,
217             }
218         };
219         cvt(unsafe {
220             libc::clock_gettime(clock, &mut t.t)
221         }).unwrap();
222         t
223     }
224 }