Skip to main content

torrust_tracker_deployer_lib/presentation/cli/views/sinks/
composite.rs

1//! Composite output sink for multiple destinations
2
3use super::super::{OutputMessage, OutputSink};
4
5pub struct CompositeSink {
6    sinks: Vec<Box<dyn OutputSink>>,
7}
8
9impl CompositeSink {
10    /// Create a new composite sink with the given child sinks
11    ///
12    /// # Examples
13    ///
14    /// ```rust,ignore
15    /// use torrust_tracker_deployer_lib::presentation::cli::views::CompositeSink;
16    ///
17    /// let composite = CompositeSink::new(vec![
18    ///     Box::new(StandardSink::default_console()),
19    ///     Box::new(FileSink::new("output.log").unwrap()),
20    /// ]);
21    /// ```
22    #[must_use]
23    pub fn new(sinks: Vec<Box<dyn OutputSink>>) -> Self {
24        Self { sinks }
25    }
26
27    /// Add a sink to the composite
28    ///
29    /// # Examples
30    ///
31    /// ```rust,ignore
32    /// use torrust_tracker_deployer_lib::presentation::cli::views::CompositeSink;
33    ///
34    /// let mut composite = CompositeSink::new(vec![]);
35    /// composite.add_sink(Box::new(StandardSink::default_console()));
36    /// composite.add_sink(Box::new(FileSink::new("output.log").unwrap()));
37    /// ```
38    pub fn add_sink(&mut self, sink: Box<dyn OutputSink>) {
39        self.sinks.push(sink);
40    }
41}
42
43impl OutputSink for CompositeSink {
44    fn write_message(&mut self, message: &dyn OutputMessage, formatted: &str) {
45        for sink in &mut self.sinks {
46            sink.write_message(message, formatted);
47        }
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn it_should_create_composite_sink_when_given_empty_sink_list() {
57        let composite = CompositeSink::new(vec![]);
58
59        assert_eq!(composite.sinks.len(), 0);
60    }
61
62    #[test]
63    fn it_should_add_sink_to_composite_when_add_sink_is_called() {
64        // Create a mock sink for testing
65        struct MockSink;
66        impl OutputSink for MockSink {
67            fn write_message(&mut self, _message: &dyn OutputMessage, _formatted: &str) {}
68        }
69
70        let mut composite = CompositeSink::new(vec![]);
71
72        composite.add_sink(Box::new(MockSink));
73
74        assert_eq!(composite.sinks.len(), 1);
75    }
76}