ureq/unversioned/transport/
time.rs1use std::cmp::Ordering;
4use std::ops::{Add, Deref, Div};
5use std::time;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Instant {
10 AlreadyHappened,
12 Exact(time::Instant),
14 NotHappening,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Duration {
21 Exact(time::Duration),
23 NotHappening,
25}
26
27impl Duration {
28 const ZERO: Duration = Duration::Exact(time::Duration::ZERO);
29
30 pub const fn from_secs(secs: u64) -> Duration {
32 Duration::Exact(time::Duration::from_secs(secs))
33 }
34
35 pub const fn from_millis(millis: u64) -> Duration {
37 Duration::Exact(time::Duration::from_millis(millis))
38 }
39
40 pub fn is_not_happening(&self) -> bool {
42 *self == Duration::NotHappening
43 }
44}
45
46const NOT_HAPPENING: time::Duration = time::Duration::from_secs(u64::MAX);
47
48impl Deref for Duration {
49 type Target = time::Duration;
50
51 fn deref(&self) -> &Self::Target {
52 match self {
53 Duration::Exact(v) => v,
54 Duration::NotHappening => &NOT_HAPPENING,
55 }
56 }
57}
58
59impl Instant {
60 pub fn now() -> Self {
62 Instant::Exact(time::Instant::now())
63 }
64
65 pub(crate) fn duration_since(&self, earlier: Instant) -> Duration {
66 match (self, earlier) {
67 (Instant::AlreadyHappened, Instant::AlreadyHappened) => Duration::ZERO,
68 (Instant::AlreadyHappened, Instant::Exact(_)) => Duration::ZERO,
69 (Instant::AlreadyHappened, Instant::NotHappening) => Duration::ZERO,
70 (Instant::Exact(_), Instant::NotHappening) => Duration::ZERO,
71 (Instant::Exact(v1), Instant::Exact(v2)) => {
72 Duration::Exact(v1.saturating_duration_since(v2))
73 }
74 (Instant::Exact(_), Instant::AlreadyHappened) => Duration::NotHappening,
75 (Instant::NotHappening, Instant::AlreadyHappened) => Duration::NotHappening,
76 (Instant::NotHappening, Instant::Exact(_)) => Duration::NotHappening,
77 (Instant::NotHappening, Instant::NotHappening) => Duration::NotHappening,
78 }
79 }
80}
81
82impl Add<Duration> for Instant {
83 type Output = Instant;
84
85 fn add(self, rhs: Duration) -> Self::Output {
86 match (self, rhs) {
87 (Instant::AlreadyHappened, Duration::Exact(_)) => Instant::AlreadyHappened,
88 (Instant::AlreadyHappened, Duration::NotHappening) => Instant::AlreadyHappened,
89 (Instant::Exact(v1), Duration::Exact(v2)) => Instant::Exact(v1.add(v2)),
90 (Instant::Exact(_), Duration::NotHappening) => Instant::NotHappening,
91 (Instant::NotHappening, Duration::Exact(_)) => Instant::NotHappening,
92 (Instant::NotHappening, Duration::NotHappening) => Instant::NotHappening,
93 }
94 }
95}
96
97impl Div<u32> for Duration {
98 type Output = Duration;
99
100 fn div(self, rhs: u32) -> Self::Output {
101 match self {
102 Duration::Exact(d) => Duration::Exact(d / rhs),
103 Duration::NotHappening => Duration::NotHappening,
104 }
105 }
106}
107
108impl PartialOrd for Instant {
109 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110 Some(Self::cmp(self, other))
111 }
112}
113
114impl Ord for Instant {
115 fn cmp(&self, other: &Self) -> Ordering {
116 match (self, other) {
117 (Instant::AlreadyHappened, Instant::AlreadyHappened) => Ordering::Equal,
118 (Instant::AlreadyHappened, Instant::Exact(_)) => Ordering::Less,
119 (Instant::AlreadyHappened, Instant::NotHappening) => Ordering::Less,
120 (Instant::Exact(_), Instant::AlreadyHappened) => Ordering::Greater,
121 (Instant::Exact(v1), Instant::Exact(v2)) => v1.cmp(v2),
122 (Instant::Exact(_), Instant::NotHappening) => Ordering::Less,
123 (Instant::NotHappening, Instant::AlreadyHappened) => Ordering::Greater,
124 (Instant::NotHappening, Instant::Exact(_)) => Ordering::Greater,
125 (Instant::NotHappening, Instant::NotHappening) => Ordering::Equal,
126 }
127 }
128}
129
130impl PartialOrd for Duration {
131 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
132 Some(Self::cmp(self, other))
133 }
134}
135
136impl Ord for Duration {
137 fn cmp(&self, other: &Self) -> Ordering {
138 match (self, other) {
139 (Duration::Exact(v1), Duration::Exact(v2)) => v1.cmp(v2),
140 (Duration::Exact(_), Duration::NotHappening) => Ordering::Less,
141 (Duration::NotHappening, Duration::Exact(_)) => Ordering::Greater,
142 (Duration::NotHappening, Duration::NotHappening) => Ordering::Equal,
143 }
144 }
145}
146
147impl From<std::time::Duration> for Duration {
148 fn from(value: std::time::Duration) -> Self {
149 Self::Exact(value)
150 }
151}
152
153#[cfg(test)]
154mod test {
155 use super::*;
156
157 #[test]
158 fn time_ord() {
159 assert!(Instant::AlreadyHappened < Instant::now());
160 assert!(Instant::now() < Instant::NotHappening);
161 assert!(Instant::AlreadyHappened < Instant::NotHappening);
162 }
163}