1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::time::Duration;
use std::convert::TryInto;
use rustix::time::{Itimerspec, Timespec};
use TimerState;
const TS_NULL: Timespec = Timespec { tv_sec: 0, tv_nsec: 0 };
fn to_timespec(d: Duration) -> Timespec {
Timespec {
tv_sec: d.as_secs().try_into().unwrap(),
tv_nsec: d.subsec_nanos() as _,
}
}
fn from_timespec(ts: Timespec) -> Duration {
Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32)
}
impl From<TimerState> for Itimerspec {
fn from(ts: TimerState) -> Itimerspec {
match ts {
TimerState::Disarmed => Itimerspec {
it_value: TS_NULL,
it_interval: TS_NULL
},
TimerState::Oneshot(d) => Itimerspec {
it_value: to_timespec(d),
it_interval: TS_NULL,
},
TimerState::Periodic { current, interval } => Itimerspec {
it_value: to_timespec(current),
it_interval: to_timespec(interval)
},
}
}
}
impl From<Itimerspec> for TimerState {
fn from(its: Itimerspec) -> TimerState {
match its {
Itimerspec { it_value, .. } if it_value == TS_NULL => {
TimerState::Disarmed
}
Itimerspec { it_value, it_interval } if it_interval == TS_NULL => {
TimerState::Oneshot(from_timespec(it_value))
}
Itimerspec { it_value, it_interval } => {
TimerState::Periodic {
current: from_timespec(it_value),
interval: from_timespec(it_interval)
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn convert_disarmed() {
let start = TimerState::Disarmed;
let clone = start.clone();
assert_eq!(clone, start);
let native: Itimerspec = clone.into();
assert!(native.it_value.tv_sec == 0);
assert!(native.it_value.tv_nsec == 0);
let target: TimerState = native.into();
assert_eq!(target, start);
}
#[test]
fn convert_oneshot() {
let start = TimerState::Oneshot(Duration::new(1, 0));
let clone = start.clone();
assert_eq!(clone, start);
let native: Itimerspec = clone.into();
assert!(native.it_interval.tv_sec == 0);
assert!(native.it_interval.tv_nsec == 0);
assert!(native.it_value.tv_sec == 1);
assert!(native.it_value.tv_nsec == 0);
let target: TimerState = native.into();
assert_eq!(target, start);
}
#[test]
fn convert_periodic() {
let start = TimerState::Periodic {
current: Duration::new(1, 0),
interval: Duration::new(0, 1),
};
let clone = start.clone();
assert_eq!(clone, start);
let native: Itimerspec = clone.into();
assert!(native.it_interval.tv_sec == 0);
assert!(native.it_interval.tv_nsec == 1);
assert!(native.it_value.tv_sec == 1);
assert!(native.it_value.tv_nsec == 0);
let target: TimerState = native.into();
assert_eq!(target, start);
}
}