pkgs/logger/
output.rs

1use std::io::{self, Write};
2
3use super::LogMessage;
4
5pub trait LoggerOutput {
6    fn log(&mut self, message: &LogMessage);
7}
8
9#[derive(Debug, Clone, Copy, Default)]
10pub struct NullOutput;
11
12impl LoggerOutput for NullOutput {
13    fn log(&mut self, _message: &LogMessage) {}
14}
15
16pub struct WriterOutput<W: Write> {
17    writer: W,
18}
19
20impl<W: Write> WriterOutput<W> {
21    pub fn new(writer: W) -> Self {
22        Self { writer }
23    }
24
25    pub fn flush(&mut self) -> io::Result<()> {
26        self.writer.flush()
27    }
28}
29
30impl<W: Write> LoggerOutput for WriterOutput<W> {
31    fn log(&mut self, message: &LogMessage) {
32        let message = match message {
33            LogMessage::LoadModule(module) => format!("Load Module {module}"),
34            LogMessage::UnloadModule(module) => format!("Unload Module {module}"),
35            LogMessage::RollbackLoadModule(module) => format!("Rollback Load Module {module}"),
36            LogMessage::RollbackUnloadModule(module) => format!("Rollback Unload Module {module}"),
37            LogMessage::CreateDir(path) => format!("Create Directory {}", path.to_string_lossy()),
38            LogMessage::CreateSymlink { src, dst } => format!(
39                "Create Symlink {} -> {}",
40                dst.to_string_lossy(),
41                src.to_string_lossy()
42            ),
43            LogMessage::RemoveDir(path) => format!("Remove Directory {}", path.to_string_lossy()),
44            LogMessage::RemoveSymlink { src, dst } => format!(
45                "Remove Symlink {} -> {}",
46                dst.to_string_lossy(),
47                src.to_string_lossy()
48            ),
49        };
50
51        // ignore errors on write
52        let _ = writeln!(self.writer, "{message}").inspect_err(|err| {
53            eprintln!("Warning! Write log output to writer failed: {err}");
54        });
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use std::io::Cursor;
61
62    use super::*;
63    use crate::test_utils::prelude::*;
64
65    #[gtest]
66    fn writer_output() -> Result<()> {
67        let mut buf = Cursor::new(Vec::new());
68        let mut output = WriterOutput::new(&mut buf);
69        output.log(&LogMessage::CreateDir(PathBuf::from("test_dir")));
70        output.log(&LogMessage::CreateSymlink {
71            src: PathBuf::from("src"),
72            dst: PathBuf::from("dst"),
73        });
74        output.flush()?;
75
76        let content = String::from_utf8(buf.into_inner())?;
77        expect_eq!(
78            content,
79            "Create Directory test_dir\nCreate Symlink dst -> src\n"
80        );
81
82        Ok(())
83    }
84}