use std::collections::BTreeSet;
use super::Report;
pub(super) fn render_text(report: &Report) -> String {
let now = report.now.now_secs();
let ages: Vec<String> = report
.rules
.iter()
.map(|rule| {
rule.cached.as_ref().map_or_else(String::new, |record| {
humanize_age(now.saturating_sub(record.ran_at))
})
})
.collect();
let voided = report
.rules
.iter()
.any(|rule| rule.missing_output.is_some());
let multi_source = report
.rules
.iter()
.map(|rule| rule.source.as_str())
.collect::<BTreeSet<_>>()
.len()
> 1;
let rule_width = column_width(
report.rules.iter().map(|rule| rule.name.chars().count()),
"RULE",
);
let source_width = if multi_source {
column_width(
report.rules.iter().map(|rule| rule.source.chars().count()),
"SOURCE",
)
} else {
0
};
let state_width = column_width(
report.rules.iter().map(|rule| rule.state.label().len()),
"STATE",
);
let age_width = if voided {
column_width(ages.iter().map(|age| age.chars().count()), "AGE")
} else {
0
};
let row = |rule: &str, source: &str, state: &str, age: &str, missing: &str| {
let mut line = format!("{rule:<rule_width$}");
if multi_source {
line.push_str(&format!(" {source:<source_width$}"));
}
line.push_str(&format!(
" {state:<state_width$} {age:<age_width$} {missing}"
));
format!("{}\n", line.trim_end())
};
let mut out = row(
"RULE",
"SOURCE",
"STATE",
"AGE",
if voided { "MISSING OUTPUT" } else { "" },
);
for (rule, age) in report.rules.iter().zip(&ages) {
out.push_str(&row(
&rule.name,
&rule.source,
rule.state.label(),
age,
rule.missing_output.as_deref().unwrap_or(""),
));
}
out
}
fn column_width(cells: impl Iterator<Item = usize>, header: &str) -> usize {
cells.max().unwrap_or(0).max(header.len())
}
fn humanize_age(secs: u64) -> String {
const MINUTE: u64 = 60;
const HOUR: u64 = 60 * MINUTE;
const DAY: u64 = 24 * HOUR;
if secs < MINUTE {
format!("{secs}s ago")
} else if secs < HOUR {
format!("{}m ago", secs / MINUTE)
} else if secs < DAY {
format!("{}h ago", secs / HOUR)
} else {
format!("{}d ago", secs / DAY)
}
}
#[cfg(test)]
#[path = "status_table_tests.rs"]
mod tests;