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
//! Utility function to spawn a log proxy implementation to forward standard i/o streams.

use crate::{
    common::log::{init, proxy::LogProxy, LogRecord, Loglevel, LoglevelFilter},
    error, log, trace,
};
use crossbeam_channel::Sender;
use std::{
    io::Read,
    thread::{spawn, JoinHandle},
};

/// Forward standard i/o to log channel.
///
/// Spawns a thread which takes a readable stream and forwards lines as log
/// records to the log thread until it matches EOF. The log record level is
/// set to the level argument of the function.
///
/// Returns a thread::JoinHandle to the spawned thread.
pub fn proxy_stdio(
    name: impl Into<String>,
    mut stream: Box<dyn Read + Send>,
    sender: Sender<LogRecord>,
    level: Loglevel,
) -> JoinHandle<()> {
    let name = name.into();
    spawn(move || {
        init(vec![LogProxy::boxed(
            name,
            LoglevelFilter::from(level),
            sender,
        )])
        .unwrap();
        let mut buf = Vec::new();
        let mut byte = [0u8];
        loop {
            match stream.read(&mut byte) {
                Ok(0) => {
                    trace!("EOF: closing stdio forwarding channel");
                    break;
                }
                Ok(_) => {
                    if byte[0] == 0x0A {
                        match String::from_utf8(buf.clone()) {
                            Ok(line) => log!(level, "{}", line),
                            Err(err) => error!("{}", err),
                        }
                        buf.clear()
                    } else {
                        buf.push(byte[0])
                    }
                }
                Err(error) => {
                    error!("{}", error);
                }
            }
        }
    })
}