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