libmactime2/bodyfile/
bodyfile_decoder.rs

1use crate::{Filter, Joinable, RunOptions, Provider, Consumer};
2use std::sync::mpsc::{self, Sender, Receiver};
3use std::thread::{JoinHandle};
4use bodyfile::Bodyfile3Line;
5use std::convert::TryFrom;
6
7pub struct BodyfileDecoder {
8    worker: Option<JoinHandle<()>>,
9    rx: Option<Receiver<Bodyfile3Line>>,
10}
11
12impl Filter<String, Bodyfile3Line, ()> for BodyfileDecoder {
13    fn worker(reader: Receiver<String>, tx: Sender<Bodyfile3Line>, options: RunOptions) {
14        loop {
15            let mut line = match reader.recv() {
16                Err(_) => {break;}
17                Ok(l) => l
18            };
19
20            if line.starts_with('#') { continue; }
21            Self::trim_newline(&mut line);
22
23            let bf_line = match Bodyfile3Line::try_from(line.as_ref()) {
24                Err(e) => {
25                    if options.strict_mode {
26                        log::warn!("bodyfile parser error: {}", e);
27                        panic!("failed while parsing: {:?}", line);
28                    } else {
29                        log::warn!("bodyfile parser error: {}", e);
30                        #[cfg(debug_assertions)]
31                        log::warn!("failed line was: {:?}", line);
32                    }
33                    continue;
34                }
35                Ok(l) => l
36            };
37
38            if tx.send(bf_line).is_err() {
39                break;
40            }
41        }
42    }
43}
44
45impl Provider<Bodyfile3Line, ()> for BodyfileDecoder {
46    fn get_receiver(&mut self) -> Receiver<Bodyfile3Line> {
47        self.rx.take().unwrap()
48    }
49
50}
51
52impl Consumer<String> for BodyfileDecoder {
53    fn with_receiver(reader: Receiver<String>, options: RunOptions) -> Self {
54        let (tx, rx): (Sender<Bodyfile3Line>, Receiver<Bodyfile3Line>) = mpsc::channel();
55        Self {
56            worker: Some(std::thread::spawn(move || {
57                Self::worker(reader, tx, options)
58            })),
59            rx: Some(rx),
60        }
61    }
62}
63
64impl BodyfileDecoder {
65    fn trim_newline(s: &mut String) {
66        if s.ends_with('\n') {
67            s.pop();
68            if s.ends_with('\r') {
69                s.pop();
70            }
71        }
72    }
73}
74
75impl Joinable<()> for BodyfileDecoder {
76    fn join(&mut self) -> std::thread::Result<()> {
77        self.worker.take().unwrap().join()
78    }
79}