1use std::io::{self, Read, Write};
4
5use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
11pub struct Timeval {
12 pub sec: i32,
14 pub usec: i32,
16}
17
18impl Timeval {
19 pub fn from_usec(usec: i64) -> Self {
21 Self {
22 sec: (usec / 1_000_000) as i32,
23 usec: (usec % 1_000_000) as i32,
24 }
25 }
26
27 pub fn to_usec(self) -> i64 {
29 self.sec as i64 * 1_000_000 + self.usec as i64
30 }
31
32 pub fn read_from<R: Read>(r: &mut R) -> io::Result<Self> {
34 Ok(Self {
35 sec: r.read_i32::<LittleEndian>()?,
36 usec: r.read_i32::<LittleEndian>()?,
37 })
38 }
39
40 pub fn write_to<W: Write>(&self, w: &mut W) -> io::Result<()> {
42 w.write_i32::<LittleEndian>(self.sec)?;
43 w.write_i32::<LittleEndian>(self.usec)?;
44 Ok(())
45 }
46}
47
48impl std::ops::Add for Timeval {
49 type Output = Self;
50
51 fn add(self, rhs: Self) -> Self {
52 let mut sec = self.sec + rhs.sec;
53 let mut usec = self.usec + rhs.usec;
54 if usec >= 1_000_000 {
55 sec += usec / 1_000_000;
56 usec %= 1_000_000;
57 }
58 Self { sec, usec }
59 }
60}
61
62impl std::ops::Sub for Timeval {
63 type Output = Self;
64
65 fn sub(self, rhs: Self) -> Self {
66 let mut sec = self.sec - rhs.sec;
67 let mut usec = self.usec - rhs.usec;
68 while usec < 0 {
69 sec -= 1;
70 usec += 1_000_000;
71 }
72 Self { sec, usec }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn timeval_add() {
82 let a = Timeval {
83 sec: 1,
84 usec: 900_000,
85 };
86 let b = Timeval {
87 sec: 0,
88 usec: 200_000,
89 };
90 let result = a + b;
91 assert_eq!(
92 result,
93 Timeval {
94 sec: 2,
95 usec: 100_000
96 }
97 );
98 }
99
100 #[test]
101 fn timeval_sub() {
102 let a = Timeval {
103 sec: 2,
104 usec: 100_000,
105 };
106 let b = Timeval {
107 sec: 1,
108 usec: 900_000,
109 };
110 let result = a - b;
111 assert_eq!(
112 result,
113 Timeval {
114 sec: 0,
115 usec: 200_000
116 }
117 );
118 }
119
120 #[test]
121 fn timeval_round_trip() {
122 let tv = Timeval {
123 sec: 1000,
124 usec: 500_000,
125 };
126 let mut buf = Vec::new();
127 tv.write_to(&mut buf).unwrap();
128 assert_eq!(buf.len(), 8);
129 let mut cursor = io::Cursor::new(&buf);
130 let decoded = Timeval::read_from(&mut cursor).unwrap();
131 assert_eq!(tv, decoded);
132 }
133
134 #[test]
135 fn timeval_known_bytes() {
136 let expected: [u8; 8] = [0xE8, 0x03, 0x00, 0x00, 0x20, 0xA1, 0x07, 0x00];
138 let tv = Timeval {
139 sec: 1000,
140 usec: 500_000,
141 };
142 let mut buf = Vec::new();
143 tv.write_to(&mut buf).unwrap();
144 assert_eq!(buf.as_slice(), &expected);
145 }
146}