1 #![allow(dead_code)] 2 3 use crate::std::cmp::Ordering; 4 use crate::std::ops::{Add, AddAssign, Sub, SubAssign}; 5 use crate::std::sys::hermit::abi; 6 use crate::std::sys::hermit::abi::timespec; 7 use crate::std::sys::hermit::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; 8 use crate::std::time::Duration; 9 use core::hash::{Hash, Hasher}; 10 11 #[derive(Copy, Clone, Debug)] 12 struct Timespec { 13 t: timespec, 14 } 15 16 impl Timespec { zero() -> Timespec17 const fn zero() -> Timespec { 18 Timespec { 19 t: timespec { 20 tv_sec: 0, 21 tv_nsec: 0, 22 }, 23 } 24 } 25 sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration>26 fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { 27 if self >= other { 28 Ok(if self.t.tv_nsec >= other.t.tv_nsec { 29 Duration::new( 30 (self.t.tv_sec - other.t.tv_sec) as u64, 31 (self.t.tv_nsec - other.t.tv_nsec) as u32, 32 ) 33 } else { 34 Duration::new( 35 (self.t.tv_sec - 1 - other.t.tv_sec) as u64, 36 self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32, 37 ) 38 }) 39 } else { 40 match other.sub_timespec(self) { 41 Ok(d) => Err(d), 42 Err(d) => Ok(d), 43 } 44 } 45 } 46 checked_add_duration(&self, other: &Duration) -> Option<Timespec>47 fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { 48 let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?; 49 50 // Nano calculations can't overflow because nanos are <1B which fit 51 // in a u32. 52 let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; 53 if nsec >= NSEC_PER_SEC as u32 { 54 nsec -= NSEC_PER_SEC as u32; 55 secs = secs.checked_add(1)?; 56 } 57 Some(Timespec { 58 t: timespec { 59 tv_sec: secs, 60 tv_nsec: nsec as _, 61 }, 62 }) 63 } 64 checked_sub_duration(&self, other: &Duration) -> Option<Timespec>65 fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { 66 let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?; 67 68 // Similar to above, nanos can't overflow. 69 let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32; 70 if nsec < 0 { 71 nsec += NSEC_PER_SEC as i32; 72 secs = secs.checked_sub(1)?; 73 } 74 Some(Timespec { 75 t: timespec { 76 tv_sec: secs, 77 tv_nsec: nsec as _, 78 }, 79 }) 80 } 81 } 82 83 impl PartialEq for Timespec { eq(&self, other: &Timespec) -> bool84 fn eq(&self, other: &Timespec) -> bool { 85 self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec 86 } 87 } 88 89 impl Eq for Timespec {} 90 91 impl PartialOrd for Timespec { partial_cmp(&self, other: &Timespec) -> Option<Ordering>92 fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> { 93 Some(self.cmp(other)) 94 } 95 } 96 97 impl Ord for Timespec { cmp(&self, other: &Timespec) -> Ordering98 fn cmp(&self, other: &Timespec) -> Ordering { 99 let me = (self.t.tv_sec, self.t.tv_nsec); 100 let other = (other.t.tv_sec, other.t.tv_nsec); 101 me.cmp(&other) 102 } 103 } 104 105 impl Hash for Timespec { hash<H: Hasher>(&self, state: &mut H)106 fn hash<H: Hasher>(&self, state: &mut H) { 107 self.t.tv_sec.hash(state); 108 self.t.tv_nsec.hash(state); 109 } 110 } 111 112 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] 113 pub struct Instant(Timespec); 114 115 impl Instant { now() -> Instant116 pub fn now() -> Instant { 117 let mut time: Timespec = Timespec::zero(); 118 let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) }; 119 120 Instant(time) 121 } 122 elapsed(&self) -> Duration123 pub fn elapsed(&self) -> Duration { 124 Instant::now() - *self 125 } 126 duration_since(&self, earlier: Instant) -> Duration127 pub fn duration_since(&self, earlier: Instant) -> Duration { 128 self.checked_duration_since(earlier).unwrap_or_default() 129 } 130 checked_duration_since(&self, earlier: Instant) -> Option<Duration>131 pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> { 132 self.checked_sub_instant(&earlier) 133 } 134 checked_sub_instant(&self, other: &Instant) -> Option<Duration>135 pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { 136 self.0.sub_timespec(&other.0).ok() 137 } 138 checked_add_duration(&self, other: &Duration) -> Option<Instant>139 pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { 140 Some(Instant(self.0.checked_add_duration(other)?)) 141 } 142 checked_sub_duration(&self, other: &Duration) -> Option<Instant>143 pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { 144 Some(Instant(self.0.checked_sub_duration(other)?)) 145 } 146 checked_add(&self, duration: Duration) -> Option<Instant>147 pub fn checked_add(&self, duration: Duration) -> Option<Instant> { 148 self.0.checked_add_duration(&duration).map(Instant) 149 } 150 checked_sub(&self, duration: Duration) -> Option<Instant>151 pub fn checked_sub(&self, duration: Duration) -> Option<Instant> { 152 self.0.checked_sub_duration(&duration).map(Instant) 153 } 154 } 155 156 impl Add<Duration> for Instant { 157 type Output = Instant; 158 159 /// # Panics 160 /// 161 /// This function may panic if the resulting point in time cannot be represented by the 162 /// underlying data structure. See [`Instant::checked_add`] for a version without panic. add(self, other: Duration) -> Instant163 fn add(self, other: Duration) -> Instant { 164 self.checked_add(other) 165 .expect("overflow when adding duration to instant") 166 } 167 } 168 169 impl AddAssign<Duration> for Instant { add_assign(&mut self, other: Duration)170 fn add_assign(&mut self, other: Duration) { 171 *self = *self + other; 172 } 173 } 174 175 impl Sub<Duration> for Instant { 176 type Output = Instant; 177 sub(self, other: Duration) -> Instant178 fn sub(self, other: Duration) -> Instant { 179 self.checked_sub(other) 180 .expect("overflow when subtracting duration from instant") 181 } 182 } 183 184 impl SubAssign<Duration> for Instant { sub_assign(&mut self, other: Duration)185 fn sub_assign(&mut self, other: Duration) { 186 *self = *self - other; 187 } 188 } 189 190 impl Sub<Instant> for Instant { 191 type Output = Duration; 192 193 /// Returns the amount of time elapsed from another instant to this one, 194 /// or zero duration if that instant is later than this one. 195 /// 196 /// # Panics 197 /// 198 /// Previous rust versions panicked when `other` was later than `self`. Currently this 199 /// method saturates. Future versions may reintroduce the panic in some circumstances. 200 /// See [Monotonicity]. 201 /// 202 /// [Monotonicity]: Instant#monotonicity sub(self, other: Instant) -> Duration203 fn sub(self, other: Instant) -> Duration { 204 self.duration_since(other) 205 } 206 } 207 208 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 209 pub struct SystemTime(Timespec); 210 211 pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); 212 213 impl SystemTime { now() -> SystemTime214 pub fn now() -> SystemTime { 215 let mut time: Timespec = Timespec::zero(); 216 let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) }; 217 218 SystemTime(time) 219 } 220 sub_time(&self, other: &SystemTime) -> Result<Duration, Duration>221 pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { 222 self.0.sub_timespec(&other.0) 223 } 224 checked_add_duration(&self, other: &Duration) -> Option<SystemTime>225 pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { 226 Some(SystemTime(self.0.checked_add_duration(other)?)) 227 } 228 checked_sub_duration(&self, other: &Duration) -> Option<SystemTime>229 pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { 230 Some(SystemTime(self.0.checked_sub_duration(other)?)) 231 } 232 } 233