3 use crate::cmp
::Ordering
;
4 use crate::convert
::TryInto
;
5 use crate::sys
::hermit
::abi
;
6 use crate::sys
::hermit
::abi
::timespec
;
7 use crate::sys
::hermit
::abi
::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}
;
8 use crate::time
::Duration
;
9 use core
::hash
::{Hash, Hasher}
;
11 #[derive(Copy, Clone, Debug)]
17 const fn zero() -> Timespec
{
18 Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 }
}
21 fn sub_timespec(&self, other
: &Timespec
) -> Result
<Duration
, Duration
> {
23 Ok(if self.t
.tv_nsec
>= other
.t
.tv_nsec
{
25 (self.t
.tv_sec
- other
.t
.tv_sec
) as u64,
26 (self.t
.tv_nsec
- other
.t
.tv_nsec
) as u32,
30 (self.t
.tv_sec
- 1 - other
.t
.tv_sec
) as u64,
31 self.t
.tv_nsec
as u32 + (NSEC_PER_SEC
as u32) - other
.t
.tv_nsec
as u32,
35 match other
.sub_timespec(self) {
42 fn checked_add_duration(&self, other
: &Duration
) -> Option
<Timespec
> {
45 .try_into() // <- target type would be `libc::time_t`
47 .and_then(|secs
| self.t
.tv_sec
.checked_add(secs
))?
;
49 // Nano calculations can't overflow because nanos are <1B which fit
51 let mut nsec
= other
.subsec_nanos() + self.t
.tv_nsec
as u32;
52 if nsec
>= NSEC_PER_SEC
as u32 {
53 nsec
-= NSEC_PER_SEC
as u32;
54 secs
= secs
.checked_add(1)?
;
56 Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ }
})
59 fn checked_sub_duration(&self, other
: &Duration
) -> Option
<Timespec
> {
62 .try_into() // <- target type would be `libc::time_t`
64 .and_then(|secs
| self.t
.tv_sec
.checked_sub(secs
))?
;
66 // Similar to above, nanos can't overflow.
67 let mut nsec
= self.t
.tv_nsec
as i32 - other
.subsec_nanos() as i32;
69 nsec
+= NSEC_PER_SEC
as i32;
70 secs
= secs
.checked_sub(1)?
;
72 Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ }
})
76 impl PartialEq
for Timespec
{
77 fn eq(&self, other
: &Timespec
) -> bool
{
78 self.t
.tv_sec
== other
.t
.tv_sec
&& self.t
.tv_nsec
== other
.t
.tv_nsec
82 impl Eq
for Timespec {}
84 impl PartialOrd
for Timespec
{
85 fn partial_cmp(&self, other
: &Timespec
) -> Option
<Ordering
> {
90 impl Ord
for Timespec
{
91 fn cmp(&self, other
: &Timespec
) -> Ordering
{
92 let me
= (self.t
.tv_sec
, self.t
.tv_nsec
);
93 let other
= (other
.t
.tv_sec
, other
.t
.tv_nsec
);
98 impl Hash
for Timespec
{
99 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
100 self.t
.tv_sec
.hash(state
);
101 self.t
.tv_nsec
.hash(state
);
105 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
111 pub fn now() -> Instant
{
112 let mut time
: Timespec
= Timespec
::zero();
113 let _
= unsafe { abi::clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) }
;
118 pub const fn zero() -> Instant
{
119 Instant { t: Timespec::zero() }
122 pub fn actually_monotonic() -> bool
{
126 pub fn checked_sub_instant(&self, other
: &Instant
) -> Option
<Duration
> {
127 self.t
.sub_timespec(&other
.t
).ok()
130 pub fn checked_add_duration(&self, other
: &Duration
) -> Option
<Instant
> {
131 Some(Instant { t: self.t.checked_add_duration(other)? }
)
134 pub fn checked_sub_duration(&self, other
: &Duration
) -> Option
<Instant
> {
135 Some(Instant { t: self.t.checked_sub_duration(other)? }
)
139 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
140 pub struct SystemTime
{
144 pub const UNIX_EPOCH
: SystemTime
= SystemTime { t: Timespec::zero() }
;
147 pub fn now() -> SystemTime
{
148 let mut time
: Timespec
= Timespec
::zero();
149 let _
= unsafe { abi::clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) }
;
151 SystemTime { t: time }
154 pub fn sub_time(&self, other
: &SystemTime
) -> Result
<Duration
, Duration
> {
155 self.t
.sub_timespec(&other
.t
)
158 pub fn checked_add_duration(&self, other
: &Duration
) -> Option
<SystemTime
> {
159 Some(SystemTime { t: self.t.checked_add_duration(other)? }
)
162 pub fn checked_sub_duration(&self, other
: &Duration
) -> Option
<SystemTime
> {
163 Some(SystemTime { t: self.t.checked_sub_duration(other)? }
)