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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#[cfg(target_os = "linux")]
#[macro_use]
extern crate enum_display_derive;
pub mod error;
use error::RMesgError;
use std::thread::sleep;
use std::time::{Duration, SystemTime};
#[cfg(target_os = "linux")]
pub mod linux;
#[cfg(target_os = "linux")]
pub use linux::rmesg;
#[cfg(not(target_os = "linux"))]
pub mod default;
#[cfg(not(target_os = "linux"))]
pub use default::rmesg;
pub const SUGGESTED_POLL_INTERVAL: std::time::Duration = Duration::from_secs(10);
pub struct RMesgLinesIterator {
clear: bool,
lines: Vec<String>,
poll_interval: Duration,
sleep_interval: Duration,
last_poll: SystemTime,
lastline: Option<String>,
}
impl std::iter::Iterator for RMesgLinesIterator {
type Item = Result<String, RMesgError>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let elapsed = match self.last_poll.elapsed() {
Ok(duration) => duration,
Err(e) => {
eprintln!(
"Error occurred when obtaining elapsed time since last poll: {:?}",
e
);
return None;
}
};
if elapsed >= self.poll_interval {
if let Err(e) = self.poll() {
eprintln!(
"An error occurred when polling rmesg for new messages to trail: {}",
e
);
return None;
}
}
if self.lines.len() == 0 {
sleep(self.sleep_interval);
continue;
}
return Some(Ok(self.lines.remove(0)));
}
}
}
impl RMesgLinesIterator {
fn poll(&mut self) -> Result<usize, RMesgError> {
let rawlogs = rmesg(self.clear)?;
let maybe_lastline = self.lastline.as_ref();
let revlines = rawlogs.lines().rev();
let lines_since_lastline_rev_iter = revlines
.take_while(|&line| maybe_lastline.is_none() || line != maybe_lastline.unwrap());
let mut newlines: Vec<&str> = vec![];
for revline in lines_since_lastline_rev_iter {
newlines.push(revline);
}
newlines.reverse();
let mut linesadded: usize = 0;
let mut new_lastline: &str = "";
for newline in newlines {
self.lines.push(newline.to_owned());
linesadded = linesadded + 1;
new_lastline = newline;
}
if linesadded > 0 {
self.lastline = Some(new_lastline.to_owned());
return Ok(linesadded);
}
Ok(0)
}
}
pub fn rmesg_lines_iter(
clear: bool,
poll_interval: Duration,
) -> Result<RMesgLinesIterator, RMesgError> {
let sleep_interval = match poll_interval.checked_add(Duration::from_millis(200)) {
Some(si) => si,
None => return Err(RMesgError::UnableToAddDurationToSystemTime),
};
let last_poll = match SystemTime::now().checked_sub(sleep_interval) {
Some(lp) => lp,
None => return Err(RMesgError::UnableToAddDurationToSystemTime),
};
Ok(RMesgLinesIterator {
lines: Vec::with_capacity(1000),
poll_interval,
sleep_interval,
last_poll,
clear,
lastline: None,
})
}