#![allow(dead_code)]
use crate::normalized::NormalizedDrive;
use crate::state::SystemState;
const KIB: u64 = 1024;
const MIB: u64 = KIB * 1024;
const GIB: u64 = MIB * 1024;
const TIB: u64 = GIB * 1024;
#[allow(clippy::cast_precision_loss)]
pub fn format_bytes(bytes: u64) -> String {
if bytes == 0 {
return "0 B".to_string();
}
if bytes >= TIB {
format!("{:.1} TiB", bytes as f64 / TIB as f64)
} else if bytes >= GIB {
format!("{:.1} GiB", bytes as f64 / GIB as f64)
} else if bytes >= MIB {
format!("{:.1} MiB", bytes as f64 / MIB as f64)
} else if bytes >= KIB {
format!("{:.1} KiB", bytes as f64 / KIB as f64)
} else {
format!("{bytes} B")
}
}
pub fn format_pct(pct: f32) -> String {
let clamped = pct.clamp(0.0, 100.0);
if clamped >= 100.0 {
"100%".to_string()
} else if clamped <= 0.0 {
"0.0%".to_string()
} else {
format!("{clamped:.1}%")
}
}
pub fn format_load(load: &gregg_protocol::LoadAverage) -> String {
format!("{:.2}/{:.2}/{:.2}", load.one, load.five, load.fifteen)
}
pub fn header_line(system: &SystemState, width: u16) -> String {
let Some(snap) = &system.latest else {
return format!("{} (no data)", display_name(system));
};
let name = display_name(system);
let io_str = if snap.cpu_iowait_supported {
match snap.iowait_pct {
Some(iowait) => format!("IO {iowait:.1}%"),
None => "IO \u{2014}".to_string(),
}
} else {
"IO \u{2014}".to_string()
};
let load_str = match &snap.load {
Some(l) => format_load(l),
None => "L \u{2014}".to_string(),
};
let cores_str = format!("{}c", snap.logical_cores);
let os_str = format!("{} {}", snap.system.os_name, snap.system.os_version);
let kernel_str = format!("{} {}", snap.system.kernel_name, snap.system.kernel_release);
let arch_str = &snap.system.architecture;
if width >= 80 {
format!("{name} {io_str} {load_str} {cores_str} {os_str} {kernel_str} {arch_str}")
} else if width >= 50 {
format!("{name} {io_str} {load_str} {cores_str} {os_str}")
} else if width >= 32 {
format!("{name} {io_str} {load_str} {cores_str}")
} else {
format!("{name} {io_str}")
}
}
fn display_name(system: &SystemState) -> &str {
system
.configured_name
.as_deref()
.unwrap_or(&system.endpoint.host)
}
#[allow(clippy::cast_possible_truncation, clippy::cast_precision_loss)]
pub fn drive_detail_line(drive: &NormalizedDrive, width: u16) -> String {
let percentage = if drive.total_bytes > 0 && drive.used_bytes <= drive.total_bytes {
format_pct((drive.used_bytes as f64 * 100.0 / drive.total_bytes as f64) as f32)
} else {
"—".to_string()
};
let values = format!(
"{} / {} {percentage}",
format_bytes(drive.used_bytes),
format_bytes(drive.total_bytes)
);
let width = usize::from(width);
let value_width = unicode_width::UnicodeWidthStr::width(values.as_str());
if width > value_width + 3 {
let name_width = width - value_width - 3;
format!(" {} {values}", truncate_width(&drive.name, name_width))
} else if width > percentage.len() + 3 {
let name_width = width - percentage.len() - 3;
format!(
" {} {percentage}",
truncate_width(&drive.name, name_width)
)
} else {
format!(" {}", truncate_width(&drive.name, width.saturating_sub(2)))
}
}
pub(crate) fn truncate_width(s: &str, max_width: usize) -> String {
use unicode_width::UnicodeWidthChar;
let mut width = 0;
let mut end = 0;
for (index, ch) in s.char_indices() {
let char_width = ch.width().unwrap_or(0);
if width + char_width > max_width {
break;
}
width += char_width;
end = index + ch.len_utf8();
}
if end == s.len() {
s.to_string()
} else if max_width > 0 && width < max_width {
format!("{}…", &s[..end])
} else {
s[..end].to_string()
}
}