1use std::{borrow::Cow, cmp::Ordering, fmt, io::{self}, ops, os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd}, sync::Arc, time::Duration};
19
20use chrono::{DateTime, TimeZone};
21use nix::libc::{self, ECANCELED, EWOULDBLOCK};
22use bitflags::bitflags;
23
24
25use crate::{common, timer_portable::portable_error::TimerPortResult};
26
27#[cfg(target_os = "linux")]
28pub use super::linux::timer_fd_linux::TimerFdInternal;
29
30#[cfg(
31 all(
32 any(
33 target_os = "freebsd",
34 target_os = "dragonfly",
35 target_os = "netbsd",
36 target_os = "openbsd",
37 target_os = "macos",
38 ),
39 feature = "bsd_use_timerfd"
40 )
41)]
42pub use super::bsd::timer_fd_bsd::TimerFdInternal;
43
44#[cfg(
45 all(
46 any(
47 target_os = "freebsd",
48 target_os = "dragonfly",
49 target_os = "netbsd",
50 target_os = "openbsd",
51 target_os = "macos",
52 ),
53 not(feature = "bsd_use_timerfd")
54 )
55)]
56pub use super::bsd::timer_kqueue_fd_bsd::TimerFdInternal;
57
58
59#[allow(non_camel_case_types)]
61#[repr(i32)]
62#[derive(Debug)]
63pub enum TimerType
64{
65 CLOCK_REALTIME = libc::CLOCK_REALTIME,
67
68 CLOCK_MONOTONIC = libc::CLOCK_MONOTONIC,
73
74
75 #[cfg(target_os = "linux")]
83 CLOCK_BOOTTIME = libc::CLOCK_BOOTTIME,
84
85 #[cfg(target_os = "linux")]
89 CLOCK_REALTIME_ALARM = libc::CLOCK_REALTIME_ALARM,
90
91 #[cfg(target_os = "linux")]
95 CLOCK_BOOTTIME_ALARM = libc::CLOCK_BOOTTIME_ALARM,
96}
97
98impl From<TimerType> for libc::clockid_t
126{
127 fn from(value: TimerType) -> Self
128 {
129 return value as libc::clockid_t;
130 }
131}
132
133
134bitflags! {
135 #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
137 pub struct TimerFlags: i32
138 {
139 const TFD_NONBLOCK = libc::TFD_NONBLOCK;
144
145 const TFD_CLOEXEC = libc::TFD_CLOEXEC;
149 }
150}
151
152
153bitflags! {
154 #[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
156 pub struct TimerSetTimeFlags: i32
157 {
158 const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
162
163 const TFD_TIMER_CANCEL_ON_SET = libc::TFD_TIMER_CANCEL_ON_SET;
171 }
172}
173
174
175pub trait ModeTimeType: Eq + PartialEq + Ord + PartialOrd + fmt::Display + fmt::Debug + Clone + Copy
183{
184
185 fn new(time_spec: timespec) -> Self where Self: Sized;
196
197 fn get_sec(&self) -> i64;
199
200 fn get_nsec(&self) -> i64;
202
203 fn is_value_valid(&self) -> bool;
205
206 fn get_flags() -> TimerSetTimeFlags;
209}
210
211#[derive(Debug, PartialEq, Eq, Clone, Copy)]
213pub struct RelativeTime
214{
215 time_sec: i64,
217
218 time_nsec: i64,
220}
221
222impl From<Duration> for RelativeTime
225{
226 fn from(value: Duration) -> Self
227 {
228 return Self
229 {
230 time_sec:
231 value.as_secs() as i64,
232 time_nsec:
233 value.subsec_nanos() as i64,
234 };
235 }
236}
237
238impl From<RelativeTime> for Duration
239{
240 fn from(value: RelativeTime) -> Self
241 {
242 return Duration::new(value.time_sec as u64, value.time_nsec as u32);
243 }
244}
245
246impl Ord for RelativeTime
247{
248 fn cmp(&self, other: &Self) -> Ordering
249 {
250 return
251 self
252 .time_sec
253 .cmp(&other.time_sec)
254 .then(
255 self
256 .time_nsec
257 .cmp(&other.time_nsec)
258 );
259 }
260}
261
262impl PartialOrd for RelativeTime
263{
264 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
265 {
266 return Some(self.cmp(other));
267 }
268}
269
270impl fmt::Display for RelativeTime
271{
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
273 {
274 write!(f, "[relative] sec: {}, nsec: {}", self.time_sec, self.time_nsec)
275 }
276}
277
278impl ModeTimeType for RelativeTime
279{
280 fn new(time_spec: timespec) -> RelativeTime
281 {
282 return
283 Self::new_time(time_spec.tv_sec, time_spec.tv_nsec);
284 }
285
286 fn get_sec(&self) -> i64
287 {
288 return self.time_sec;
289 }
290
291 fn get_nsec(&self) -> i64 {
292
293 return self.time_nsec;
294 }
295
296 fn is_value_valid(&self) -> bool
297 {
298 return true;
299 }
300
301 fn get_flags() -> TimerSetTimeFlags
302 {
303 return TimerSetTimeFlags::empty();
304 }
305}
306
307impl RelativeTime
308{
309 pub const MAX_NS: i64 = 1_000_000_000;
311
312 pub
326 fn new_time(time_sec: i64, time_nsec: i64) -> Self
327 {
328 let extra_sec = time_nsec / Self::MAX_NS;
329 let nsec_new = time_nsec % Self::MAX_NS;
330
331 return
332 Self
333 {
334 time_nsec: nsec_new,
335 time_sec: time_sec + extra_sec,
336 };
337 }
338
339 pub
340 fn is_zero(&self) -> bool
341 {
342 return self.time_nsec == 0 && self.time_sec == 0;
343 }
344}
345
346#[derive(Debug, PartialEq, Eq, Clone, Copy)]
349pub struct AbsoluteTime
350{
351 time_sec: i64,
353
354 time_nsec: i64,
356}
357
358impl<TZ: TimeZone> From<DateTime<TZ>> for AbsoluteTime
362{
363 fn from(value: DateTime<TZ>) -> Self
364 {
365 return Self
366 {
367 time_sec:
368 value.timestamp(),
369 time_nsec:
370 value.timestamp_subsec_nanos() as i64,
371 };
372 }
373}
374
375impl From<Duration> for AbsoluteTime
378{
379 fn from(value: Duration) -> Self
380 {
381 return Self
382 {
383 time_sec:
384 value.as_secs() as i64,
385 time_nsec:
386 value.subsec_nanos() as i64,
387 };
388 }
389}
390
391impl From<AbsoluteTime> for Duration
392{
393 fn from(value: AbsoluteTime) -> Self
394 {
395 return Duration::new(value.time_sec as u64, value.time_nsec as u32);
396 }
397}
398
399impl Ord for AbsoluteTime
400{
401 fn cmp(&self, other: &Self) -> Ordering
402 {
403 return
404 self
405 .time_sec
406 .cmp(&other.time_sec)
407 .then(
408 self
409 .time_nsec
410 .cmp(&other.time_nsec)
411 );
412 }
413}
414
415impl PartialOrd for AbsoluteTime
416{
417 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
418 {
419 return Some(self.cmp(other));
420 }
421}
422
423impl ops::AddAssign<Duration> for AbsoluteTime
424{
425 fn add_assign(&mut self, rhs: Duration)
426 {
427 self.time_nsec += rhs.subsec_nanos() as i64;
428 let add_sec = self.time_nsec / Self::MAX_NS;
429
430 if add_sec > 0
431 {
432 self.time_nsec %= Self::MAX_NS;
433 }
434
435 self.time_sec += rhs.as_secs() as i64 + add_sec;
436 }
437}
438
439impl ops::AddAssign<RelativeTime> for AbsoluteTime
440{
441 fn add_assign(&mut self, rhs: RelativeTime)
442 {
443 self.time_nsec += rhs.time_nsec;
444 let add_sec = self.time_nsec / Self::MAX_NS;
445
446 if add_sec > 0
447 {
448 self.time_nsec %= Self::MAX_NS;
449 }
450
451 self.time_sec += rhs.time_sec + add_sec;
452 }
453}
454
455impl ops::Add<Duration> for AbsoluteTime
456{
457 type Output = AbsoluteTime;
458
459 fn add(mut self, rhs: Duration) -> Self::Output
460 {
461 self += rhs;
462
463 return self;
464 }
465}
466
467impl ops::Add<RelativeTime> for AbsoluteTime
468{
469 type Output = AbsoluteTime;
470
471 fn add(mut self, rhs: RelativeTime) -> Self::Output
472 {
473 self += rhs;
474
475 return self;
476 }
477}
478
479impl ops::SubAssign<Duration> for AbsoluteTime
480{
481 fn sub_assign(&mut self, rhs: Duration)
482 {
483 let mut sec = rhs.as_secs() as i64;
484 let mut nsec = self.time_nsec - rhs.subsec_nanos() as i64;
485
486 if nsec < 0
487 {
488 sec += 1;
489
490 nsec = Self::MAX_NS + nsec;
491 }
492
493 self.time_nsec = nsec;
494 self.time_sec -= sec;
495
496 return;
497 }
498}
499
500impl ops::SubAssign<RelativeTime> for AbsoluteTime
501{
502 fn sub_assign(&mut self, mut rhs: RelativeTime)
503 {
504
505 let mut nsec = self.time_nsec - rhs.time_nsec;
506
507 if nsec < 0
508 {
509 rhs.time_sec += 1;
510
511 nsec = Self::MAX_NS + nsec;
512 }
513
514 self.time_nsec = nsec;
515 self.time_sec -= rhs.time_sec;
516
517 return;
518 }
519}
520
521impl ops::Sub<Duration> for AbsoluteTime
522{
523 type Output = AbsoluteTime;
524
525 fn sub(mut self, rhs: Duration) -> Self::Output
526 {
527 self -= rhs;
528
529 return self;
530 }
531}
532
533impl ops::Sub<RelativeTime> for AbsoluteTime
534{
535 type Output = AbsoluteTime;
536
537 fn sub(mut self, rhs: RelativeTime) -> Self::Output
538 {
539 self -= rhs;
540
541 return self;
542 }
543}
544
545impl ops::SubAssign for AbsoluteTime
546{
547 fn sub_assign(&mut self, mut rhs: Self)
548 {
549
550 let mut nsec = self.time_nsec - rhs.time_nsec;
551
552 if nsec < 0
553 {
554 rhs.time_sec += 1;
555
556 nsec = Self::MAX_NS + nsec;
557 }
558
559 self.time_nsec = nsec;
560 self.time_sec -= rhs.time_sec;
561
562 return;
563 }
564}
565
566impl ops::Sub for AbsoluteTime
567{
568 type Output = AbsoluteTime;
569
570 fn sub(mut self, rhs: Self) -> Self::Output
571 {
572 self -= rhs;
573
574 return self;
575 }
576}
577
578
579impl fmt::Display for AbsoluteTime
580{
581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
582 {
583 write!(f, "[absolute] {}.{:09}sec", self.time_sec, self.time_nsec)
584 }
585}
586
587
588impl ModeTimeType for AbsoluteTime
589{
590 fn new(time_spec: timespec) -> Self where Self: Sized
591 {
592 return
593 unsafe { Self::new_time_unchecked(time_spec.tv_sec, time_spec.tv_nsec) };
594 }
595
596 fn get_sec(&self) -> i64
597 {
598 return self.time_sec;
599 }
600
601 fn get_nsec(&self) -> i64
602 {
603
604 return self.time_nsec;
605 }
606
607 fn is_value_valid(&self) -> bool
608 {
609 return self.time_nsec != 0 || self.time_sec != 0;
610 }
611
612 fn get_flags() -> TimerSetTimeFlags
613 {
614 return TimerSetTimeFlags::TFD_TIMER_ABSTIME | TimerSetTimeFlags::TFD_TIMER_CANCEL_ON_SET;
615 }
616}
617
618impl AbsoluteTime
619{
620 pub const MAX_NS: i64 = 1_000_000_000;}
623
624impl AbsoluteTime
625{
626 pub
628 fn now() -> Self
629 {
630 let value = common::get_current_timestamp();
631
632 return Self
633 {
634 time_sec: value.timestamp(),
635 time_nsec: value.timestamp_subsec_nanos() as i64,
636 }
637 }
638
639 pub
640 fn new_time(time_sec: i64, time_nsec: i64) -> Option<Self>
641 {
642 let tm =
643 unsafe { Self::new_time_unchecked(time_sec, time_nsec) };
644
645 if tm.is_value_valid() == false
646 {
647 return None;
648 }
649
650 return Some(tm);
651 }
652
653 pub unsafe
671 fn new_time_unchecked(time_sec: i64, time_nsec: i64) -> Self
672 {
673 let extra_sec = time_nsec / Self::MAX_NS;
674 let nsec_new = time_nsec % Self::MAX_NS;
675
676 return
677 Self
678 {
679 time_nsec: nsec_new,
680 time_sec: time_sec + extra_sec,
681 };
682 }
683
684 pub
686 fn seconds_cmp(&self, other: &Self) -> Ordering
687 {
688 return self.time_sec.cmp(&other.time_sec);
689 }
690
691 pub
692 fn add_sec(mut self, seconds: i64) -> Self
693 {
694 self.time_sec += seconds;
695
696 return self;
697 }
698
699 pub
700 fn reset_nsec(mut self) -> Self
701 {
702 self.time_nsec = 0;
703
704 return self;
705 }
706}
707
708
709
710#[derive(Clone, Copy, Debug, PartialEq, Eq)]
715pub enum TimerExpMode<TIMERTYPE: ModeTimeType>
716{
717 None,
719
720 OneShot
722 {
723 timeout: TIMERTYPE
724 },
725
726 IntervalDelayed
728 {
729 delay_tm: TIMERTYPE,
731
732 interv_tm: TIMERTYPE
734 },
735
736 Interval
739 {
740 interv_tm: TIMERTYPE
742 },
743}
744
745
746impl ops::AddAssign<RelativeTime> for TimerExpMode<AbsoluteTime>
747{
748 fn add_assign(&mut self, rhs: RelativeTime)
749 {
750 match self
751 {
752 TimerExpMode::None =>
753 return,
754 TimerExpMode::OneShot { timeout } =>
755 {
756 *timeout += rhs;
757
758 },
759 TimerExpMode::IntervalDelayed { interv_tm, .. } =>
760 {
761 *interv_tm += rhs;
762 },
763 TimerExpMode::Interval { interv_tm } =>
764 {
765 *interv_tm += rhs;
766 },
767 }
768 }
769}
770
771
772impl ops::Add<RelativeTime> for TimerExpMode<AbsoluteTime>
773{
774 type Output = TimerExpMode<AbsoluteTime>;
775
776 fn add(mut self, rhs: RelativeTime) -> Self::Output
777 {
778 self += rhs;
779
780 return self;
781 }
782}
783
784
785impl<TIMERTYPE: ModeTimeType> Ord for TimerExpMode<TIMERTYPE>
786{
787 fn cmp(&self, other: &Self) -> Ordering
788 {
789 match (self, other)
790 {
791 (TimerExpMode::None, TimerExpMode::None) =>
792 return Ordering::Equal,
793 (TimerExpMode::OneShot{ timeout }, TimerExpMode::OneShot { timeout: timeout2 }) =>
794 {
795 return timeout.cmp(timeout2);
796 },
797 (
798 TimerExpMode::IntervalDelayed{ delay_tm, interv_tm },
799 TimerExpMode::IntervalDelayed{ delay_tm: delay_tm2, interv_tm: interv_tm2 }
800 ) =>
801 {
802 return
803 delay_tm.cmp(delay_tm2)
804 .then(interv_tm.cmp(interv_tm2));
805 },
806 (TimerExpMode::Interval { interv_tm }, TimerExpMode::Interval { interv_tm: interv_tm2 }) =>
807 {
808 return interv_tm.cmp(interv_tm2);
809 },
810 _ =>
811 panic!("cannot compare different types {} and {}", self, other)
812 }
813 }
814}
815
816impl<TIMERTYPE: ModeTimeType> PartialOrd for TimerExpMode<TIMERTYPE>
817{
818 fn partial_cmp(&self, other: &Self) -> Option<Ordering>
819 {
820 return Some(self.cmp(other));
821 }
822}
823
824
825
826impl TimerExpMode<AbsoluteTime>
828{
829 #[inline]
832 fn is_valid_inner(&self) -> bool
833 {
834 match self
835 {
836 Self::None =>
837 return false,
838 Self::OneShot{ timeout} =>
839 return timeout.is_value_valid(),
840 Self::IntervalDelayed{ delay_tm, interv_tm } =>
841 return delay_tm.is_value_valid() && interv_tm.is_value_valid(),
842 Self::Interval{ interv_tm } =>
843 return interv_tm.is_value_valid()
844 }
845 }
846
847 pub
851 fn new_oneshot(abs_time: AbsoluteTime) -> Self
852 {
853 return Self::OneShot { timeout: abs_time };
854 }
855}
856
857
858
859impl TimerExpMode<RelativeTime>
861{
862 pub
865 fn new_oneshot(rel_time: RelativeTime) -> Self
866 {
867 return Self::OneShot { timeout: rel_time };
868 }
869
870 pub
873 fn new_interval(rel_time: RelativeTime) -> Self
874 {
875 return Self::Interval { interv_tm: rel_time };
876 }
877
878 pub
883 fn new_interval_with_init_delay(delay_time: RelativeTime, intev_time: RelativeTime) -> Self
884 {
885 return Self::IntervalDelayed { delay_tm: delay_time, interv_tm: intev_time };
886 }
887}
888
889impl<TIMERTYPE: ModeTimeType> TimerExpMode<TIMERTYPE>
890{
891 #[inline]
893 pub
894 fn reset() -> Self
895 {
896 return Self::None;
897 }
898}
899
900impl<TIMERTYPE: ModeTimeType> fmt::Display for TimerExpMode<TIMERTYPE>
901{
902 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
903 {
904 match self
905 {
906 Self::None =>
907 write!(f, "disarmed"),
908 Self::OneShot{ timeout } =>
909 write!(f, "oneshot {}", timeout),
910 Self::IntervalDelayed
911 { delay_tm, interv_tm } =>
912 write!(f, "interval {} with delay {}", interv_tm, delay_tm),
913 Self::Interval{ interv_tm } =>
914 write!(f, "interval {}", interv_tm),
915 }
916 }
917}
918
919
920
921#[derive(Debug, Clone, PartialEq, Eq)]
940pub enum TimerReadRes<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq>
941{
942 Ok(T),
944
945 Cancelled,
952
953 WouldBlock,
956}
957
958impl TimerReadRes<u64>
959{
960 pub
961 fn ok() -> Self
962 {
963 return Self::Ok(1);
964 }
965}
966
967impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> From<io::Error> for TimerReadRes<T>
968{
969 fn from(value: io::Error) -> Self
970 {
971 if let Some(errn) = value.raw_os_error()
972 {
973 if errn == ECANCELED
974 {
975 return Self::Cancelled;
976 }
977 else if errn == EWOULDBLOCK
978 {
979 return Self::WouldBlock;
980 }
981 }
982
983 return Self::Cancelled;
984 }
985}
986
987impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> fmt::Display for TimerReadRes<T>
988{
989 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
990 {
991 match self
992 {
993 Self::Ok(ovfl) =>
994 write!(f, "OK(overflows:{})", ovfl),
995 Self::Cancelled =>
996 write!(f, "CANCELLED"),
997 Self::WouldBlock =>
998 write!(f, "WOULDBLOCK"),
999 }
1000 }
1001}
1002
1003impl<T: Sized + fmt::Debug + fmt::Display + Clone + Eq + PartialEq> TimerReadRes<T>
1004{
1005 pub
1006 fn unwrap(self) -> T
1007 {
1008 let Self::Ok(t) = self
1009 else { panic!("can not unwrap {:?}", self)};
1010
1011 return t;
1012 }
1013}
1014
1015pub trait FdTimerRead: AsFd + AsRawFd + fmt::Display + AsRef<str> + PartialEq<str> + PartialEq<RawFd>
1016{
1017 fn read(&self) -> TimerPortResult<TimerReadRes<u64>>;
1038}
1039
1040pub trait FdTimerMarker: FdTimerRead + Eq + PartialEq + PartialEq<RawFd>
1041{
1042 fn clone_timer(&self) -> TimerFd;
1043
1044 fn get_strong_count(&self) -> usize;
1045}
1046
1047
1048pub trait FdTimerCom: FdTimerRead
1050{
1051 fn new(label: Cow<'static, str>, timer_type: TimerType, timer_flags: TimerFlags) -> TimerPortResult<Self>
1065 where Self: Sized;
1066
1067 fn set_time<TIMERTYPE: ModeTimeType>(&self, timer_exp: TimerExpMode<TIMERTYPE>) -> TimerPortResult<()>;
1073
1074 fn unset_time(&self) -> TimerPortResult<()>;
1076
1077 fn set_nonblocking(&self, flag: bool) -> TimerPortResult<()>;
1081
1082 fn is_nonblocking(&self) -> TimerPortResult<bool>;
1091}
1092
1093#[derive(Debug)]
1094pub struct TimerFd(Arc<TimerFdInternal>);
1095
1096impl fmt::Display for TimerFd
1097{
1098 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
1099 {
1100 write!(f, "{}", self.0)
1101 }
1102}
1103
1104impl AsFd for TimerFd
1105{
1106 fn as_fd(&self) -> BorrowedFd<'_>
1107 {
1108 return self.0.as_fd();
1109 }
1110}
1111
1112impl AsRawFd for TimerFd
1113{
1114 fn as_raw_fd(&self) -> RawFd
1115 {
1116 return self.0.as_raw_fd();
1117 }
1118}
1119impl AsRef<str> for TimerFd
1120{
1121 fn as_ref(&self) -> &str
1122 {
1123 return self.0.as_ref().as_ref();
1124 }
1125}
1126
1127impl Eq for TimerFd {}
1128
1129impl PartialEq for TimerFd
1130{
1131 fn eq(&self, other: &Self) -> bool
1132 {
1133 return self.0 == other.0
1134 }
1135}
1136
1137impl PartialEq<RawFd> for TimerFd
1138{
1139 fn eq(&self, other: &RawFd) -> bool
1140 {
1141 return self.0.as_raw_fd() == *other;
1142 }
1143}
1144
1145impl PartialEq<str> for TimerFd
1146{
1147 fn eq(&self, other: &str) -> bool
1148 {
1149 return self.0.as_ref() == other;
1150 }
1151}
1152
1153impl FdTimerMarker for TimerFd
1154{
1155 fn clone_timer(&self) -> TimerFd
1156 {
1157 return Self(self.0.clone());
1158 }
1159
1160 fn get_strong_count(&self) -> usize
1161 {
1162 return Arc::strong_count(&self.0);
1163 }
1164}
1165
1166impl TimerFd
1167{
1168 pub
1169 fn new(label: Cow<'static, str>, timer_type: TimerType, timer_flags: TimerFlags) -> TimerPortResult<Self>
1170 {
1171 return Ok(
1172 Self( Arc::new(TimerFdInternal::new(label, timer_type, timer_flags)?) )
1173 );
1174 }
1175
1176 pub
1177 fn get_timer(&self) -> &TimerFdInternal
1178 {
1179 return &self.0;
1180 }
1181}
1182
1183impl FdTimerRead for TimerFd
1184{
1185 fn read(&self) -> TimerPortResult<TimerReadRes<u64>>
1186 {
1187 return self.0.read();
1188 }
1189}
1190
1191pub use nix::libc::{itimerspec, timespec};
1192
1193impl<TIMERTYPE: ModeTimeType> From<itimerspec> for TimerExpMode<TIMERTYPE>
1195{
1196 fn from(value: itimerspec) -> Self
1197 {
1198 if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0 &&
1199 value.it_value.tv_sec == 0 && value.it_value.tv_nsec == 0
1200 {
1201 return Self::None;
1203 }
1204 else if value.it_interval.tv_sec == 0 && value.it_interval.tv_nsec == 0
1205 {
1206 return
1208 Self::OneShot
1209 {
1210 timeout: TIMERTYPE::new(value.it_value)
1211 };
1212 }
1213 else if value.it_interval.tv_sec == value.it_value.tv_sec &&
1214 value.it_interval.tv_nsec == value.it_value.tv_nsec
1215 {
1216 return
1218 Self::Interval
1219 {
1220 interv_tm: TIMERTYPE::new(value.it_interval)
1221 };
1222 }
1223 else
1224 {
1225 return
1227 Self::IntervalDelayed
1228 {
1229 delay_tm: TIMERTYPE::new(value.it_value),
1230 interv_tm: TIMERTYPE::new(value.it_interval)
1231 };
1232 }
1233 }
1234}
1235
1236
1237impl<TIMERTYPE: ModeTimeType> From<TimerExpMode<TIMERTYPE>> for itimerspec
1238{
1239 fn from(value: TimerExpMode<TIMERTYPE>) -> Self
1240 {
1241 return (&value).into();
1242 }
1243}
1244
1245impl<TIMERTYPE: ModeTimeType> From<&TimerExpMode<TIMERTYPE>> for itimerspec
1248{
1249 fn from(value: &TimerExpMode<TIMERTYPE>) -> Self
1250 {
1251 match value
1252 {
1253 TimerExpMode::None =>
1254 return
1255 itimerspec
1256 {
1257 it_interval: timespec
1258 {
1259 tv_sec: 0,
1260 tv_nsec: 0,
1261 },
1262 it_value: timespec
1263 {
1264 tv_sec: 0,
1265 tv_nsec: 0,
1266 },
1267 },
1268 TimerExpMode::OneShot{ timeout} =>
1269 return
1270 itimerspec
1271 {
1272 it_interval: timespec
1273 {
1274 tv_sec: 0,
1275 tv_nsec: 0,
1276 },
1277 it_value: timespec
1278 {
1279 tv_sec: timeout.get_sec(),
1280 tv_nsec: timeout.get_nsec(),
1281 },
1282 },
1283 TimerExpMode::IntervalDelayed{ delay_tm, interv_tm } =>
1284 return
1285 itimerspec
1286 {
1287 it_interval: timespec
1288 {
1289 tv_sec: interv_tm.get_sec(),
1290 tv_nsec: interv_tm.get_nsec(),
1291 },
1292 it_value: timespec
1293 {
1294 tv_sec: delay_tm.get_sec(),
1295 tv_nsec: delay_tm.get_nsec(),
1296 },
1297 },
1298 TimerExpMode::Interval{ interv_tm } =>
1299 return
1300 itimerspec
1301 {
1302 it_interval: timespec
1303 {
1304 tv_sec: interv_tm.get_sec(),
1305 tv_nsec: interv_tm.get_nsec(),
1306 },
1307 it_value: timespec
1308 {
1309 tv_sec: interv_tm.get_sec(),
1310 tv_nsec: interv_tm.get_nsec(),
1311 },
1312 }
1313 }
1314 }
1315}
1316
1317
1318#[cfg(test)]
1319mod tests
1320{
1321
1322 use crate::{common, timer_portable::timer::{AbsoluteTime, ModeTimeType, RelativeTime, TimerExpMode}};
1323
1324 #[test]
1325 fn test_0()
1326 {
1327 let ts = common::get_current_timestamp();
1328
1329 let texp1 = TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1330
1331 assert_eq!(
1332 TimerExpMode::OneShot { timeout: AbsoluteTime::from(ts) },
1333 texp1
1334 );
1335
1336 }
1337
1338 #[test]
1339 fn test_1()
1340 {
1341 let ts = common::get_current_timestamp();
1342
1343 let texp1 =
1344 TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1345
1346 let texp2 =
1347 texp1 + RelativeTime::new_time(1, 0);
1348
1349 assert_eq!(texp1 < texp2, true);
1350 assert_eq!(texp2 > texp1, true);
1351 assert_eq!(texp2 != texp1, true);
1352 assert_eq!(texp2 < texp1, false);
1353 }
1354
1355 #[test]
1356 fn test_2()
1357 {
1358
1359 let texp1 =
1360 TimerExpMode::<AbsoluteTime>::new_oneshot(
1361 unsafe {AbsoluteTime::new_time_unchecked(100, AbsoluteTime::MAX_NS)}
1362 );
1363
1364 let texp2 =
1365 texp1 + RelativeTime::new_time(0, 1);
1366
1367
1368 assert_eq!(texp1 < texp2, true);
1369 assert_eq!(texp2 > texp1, true);
1370 assert_eq!(texp2 != texp1, true);
1371 assert_eq!(texp2 < texp1, false);
1372 }
1373
1374 #[should_panic]
1375 #[test]
1376 fn test_2_fail()
1377 {
1378 let ts = common::get_current_timestamp();
1379
1380 let texp1 =
1381 TimerExpMode::<AbsoluteTime>::new_oneshot(AbsoluteTime::from(ts));
1382
1383 let texp2 =
1384 TimerExpMode::<AbsoluteTime>::Interval { interv_tm: AbsoluteTime::from(ts)};
1385
1386 assert_eq!(texp1 == texp2, true);
1387 }
1388
1389 #[test]
1390 fn test_abstime_cmp()
1391 {
1392 let abs_time = AbsoluteTime::now();
1393 let abs_time_future = abs_time + RelativeTime::new_time(10, 1);
1394 let abs_time_past = abs_time - RelativeTime::new_time(10, 1);
1395
1396 assert_eq!(abs_time < abs_time_future, true);
1397 assert_eq!(abs_time_future > abs_time, true);
1398 assert_eq!(abs_time > abs_time_past, true);
1399 assert_eq!(abs_time_past < abs_time, true);
1400 assert_eq!(abs_time_future > abs_time_past, true);
1401 assert_eq!(abs_time_past < abs_time_future, true);
1402 }
1403
1404 #[test]
1405 fn test_abstime_new()
1406 {
1407 let abs = AbsoluteTime::new_time(1, 999_999_999).unwrap();
1408 assert_eq!(abs.time_nsec, 999_999_999);
1409 assert_eq!(abs.time_sec, 1);
1410
1411 let abs = AbsoluteTime::new_time(1, 1_000_000_000).unwrap();
1412 assert_eq!(abs.time_nsec, 0);
1413 assert_eq!(abs.time_sec, 2);
1414
1415 let abs = AbsoluteTime::new_time(1, 1_000_000_001).unwrap();
1416 assert_eq!(abs.time_nsec, 1);
1417 assert_eq!(abs.time_sec, 2);
1418
1419 let abs = AbsoluteTime::new_time(1, 2_000_000_001).unwrap();
1420 assert_eq!(abs.time_nsec, 1);
1421 assert_eq!(abs.time_sec, 3);
1422 }
1423
1424 #[test]
1425 fn test_abstime_add()
1426 {
1427 let mut abs = AbsoluteTime::new_time(1, 999_999_999).unwrap();
1428
1429 abs += RelativeTime::new_time(0, 1);
1430
1431 assert_eq!(abs.time_nsec, 0);
1432 assert_eq!(abs.time_sec, 2);
1433
1434 abs += RelativeTime::new_time(1, 1);
1435
1436 assert_eq!(abs.time_nsec, 1);
1437 assert_eq!(abs.time_sec, 3);
1438
1439 abs += RelativeTime::new_time(0, 999_999_999);
1440
1441 assert_eq!(abs.time_nsec, 0);
1442 assert_eq!(abs.time_sec, 4);
1443
1444 abs -= RelativeTime::new_time(0, 999_999_999);
1445
1446 assert_eq!(abs.time_nsec, 1);
1447 assert_eq!(abs.time_sec, 3);
1448
1449 abs -= RelativeTime::new_time(0, 1);
1450
1451 assert_eq!(abs.time_nsec, 0);
1452 assert_eq!(abs.time_sec, 3);
1453
1454 abs -= RelativeTime::new_time(0, 500_000_000);
1455
1456 assert_eq!(abs.time_nsec, 500_000_000);
1457 assert_eq!(abs.time_sec, 2);
1458
1459 abs -= RelativeTime::new_time(0, 400_000_000);
1460
1461 assert_eq!(abs.time_nsec, 100_000_000);
1462 assert_eq!(abs.time_sec, 2);
1463
1464 abs -= RelativeTime::new_time(1, 200_000_000);
1465
1466 assert_eq!(abs.time_nsec, 900_000_000);
1467 assert_eq!(abs.time_sec, 0);
1468 }
1469}