mod csv;
mod human;
mod json;
use crate::cli::{CountMode, DisplayMode, OutputFormat};
use crate::counter::Count;
pub struct OutputFormatter {
format: OutputFormat,
mode: CountMode,
}
impl OutputFormatter {
#[must_use]
pub const fn new(format: OutputFormat, mode: CountMode) -> Self {
Self { format, mode }
}
#[must_use]
pub fn format_output(&self, results: &[(String, Count)], display: DisplayMode) -> String {
match self.format {
OutputFormat::Human => human::format(results, display, self.mode),
OutputFormat::Json => json::format(results, display, self.mode),
OutputFormat::Csv => csv::format(results, display, self.mode),
}
}
}
#[must_use]
pub fn calculate_total(results: &[(String, Count)]) -> Count {
Count {
words: results.iter().map(|(_, c)| c.words).sum(),
characters: results.iter().map(|(_, c)| c.characters).sum(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_total_single_file() {
let results = vec![(
"file1.typ".to_string(),
Count {
words: 100,
characters: 500,
},
)];
let total = calculate_total(&results);
assert_eq!(total.words, 100);
assert_eq!(total.characters, 500);
}
#[test]
fn test_calculate_total_multiple_files() {
let results = vec![
(
"file1.typ".to_string(),
Count {
words: 100,
characters: 500,
},
),
(
"file2.typ".to_string(),
Count {
words: 200,
characters: 1000,
},
),
(
"file3.typ".to_string(),
Count {
words: 50,
characters: 250,
},
),
];
let total = calculate_total(&results);
assert_eq!(total.words, 350);
assert_eq!(total.characters, 1750);
}
#[test]
fn test_calculate_total_empty() {
let results: Vec<(String, Count)> = vec![];
let total = calculate_total(&results);
assert_eq!(total.words, 0);
assert_eq!(total.characters, 0);
}
#[test]
fn test_calculate_total_zero_counts() {
let results = vec![
(
"file1.typ".to_string(),
Count {
words: 0,
characters: 0,
},
),
(
"file2.typ".to_string(),
Count {
words: 0,
characters: 0,
},
),
];
let total = calculate_total(&results);
assert_eq!(total.words, 0);
assert_eq!(total.characters, 0);
}
#[test]
fn test_output_formatter_creation() {
let formatter = OutputFormatter::new(OutputFormat::Human, CountMode::Both);
assert_eq!(formatter.mode, CountMode::Both);
}
#[test]
fn test_output_formatter_format_output_single_file() {
let formatter = OutputFormatter::new(OutputFormat::Human, CountMode::Both);
let results = vec![(
"test.typ".to_string(),
Count {
words: 42,
characters: 200,
},
)];
let output = formatter.format_output(&results, DisplayMode::Auto);
assert!(output.contains("42"));
assert!(output.contains("200"));
}
}