1use std::fs::{self, File};
7use std::io::{self, Read, Seek, SeekFrom};
8use std::num;
9use std::process::Command;
10use std::thread;
11use std::time::Duration;
12
13fn read_to_string(f: &mut File, mut buf: &mut String) -> io::Result<()> {
15 f.seek(SeekFrom::Start(0))?;
16 f.read_to_string(&mut buf)?;
17 Ok(())
18}
19
20pub fn str_to_f32(s: &str) -> Result<f32, num::ParseFloatError> {
22 s.trim().parse()
23}
24
25pub fn file_to_f32(path: &str) -> Result<f32, num::ParseFloatError> {
27 fs::read_to_string(path).unwrap().trim().parse()
28}
29
30pub struct Monitor<T>
32where
33 T: FnMut() -> String,
34{
35 reader: T,
36 period: Duration,
37 first: bool,
38}
39
40impl<T> Monitor<T>
41where
42 T: FnMut() -> String,
43{
44 fn new(reader: T, period: f32) -> Self {
45 Monitor {
46 reader,
47 period: Duration::from_secs_f32(period),
48 first: true,
49 }
50 }
51
52 pub fn read(&mut self) -> String {
53 (self.reader)()
54 }
55}
56
57impl<T> Iterator for Monitor<T>
58where
59 T: FnMut() -> String,
60{
61 type Item = String;
62
63 fn next(&mut self) -> Option<Self::Item> {
64 if self.first {
65 self.first = false;
66 } else {
67 thread::sleep(self.period);
68 }
69 Some(self.read())
70 }
71}
72
73pub fn monitor_file(path: String, period: f32) -> Monitor<impl FnMut() -> String> {
77 let mut file = File::open(&path).unwrap();
78 let mut buf = String::new();
79 Monitor::new(
80 move || {
81 buf.truncate(0);
82 if let Ok(_) = read_to_string(&mut file, &mut buf) {
83 buf.clone()
84 } else {
85 format!("Failed to read: {}", &path)
86 }
87 },
88 period,
89 )
90}
91
92pub fn monitor_command(
95 cmd: &'static str,
96 args: &'static [&'static str],
97 period: f32,
98) -> Monitor<impl FnMut() -> String> {
99 Monitor::new(
100 move || {
101 if let Ok(output) = Command::new(cmd).args(args).output() {
102 String::from_utf8(output.stdout).unwrap()
103 } else {
104 format!("Command failed: '{:?}'", &cmd)
105 }
106 },
107 period,
108 )
109}
110
111pub fn wait_for_signal(signal: i32, timeout: f32) -> crossbeam_channel::Receiver<()> {
114 let (s, r) = crossbeam_channel::unbounded();
115 let s2 = s.clone();
116 unsafe {
117 signal_hook::register(signal, move || s2.send(()).unwrap()).unwrap();
118 }
119 thread::spawn(move || loop {
120 thread::sleep(Duration::from_secs_f32(timeout));
121 s.send(()).unwrap();
122 });
123 r
124}