use crate::theme::theme;
use anstream::{print, println};
use cnt_core::{Counter, Counters, CountersBlock, Severity};
const USAGE_WARN_PERCENT: u64 = 95;
pub fn list(counters: &Counters) {
let hint = theme().hint;
if let Some(ram) = counters.ram_counters() {
list_entries(ram);
if counters.bkp_counters().is_some() {
println!();
}
} else {
println!("{hint}No RAM counters found{hint:#}");
}
if let Some(bkp) = counters.bkp_counters() {
list_entries(bkp);
} else {
println!("{hint}No BKP counters found{hint:#}");
}
}
fn list_entries(cnt: &CountersBlock) {
let t = theme();
print_header(cnt);
let width = name_width(cnt);
for c in cnt.entries().values() {
let hint = t.hint;
print!(
"{hint}{}{hint:#} {:width$}",
severity_label(c.severity),
c.qualified_name()
);
print!(" {hint}{}{hint:#}", c.ty);
if !c.unit.is_empty() {
print!(" {hint}`{}`{hint:#}", c.unit);
}
println!();
print_location(c);
}
print_usage(cnt, cnt.used_bytes());
}
pub(super) fn print_header(cnt: &CountersBlock) {
let t = theme();
let (header, hint) = (t.header, t.hint);
println!(
"📍 {header}{} counters{header:#} {hint}at 0x{:08x}, {} B{hint:#}",
cnt.storage(),
cnt.buffer().addr,
cnt.buffer().size
);
}
pub(super) fn name_width(cnt: &CountersBlock) -> usize {
cnt.entries()
.values()
.map(|c| c.qualified_name().len())
.max()
.unwrap_or(0)
}
pub(crate) fn severity_label(severity: Severity) -> &'static str {
match severity {
Severity::Error => "ERROR",
Severity::Warn => "WARN ",
Severity::Info => "INFO ",
Severity::Debug => "DEBUG",
Severity::Trace => "TRACE",
}
}
pub(super) fn print_location(c: &Counter) {
let t = theme();
let (hint, path) = (t.hint, t.path);
print!("{hint}└─ {}", c.crate_name);
if let Some(layout) = &c.layout {
print!(" {layout}");
}
println!(" @ {hint:#}{path}{}{path:#}", c.location);
}
fn print_usage(cnt: &CountersBlock, used: u64) {
let t = theme();
let hint = t.hint;
let size = cnt.buffer().size;
let free = size as i64 - used as i64;
let percent = if size == 0 {
0
} else {
(used * 100).div_ceil(size)
};
println!(
"{hint}{} used: {used} of {size} B ({percent}%), free: {free} B ({}x u32, {}x u64){hint:#}",
cnt.storage(),
free.max(0) / 4,
free.max(0) / 8
);
if used > size {
let error = t.error;
println!(
"🛑 {error}Not enough space for {} counters: {used} B needed, {size} B available{error:#}",
cnt.storage()
);
} else if percent > USAGE_WARN_PERCENT {
let warn = t.warn;
println!(
"⚠️ {warn}{} counters buffer is {percent}% full{warn:#}",
cnt.storage()
);
}
}