torrust_tracker_deployer_lib/presentation/cli/views/sinks/file.rs
1//! File output sink implementation
2
3use std::io::Write;
4
5use super::super::{OutputMessage, OutputSink};
6
7// ============================================================================
8// Example Sink Implementations
9// ============================================================================
10
11/// Example: File sink that writes all output to a file
12///
13/// This is an example implementation showing how to create a custom sink
14/// that writes to a file. In production, you might want to add buffering,
15/// rotation, or other features.
16///
17/// # Examples
18///
19/// ```rust,ignore
20/// use torrust_tracker_deployer_lib::presentation::cli::views::{FileSink, UserOutput, VerbosityLevel, CompositeSink, StandardSink};
21///
22/// // Write to both console and file
23/// let composite = CompositeSink::new(vec![
24/// Box::new(StandardSink::default_console()),
25/// Box::new(FileSink::new("output.log").unwrap()),
26/// ]);
27/// let mut output = UserOutput::with_sink(VerbosityLevel::Normal, Box::new(composite));
28/// ```
29pub struct FileSink {
30 file: std::fs::File,
31}
32
33impl FileSink {
34 /// Create a new file sink
35 ///
36 /// Opens or creates the file at the given path in append mode.
37 ///
38 /// # Errors
39 ///
40 /// Returns an error if the file cannot be opened or created.
41 ///
42 /// # Examples
43 ///
44 /// ```rust,ignore
45 /// use torrust_tracker_deployer_lib::presentation::cli::views::FileSink;
46 ///
47 /// let sink = FileSink::new("output.log")?;
48 /// ```
49 pub fn new(path: &str) -> std::io::Result<Self> {
50 let file = std::fs::OpenOptions::new()
51 .create(true)
52 .append(true)
53 .open(path)?;
54 Ok(Self { file })
55 }
56}
57
58impl OutputSink for FileSink {
59 fn write_message(&mut self, _message: &dyn OutputMessage, formatted: &str) {
60 writeln!(self.file, "{formatted}").ok();
61 }
62}