1use crate::{
8 AsHandleRef, HandleBased, HandleRef, NullableHandle, ObjectQuery, Status, Topic, ok, sys,
9};
10use std::cmp::{Eq, Ord, PartialEq, PartialOrd};
11use std::hash::Hash;
12use std::{ops, time as stdtime};
13use zerocopy::{FromBytes, Immutable, IntoBytes};
14
15pub type MonotonicInstant = Instant<MonotonicTimeline, NsUnit>;
17
18pub type SyntheticInstant = Instant<SyntheticTimeline, NsUnit>;
20
21pub type BootInstant = Instant<BootTimeline>;
23
24pub type Ticks<T> = Instant<T, TicksUnit>;
27
28pub type MonotonicTicks = Instant<MonotonicTimeline, TicksUnit>;
31
32pub type BootTicks = Instant<BootTimeline, TicksUnit>;
34
35pub type MonotonicDuration = Duration<MonotonicTimeline>;
37
38pub type BootDuration = Duration<BootTimeline>;
40
41pub type SyntheticDuration = Duration<SyntheticTimeline, NsUnit>;
43
44pub type MonotonicDurationTicks = Duration<MonotonicTimeline, TicksUnit>;
46
47pub type BootDurationTicks = Duration<BootTimeline, TicksUnit>;
49
50#[derive(
52 Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, FromBytes, IntoBytes, Immutable,
53)]
54#[repr(transparent)]
55pub struct Instant<T, U = NsUnit>(sys::zx_time_t, std::marker::PhantomData<(T, U)>);
56
57impl<T, U> std::fmt::Debug for Instant<T, U> {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 let timeline_name = std::any::type_name::<T>();
61 let short_timeline_name =
62 timeline_name.rsplit_once("::").map(|(_, n)| n).unwrap_or(timeline_name);
63 let units_name = std::any::type_name::<U>();
64 let short_units_name = units_name.rsplit_once("::").map(|(_, n)| n).unwrap_or(units_name);
65 f.debug_tuple(&format!("Instant<{short_timeline_name}, {short_units_name}>"))
66 .field(&self.0)
67 .finish()
68 }
69}
70
71impl MonotonicInstant {
72 pub fn get() -> Self {
78 unsafe { Self::from_nanos(sys::zx_clock_get_monotonic()) }
79 }
80
81 pub fn after(duration: MonotonicDuration) -> Self {
87 unsafe { Self::from_nanos(sys::zx_deadline_after(duration.0)) }
88 }
89
90 pub fn sleep(self) {
96 unsafe {
97 sys::zx_nanosleep(self.0);
98 }
99 }
100}
101
102impl BootInstant {
103 pub fn get() -> Self {
105 unsafe { Self::from_nanos(sys::zx_clock_get_boot()) }
107 }
108
109 pub fn after(duration: BootDuration) -> Self {
111 Self::from_nanos(Self::get().into_nanos().saturating_add(duration.0))
112 }
113}
114
115impl<T: Timeline, U: TimeUnit> Instant<T, U> {
116 pub const ZERO: Instant<T, U> = Instant(0, std::marker::PhantomData);
117}
118
119impl<T: Timeline> Instant<T> {
120 pub const INFINITE: Instant<T, NsUnit> =
121 Instant(sys::ZX_TIME_INFINITE, std::marker::PhantomData);
122 pub const INFINITE_PAST: Instant<T, NsUnit> =
123 Instant(sys::ZX_TIME_INFINITE_PAST, std::marker::PhantomData);
124
125 pub const fn into_nanos(self) -> i64 {
127 self.0
128 }
129
130 pub const fn from_nanos(nanos: i64) -> Self {
132 Instant(nanos, std::marker::PhantomData)
133 }
134}
135
136impl MonotonicTicks {
137 pub fn get() -> Self {
145 Self(unsafe { sys::zx_ticks_get() }, std::marker::PhantomData)
147 }
148}
149
150impl BootTicks {
151 pub fn get() -> Self {
155 Self(unsafe { sys::zx_ticks_get_boot() }, std::marker::PhantomData)
157 }
158}
159
160impl<T: Timeline> Ticks<T> {
161 pub const fn into_raw(self) -> i64 {
163 self.0
164 }
165
166 pub const fn from_raw(raw: i64) -> Self {
168 Self(raw, std::marker::PhantomData)
169 }
170
171 pub fn per_second() -> i64 {
177 unsafe { sys::zx_ticks_per_second() }
179 }
180}
181
182impl<T: Timeline, U: TimeUnit> ops::Add<Duration<T, U>> for Instant<T, U> {
183 type Output = Instant<T, U>;
184 fn add(self, dur: Duration<T, U>) -> Self::Output {
185 Self(self.0.saturating_add(dur.0), std::marker::PhantomData)
186 }
187}
188
189impl<T: Timeline, U: TimeUnit> ops::Sub<Duration<T, U>> for Instant<T, U> {
190 type Output = Instant<T, U>;
191 fn sub(self, dur: Duration<T, U>) -> Self::Output {
192 Self(self.0.saturating_sub(dur.0), std::marker::PhantomData)
193 }
194}
195
196impl<T: Timeline, U: TimeUnit> ops::Sub<Instant<T, U>> for Instant<T, U> {
197 type Output = Duration<T, U>;
198 fn sub(self, rhs: Instant<T, U>) -> Self::Output {
199 Duration(self.0.saturating_sub(rhs.0), std::marker::PhantomData)
200 }
201}
202
203impl<T: Timeline, U: TimeUnit> ops::AddAssign<Duration<T, U>> for Instant<T, U> {
204 fn add_assign(&mut self, dur: Duration<T, U>) {
205 self.0 = self.0.saturating_add(dur.0);
206 }
207}
208
209impl<T: Timeline, U: TimeUnit> ops::SubAssign<Duration<T, U>> for Instant<T, U> {
210 fn sub_assign(&mut self, dur: Duration<T, U>) {
211 self.0 = self.0.saturating_sub(dur.0);
212 }
213}
214
215pub trait Timeline: Default + Copy + Clone + PartialEq + Eq {}
217
218#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
220pub struct MonotonicTimeline;
221impl Timeline for MonotonicTimeline {}
222
223#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
225pub struct BootTimeline;
226impl Timeline for BootTimeline {}
227
228#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
230pub struct SyntheticTimeline;
231impl Timeline for SyntheticTimeline {}
232
233pub trait TimeUnit {}
235
236#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
238pub struct NsUnit;
239impl TimeUnit for NsUnit {}
240
241#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
243pub struct TicksUnit;
244impl TimeUnit for TicksUnit {}
245
246#[derive(
247 Debug,
248 Default,
249 Copy,
250 Clone,
251 Eq,
252 PartialEq,
253 Ord,
254 PartialOrd,
255 Hash,
256 FromBytes,
257 IntoBytes,
258 Immutable,
259)]
260#[repr(transparent)]
261pub struct Duration<T, U = NsUnit>(sys::zx_duration_t, std::marker::PhantomData<(T, U)>);
262
263impl<T: Timeline> From<stdtime::Duration> for Duration<T, NsUnit> {
264 fn from(dur: stdtime::Duration) -> Self {
265 Duration::from_seconds(dur.as_secs() as i64)
266 + Duration::from_nanos(dur.subsec_nanos() as i64)
267 }
268}
269
270impl<T: Timeline, U: TimeUnit> ops::Add<Instant<T, U>> for Duration<T, U> {
271 type Output = Instant<T, U>;
272 fn add(self, time: Instant<T, U>) -> Self::Output {
273 Instant(self.0.saturating_add(time.0), std::marker::PhantomData)
274 }
275}
276
277impl<T: Timeline, U: TimeUnit> ops::Add for Duration<T, U> {
278 type Output = Duration<T, U>;
279 fn add(self, rhs: Duration<T, U>) -> Self::Output {
280 Self(self.0.saturating_add(rhs.0), std::marker::PhantomData)
281 }
282}
283
284impl<T: Timeline, U: TimeUnit> ops::Sub for Duration<T, U> {
285 type Output = Duration<T, U>;
286 fn sub(self, rhs: Duration<T, U>) -> Duration<T, U> {
287 Self(self.0.saturating_sub(rhs.0), std::marker::PhantomData)
288 }
289}
290
291impl<T: Timeline, U: TimeUnit> ops::AddAssign for Duration<T, U> {
292 fn add_assign(&mut self, rhs: Duration<T, U>) {
293 self.0 = self.0.saturating_add(rhs.0);
294 }
295}
296
297impl<T: Timeline, U: TimeUnit> ops::SubAssign for Duration<T, U> {
298 fn sub_assign(&mut self, rhs: Duration<T, U>) {
299 self.0 = self.0.saturating_sub(rhs.0);
300 }
301}
302
303impl<T: Timeline, S: Into<i64>, U: TimeUnit> ops::Mul<S> for Duration<T, U> {
304 type Output = Self;
305 fn mul(self, mul: S) -> Self {
306 Self(self.0.saturating_mul(mul.into()), std::marker::PhantomData)
307 }
308}
309
310impl<S: Into<i64>, T: Timeline, U: TimeUnit> ops::Div<S> for Duration<T, U> {
311 type Output = Self;
312 fn div(self, div: S) -> Self {
313 Self(self.0.saturating_div(div.into()), std::marker::PhantomData)
314 }
315}
316
317impl<T: Timeline, U: TimeUnit> ops::Neg for Duration<T, U> {
318 type Output = Self;
319
320 fn neg(self) -> Self::Output {
321 Self(self.0.saturating_neg(), std::marker::PhantomData)
322 }
323}
324
325impl<T: Timeline> Duration<T, NsUnit> {
326 pub const INFINITE: Duration<T> = Duration(sys::zx_duration_t::MAX, std::marker::PhantomData);
327 pub const INFINITE_PAST: Duration<T> =
328 Duration(sys::zx_duration_t::MIN, std::marker::PhantomData);
329 pub const ZERO: Duration<T> = Duration(0, std::marker::PhantomData);
330
331 pub const fn into_nanos(self) -> i64 {
333 self.0
334 }
335
336 pub const fn into_micros(self) -> i64 {
338 self.0 / 1_000
339 }
340
341 pub const fn into_millis(self) -> i64 {
343 self.into_micros() / 1_000
344 }
345
346 pub const fn into_seconds(self) -> i64 {
348 self.into_millis() / 1_000
349 }
350
351 pub fn into_seconds_f64(self) -> f64 {
353 self.into_nanos() as f64 / 1_000_000_000f64
354 }
355
356 pub const fn into_minutes(self) -> i64 {
358 self.into_seconds() / 60
359 }
360
361 pub const fn into_hours(self) -> i64 {
363 self.into_minutes() / 60
364 }
365
366 pub const fn from_nanos(nanos: i64) -> Self {
367 Duration(nanos, std::marker::PhantomData)
368 }
369
370 pub const fn from_micros(micros: i64) -> Self {
371 Duration(micros.saturating_mul(1_000), std::marker::PhantomData)
372 }
373
374 pub const fn from_millis(millis: i64) -> Self {
375 Duration::from_micros(millis.saturating_mul(1_000))
376 }
377
378 pub const fn from_seconds(secs: i64) -> Self {
379 Duration::from_millis(secs.saturating_mul(1_000))
380 }
381
382 pub const fn from_minutes(min: i64) -> Self {
383 Duration::from_seconds(min.saturating_mul(60))
384 }
385
386 pub const fn from_hours(hours: i64) -> Self {
387 Duration::from_minutes(hours.saturating_mul(60))
388 }
389}
390
391impl<T: Timeline> Duration<T, TicksUnit> {
392 pub const fn into_raw(self) -> i64 {
394 self.0
395 }
396
397 pub const fn from_raw(raw: i64) -> Self {
399 Self(raw, std::marker::PhantomData)
400 }
401}
402
403impl MonotonicDuration {
404 pub fn sleep(self) {
406 MonotonicInstant::after(self).sleep()
407 }
408}
409
410#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
415#[repr(transparent)]
416pub struct Timer<T = MonotonicTimeline>(NullableHandle, std::marker::PhantomData<T>);
418
419#[repr(C)]
420#[derive(Debug, Copy, Clone, Eq, PartialEq, FromBytes, Immutable)]
421pub struct TimerInfo<T: Timeline> {
422 pub options: u32,
423 clock_id: u32,
428 pub deadline: Instant<T>,
429 pub slack: Duration<T>,
430}
431
432pub type MonotonicTimerInfo = TimerInfo<MonotonicTimeline>;
433pub type BootTimerInfo = TimerInfo<BootTimeline>;
434pub type SyntheticTimerInfo = TimerInfo<SyntheticTimeline>;
435
436static_assertions::assert_eq_size!(MonotonicTimerInfo, sys::zx_info_timer_t);
437static_assertions::assert_eq_size!(BootTimerInfo, sys::zx_info_timer_t);
438static_assertions::assert_eq_size!(SyntheticTimerInfo, sys::zx_info_timer_t);
439
440impl<T: Timeline> Default for TimerInfo<T> {
441 fn default() -> Self {
442 Self::from_raw(sys::zx_info_timer_t::default())
443 }
444}
445
446impl<T: Timeline> TimerInfo<T> {
447 fn from_raw(info: sys::zx_info_timer_t) -> Self {
448 zerocopy::transmute!(info)
449 }
450}
451
452struct TimerInfoQuery;
453unsafe impl ObjectQuery for TimerInfoQuery {
454 const TOPIC: Topic = Topic::TIMER;
455 type InfoTy = sys::zx_info_timer_t;
456}
457
458pub type MonotonicTimer = Timer<MonotonicTimeline>;
460
461pub type BootTimer = Timer<BootTimeline>;
463
464impl<T: Timeline> Timer<T> {
465 pub fn info(&self) -> Result<TimerInfo<T>, Status> {
469 Ok(TimerInfo::from_raw(self.0.get_info_single::<TimerInfoQuery>()?))
470 }
471
472 delegated_concrete_handle_based_impls!(|h| Self(h, std::marker::PhantomData));
473}
474
475impl Timer<MonotonicTimeline> {
476 pub fn create() -> Self {
486 let mut out = 0;
487 let opts = 0;
488 let status = unsafe { sys::zx_timer_create(opts, sys::ZX_CLOCK_MONOTONIC, &mut out) };
489 ok(status)
490 .expect("timer creation always succeeds except with OOM or when job policy denies it");
491 unsafe { Self::from(NullableHandle::from_raw(out)) }
492 }
493}
494
495impl Timer<BootTimeline> {
496 pub fn create() -> Self {
508 let mut out = 0;
509 let opts = 0;
510 let status = unsafe { sys::zx_timer_create(opts, sys::ZX_CLOCK_BOOT, &mut out) };
511 ok(status)
512 .expect("timer creation always succeeds except with OOM or when job policy denies it");
513 unsafe { Self::from(NullableHandle::from_raw(out)) }
514 }
515}
516
517impl<T: Timeline> Timer<T> {
518 pub fn set(&self, deadline: Instant<T>, slack: Duration<T, NsUnit>) -> Result<(), Status> {
522 let status = unsafe {
523 sys::zx_timer_set(self.raw_handle(), deadline.into_nanos(), slack.into_nanos())
524 };
525 ok(status)
526 }
527
528 pub fn cancel(&self) -> Result<(), Status> {
532 let status = unsafe { sys::zx_timer_cancel(self.raw_handle()) };
533 ok(status)
534 }
535}
536
537impl<T: Timeline> AsHandleRef for Timer<T> {
538 fn as_handle_ref(&self) -> HandleRef<'_> {
539 self.0.as_handle_ref()
540 }
541}
542
543impl<T: Timeline> From<NullableHandle> for Timer<T> {
544 fn from(handle: NullableHandle) -> Self {
545 Timer(handle, std::marker::PhantomData)
546 }
547}
548
549impl<T: Timeline> From<Timer<T>> for NullableHandle {
550 fn from(x: Timer<T>) -> NullableHandle {
551 x.0
552 }
553}
554
555impl<T: Timeline> HandleBased for Timer<T> {}
556
557#[cfg(test)]
558mod tests {
559 use super::*;
560 use crate::{Signals, WaitResult};
561
562 #[test]
563 fn time_debug_repr_is_short() {
564 assert_eq!(
565 format!("{:?}", MonotonicInstant::from_nanos(0)),
566 "Instant<MonotonicTimeline, NsUnit>(0)"
567 );
568 assert_eq!(
569 format!("{:?}", SyntheticInstant::from_nanos(0)),
570 "Instant<SyntheticTimeline, NsUnit>(0)"
571 );
572 }
573
574 #[test]
575 fn monotonic_time_increases() {
576 let time1 = MonotonicInstant::get();
577 Duration::from_nanos(1_000).sleep();
578 let time2 = MonotonicInstant::get();
579 assert!(time2 > time1);
580 }
581
582 #[test]
583 fn ticks_increases() {
584 let ticks1 = MonotonicTicks::get();
585 Duration::from_nanos(1_000).sleep();
586 let ticks2 = MonotonicTicks::get();
587 assert!(ticks2 > ticks1);
588 }
589
590 #[test]
591 fn boot_time_increases() {
592 let time1 = BootInstant::get();
593 Duration::from_nanos(1_000).sleep();
594 let time2 = BootInstant::get();
595 assert!(time2 > time1);
596 }
597
598 #[test]
599 fn boot_ticks_increases() {
600 let ticks1 = BootTicks::get();
601 Duration::from_nanos(1_000).sleep();
602 let ticks2 = BootTicks::get();
603 assert!(ticks2 > ticks1);
604 }
605
606 #[test]
607 fn tick_length() {
608 let sleep_time = Duration::from_millis(1);
609 let ticks1 = MonotonicTicks::get();
610 sleep_time.sleep();
611 let ticks2 = MonotonicTicks::get();
612
613 let sleep_ticks = MonotonicDurationTicks::from_raw(
615 sleep_time.into_millis() * (MonotonicTicks::per_second() / 1000),
616 );
617 assert!(ticks2 >= (ticks1 + sleep_ticks));
618 }
619
620 #[test]
621 fn sleep() {
622 let sleep_ns = Duration::from_millis(1);
623 let time1 = MonotonicInstant::get();
624 sleep_ns.sleep();
625 let time2 = MonotonicInstant::get();
626 assert!(time2 > time1 + sleep_ns);
627 }
628
629 #[test]
630 fn from_std() {
631 let std_dur = stdtime::Duration::new(25, 25);
632 let dur = MonotonicDuration::from(std_dur);
633 let std_dur_nanos = (1_000_000_000 * std_dur.as_secs()) + std_dur.subsec_nanos() as u64;
634 assert_eq!(std_dur_nanos as i64, dur.into_nanos());
635 }
636
637 #[test]
638 fn i64_conversions() {
639 let nanos_in_one_hour = 3_600_000_000_000;
640 let dur_from_nanos = MonotonicDuration::from_nanos(nanos_in_one_hour);
641 let dur_from_hours = MonotonicDuration::from_hours(1);
642 assert_eq!(dur_from_nanos, dur_from_hours);
643 assert_eq!(dur_from_nanos.into_nanos(), dur_from_hours.into_nanos());
644 assert_eq!(dur_from_nanos.into_nanos(), nanos_in_one_hour);
645 assert_eq!(dur_from_nanos.into_hours(), 1);
646 }
647
648 #[test]
649 fn monotonic_timer_basic() {
650 let slack = Duration::from_millis(0);
651 let ten_ms = Duration::from_millis(10);
652 let five_secs = Duration::from_seconds(5);
653
654 let timer = MonotonicTimer::create();
656
657 let info = timer.info().expect("info() failed");
658 assert_eq!(info.clock_id, sys::ZX_CLOCK_MONOTONIC);
659 assert_eq!(info.deadline, Instant::ZERO);
660 assert_eq!(
664 timer.wait_one(Signals::TIMER_SIGNALED, MonotonicInstant::after(ten_ms)),
665 WaitResult::TimedOut(Signals::empty()),
666 );
667
668 let instant = MonotonicInstant::after(five_secs);
670 assert_eq!(timer.set(instant, slack), Ok(()));
671 assert_eq!(
672 timer.wait_one(Signals::TIMER_SIGNALED, Instant::INFINITE),
673 WaitResult::Ok(Signals::TIMER_SIGNALED)
674 );
675 assert_eq!(timer.info().expect("info() failed").deadline, Instant::ZERO);
677
678 assert_eq!(timer.cancel(), Ok(()));
680 assert_eq!(
681 timer.wait_one(Signals::TIMER_SIGNALED, MonotonicInstant::after(ten_ms)),
682 WaitResult::TimedOut(Signals::empty()),
683 );
684 assert_eq!(timer.info().expect("info() failed").deadline, Instant::ZERO);
685
686 assert_eq!(timer.set(Instant::INFINITE, slack), Ok(()));
687 assert_eq!(timer.info().expect("info() failed").deadline, Instant::INFINITE);
688 }
689
690 #[test]
691 fn boot_timer_basic() {
692 let slack = Duration::from_millis(0);
693 let ten_ms = Duration::from_millis(10);
694 let five_secs = Duration::from_seconds(5);
695
696 let timer = BootTimer::create();
698
699 let info = timer.info().expect("info() failed");
700 assert_eq!(info.clock_id, sys::ZX_CLOCK_BOOT);
701 assert_eq!(info.deadline, Instant::ZERO);
702 assert_eq!(
706 timer.wait_one(Signals::TIMER_SIGNALED, MonotonicInstant::after(ten_ms)),
707 WaitResult::TimedOut(Signals::empty())
708 );
709
710 let instant = BootInstant::after(five_secs);
712 assert_eq!(timer.set(instant, slack), Ok(()));
713 assert_eq!(
714 timer.wait_one(Signals::TIMER_SIGNALED, Instant::INFINITE),
715 WaitResult::Ok(Signals::TIMER_SIGNALED)
716 );
717 assert_eq!(timer.info().expect("info() failed").deadline, Instant::ZERO);
719
720 assert_eq!(timer.cancel(), Ok(()));
722 assert_eq!(
723 timer.wait_one(Signals::TIMER_SIGNALED, MonotonicInstant::after(ten_ms)),
724 WaitResult::TimedOut(Signals::empty())
725 );
726 assert_eq!(timer.info().expect("info() failed").deadline, Instant::ZERO);
727
728 assert_eq!(timer.set(Instant::INFINITE, slack), Ok(()));
729 assert_eq!(timer.info().expect("info() failed").deadline, Instant::INFINITE);
730 }
731
732 #[test]
733 fn time_minus_time() {
734 let lhs = MonotonicInstant::from_nanos(10);
735 let rhs = MonotonicInstant::from_nanos(30);
736 assert_eq!(lhs - rhs, Duration::from_nanos(-20));
737 }
738
739 #[test]
740 fn time_saturation() {
741 assert_eq!(
743 MonotonicInstant::from_nanos(10) + Duration::from_nanos(30),
744 MonotonicInstant::from_nanos(40)
745 );
746 assert_eq!(
747 MonotonicInstant::from_nanos(10) + Duration::INFINITE,
748 MonotonicInstant::INFINITE
749 );
750 assert_eq!(
751 MonotonicInstant::from_nanos(-10) + Duration::INFINITE_PAST,
752 MonotonicInstant::INFINITE_PAST
753 );
754
755 assert_eq!(
757 MonotonicInstant::from_nanos(10) - Duration::from_nanos(30),
758 MonotonicInstant::from_nanos(-20)
759 );
760 assert_eq!(
761 MonotonicInstant::from_nanos(-10) - Duration::INFINITE,
762 MonotonicInstant::INFINITE_PAST
763 );
764 assert_eq!(
765 MonotonicInstant::from_nanos(10) - Duration::INFINITE_PAST,
766 MonotonicInstant::INFINITE
767 );
768
769 {
771 let mut t = MonotonicInstant::from_nanos(10);
772 t += Duration::from_nanos(30);
773 assert_eq!(t, MonotonicInstant::from_nanos(40));
774 }
775 {
776 let mut t = MonotonicInstant::from_nanos(10);
777 t += Duration::INFINITE;
778 assert_eq!(t, MonotonicInstant::INFINITE);
779 }
780 {
781 let mut t = MonotonicInstant::from_nanos(-10);
782 t += Duration::INFINITE_PAST;
783 assert_eq!(t, MonotonicInstant::INFINITE_PAST);
784 }
785
786 {
788 let mut t = MonotonicInstant::from_nanos(10);
789 t -= Duration::from_nanos(30);
790 assert_eq!(t, MonotonicInstant::from_nanos(-20));
791 }
792 {
793 let mut t = MonotonicInstant::from_nanos(-10);
794 t -= Duration::INFINITE;
795 assert_eq!(t, MonotonicInstant::INFINITE_PAST);
796 }
797 {
798 let mut t = MonotonicInstant::from_nanos(10);
799 t -= Duration::INFINITE_PAST;
800 assert_eq!(t, MonotonicInstant::INFINITE);
801 }
802 }
803
804 #[test]
805 fn duration_saturation() {
806 assert_eq!(
808 MonotonicDuration::from_nanos(10) + Duration::from_nanos(30),
809 Duration::from_nanos(40)
810 );
811 assert_eq!(MonotonicDuration::from_nanos(10) + Duration::INFINITE, Duration::INFINITE);
812 assert_eq!(
813 MonotonicDuration::from_nanos(-10) + Duration::INFINITE_PAST,
814 Duration::INFINITE_PAST
815 );
816
817 assert_eq!(
819 MonotonicDuration::from_nanos(10) - Duration::from_nanos(30),
820 Duration::from_nanos(-20)
821 );
822 assert_eq!(
823 MonotonicDuration::from_nanos(-10) - Duration::INFINITE,
824 Duration::INFINITE_PAST
825 );
826 assert_eq!(MonotonicDuration::from_nanos(10) - Duration::INFINITE_PAST, Duration::INFINITE);
827
828 assert_eq!(MonotonicDuration::from_nanos(10) * 3, Duration::from_nanos(30));
830 assert_eq!(MonotonicDuration::from_nanos(10) * i64::MAX, Duration::INFINITE);
831 assert_eq!(MonotonicDuration::from_nanos(10) * i64::MIN, Duration::INFINITE_PAST);
832
833 assert_eq!(MonotonicDuration::from_nanos(30) / 3, Duration::from_nanos(10));
835 assert_eq!(MonotonicDuration::INFINITE_PAST / -1, Duration::INFINITE);
836
837 assert_eq!(-MonotonicDuration::from_nanos(30), Duration::from_nanos(-30));
839 assert_eq!(-MonotonicDuration::INFINITE_PAST, Duration::INFINITE);
840
841 {
843 let mut t = MonotonicDuration::from_nanos(10);
844 t += Duration::from_nanos(30);
845 assert_eq!(t, Duration::from_nanos(40));
846 }
847 {
848 let mut t = MonotonicDuration::from_nanos(10);
849 t += Duration::INFINITE;
850 assert_eq!(t, Duration::INFINITE);
851 }
852 {
853 let mut t = MonotonicDuration::from_nanos(-10);
854 t += Duration::INFINITE_PAST;
855 assert_eq!(t, Duration::INFINITE_PAST);
856 }
857
858 {
860 let mut t = MonotonicDuration::from_nanos(10);
861 t -= Duration::from_nanos(30);
862 assert_eq!(t, Duration::from_nanos(-20));
863 }
864 {
865 let mut t = MonotonicDuration::from_nanos(-10);
866 t -= Duration::INFINITE;
867 assert_eq!(t, Duration::INFINITE_PAST);
868 }
869 {
870 let mut t = MonotonicDuration::from_nanos(10);
871 t -= Duration::INFINITE_PAST;
872 assert_eq!(t, Duration::INFINITE);
873 }
874 }
875
876 #[test]
877 fn time_minus_time_saturates() {
878 assert_eq!(
879 MonotonicInstant::INFINITE - MonotonicInstant::INFINITE_PAST,
880 Duration::INFINITE
881 );
882 }
883
884 #[test]
885 fn time_and_duration_defaults() {
886 assert_eq!(MonotonicInstant::default(), MonotonicInstant::from_nanos(0));
887 assert_eq!(Duration::default(), MonotonicDuration::from_nanos(0));
888 }
889}