use std::fmt::Display;
pub fn sorted_table_lines<'a, K, V>(
table: impl IntoIterator<Item = (K, &'a V)> + 'a,
) -> (usize, impl Iterator<Item = (String, &'a V)>)
where
K: Ord + Display + 'a,
V: Ord + Display + 'a,
{
let mut entries = table.into_iter().collect::<Vec<_>>();
entries.sort_unstable_by(|a, b| a.1.cmp(b.1).reverse().then_with(|| a.0.cmp(&b.0)));
let mut entries =
entries.into_iter().map(|(label, ct)| (label.to_string().to_lowercase(), ct)).peekable();
let width = entries.peek().map(|(_, b)| b.to_string().len()).unwrap_or_default();
(width, entries)
}
#[must_use]
pub fn format_table_line<V>(width: &usize, label: &str, count: &V) -> String
where
V: Display,
{
format!("{count:>width$} {label}")
}
pub fn generate_execution_report<'a, K, V>(
table: impl IntoIterator<Item = (K, &'a V)> + 'a,
) -> impl Iterator<Item = String> + 'a
where
K: Ord + Display + 'a,
V: Ord + PartialEq<u64> + Display + 'a,
{
let (width, lines) = sorted_table_lines(table);
lines
.filter(move |(_, count)| **count != 0)
.map(move |(label, count)| format!(" {}", format_table_line(&width, &label, count)))
}