use std::fmt;
pub enum AggregationResult {
Count(CountResult),
GroupBy(GroupByResult),
Top(TopResult),
Stats(StatsResult),
}
pub struct CountResult {
pub total: usize,
}
pub struct GroupByResult {
pub field: String,
pub groups: Vec<(String, usize)>,
}
pub struct TopResult {
pub field: String,
pub n: usize,
pub entries: Vec<(String, usize)>,
}
pub struct StatsResult {
pub total: usize,
pub by_kind: Vec<(String, usize)>,
pub by_lang: Vec<(String, usize)>,
pub by_visibility: Vec<(String, usize)>,
}
impl fmt::Display for AggregationResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Count(r) => write!(f, "{r}"),
Self::GroupBy(r) => write!(f, "{r}"),
Self::Top(r) => write!(f, "{r}"),
Self::Stats(r) => write!(f, "{r}"),
}
}
}
impl fmt::Display for CountResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.total)
}
}
impl fmt::Display for GroupByResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (value, count) in &self.groups {
writeln!(f, "{value}: {count}")?;
}
Ok(())
}
}
impl fmt::Display for TopResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (value, count) in &self.entries {
writeln!(f, "{value}: {count}")?;
}
Ok(())
}
}
impl fmt::Display for StatsResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Total: {}", self.total)?;
writeln!(f, "\nBy kind:")?;
for (kind, count) in &self.by_kind {
writeln!(f, " {kind}: {count}")?;
}
writeln!(f, "\nBy language:")?;
for (lang, count) in &self.by_lang {
writeln!(f, " {lang}: {count}")?;
}
writeln!(f, "\nBy visibility:")?;
for (vis, count) in &self.by_visibility {
writeln!(f, " {vis}: {count}")?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_count_result_display() {
let result = CountResult { total: 42 };
assert_eq!(format!("{result}"), "42");
}
#[test]
fn test_group_by_result_display() {
let result = GroupByResult {
field: "lang".to_string(),
groups: vec![("rust".to_string(), 10), ("python".to_string(), 5)],
};
let output = format!("{result}");
assert!(output.contains("rust: 10"));
assert!(output.contains("python: 5"));
}
#[test]
fn test_top_result_display() {
let result = TopResult {
field: "lang".to_string(),
n: 2,
entries: vec![("rust".to_string(), 10), ("python".to_string(), 5)],
};
let output = format!("{result}");
assert!(output.contains("rust: 10"));
assert!(output.contains("python: 5"));
}
#[test]
fn test_stats_result_display() {
let result = StatsResult {
total: 15,
by_kind: vec![("function".to_string(), 10)],
by_lang: vec![("rust".to_string(), 15)],
by_visibility: vec![("public".to_string(), 8)],
};
let output = format!("{result}");
assert!(output.contains("Total: 15"));
assert!(output.contains("function: 10"));
assert!(output.contains("rust: 15"));
assert!(output.contains("public: 8"));
}
}