use indexmap::IndexMap;
use crate::net_stats::get_device_string_to_name_map;
#[macro_export]
macro_rules! test_debug {
($($arg:tt)*) => {{
if std::env::var("RUST_TEST").is_ok() {
println!($($arg)*);
}
}};
}
pub fn filter_zero_counters(
stats: &IndexMap<String, (u64, u64)>,
interfaces: &[String],
) -> Vec<String> {
interfaces
.iter()
.filter(|iface| {
if let Some(&(rx, tx)) = stats.get(*iface) {
rx != 0 || tx != 0
} else {
false
}
})
.cloned()
.collect()
}
pub fn shorten_name(name: &str) -> String {
if name.len() > 16 {
let start = name.find('\\').map(|i| i + 1).unwrap_or(0);
let name = &name[start..];
if let Some(start_idx) = name.find("TCPIP_{") {
let prefix_len = start_idx + 11; if prefix_len < name.len() {
let suffix_start = name.len().saturating_sub(5);
let prefix = &name[start_idx..prefix_len];
let suffix = &name[suffix_start..];
return format!("{}..{}", prefix, suffix);
}
}
if name.len() > 13 {
return format!("{}...", &name[..13]);
}
}
name.to_string()
}
pub fn print_headers(
interfaces: &[String],
writer: &mut dyn std::io::Write,
hide_zero_counters: bool,
stats: &IndexMap<String, (u64, u64)>,
) -> std::io::Result<()> {
let interfaces = if hide_zero_counters {
filter_zero_counters(stats, interfaces)
} else {
interfaces.to_vec()
};
if interfaces.is_empty() {
return Ok(());
}
let width = 18; for (i, interface) in interfaces.iter().enumerate() {
let short_interface = shorten_name(interface);
let padded_name = format!("{:^width$}", short_interface, width = width);
write!(writer, "{}", padded_name)?;
if i < interfaces.len() - 1 {
write!(writer, " ")?; }
}
writeln!(writer)?;
for (i, _) in interfaces.iter().enumerate() {
write!(writer, "{:>8} {:>8}", "KB/s in", "KB/s out")?;
if i < interfaces.len() - 1 {
write!(writer, " ")?; }
}
writeln!(writer)?;
Ok(())
}
pub fn print_stats(
previous: &IndexMap<String, (u64, u64)>,
current: &IndexMap<String, (u64, u64)>,
interfaces: &[String],
writer: &mut dyn std::io::Write,
hide_zero_counters: bool,
) -> std::io::Result<()> {
let interfaces = if hide_zero_counters {
filter_zero_counters(current, interfaces)
} else {
interfaces.to_vec()
};
for (i, interface) in interfaces.iter().enumerate() {
if let (Some(&(prev_rx, prev_tx)), Some(&(cur_rx, cur_tx))) =
(previous.get(interface), current.get(interface))
{
let rx_kbps = (cur_rx.saturating_sub(prev_rx)) as f64 / 1024.0;
let tx_kbps = (cur_tx.saturating_sub(prev_tx)) as f64 / 1024.0;
write!(writer, "{:>8.2} {:>8.2}", rx_kbps, tx_kbps)?;
if i < interfaces.len() - 1 {
write!(writer, " ")?; }
}
}
writeln!(writer)?;
Ok(())
}
pub fn print_net_devices(stats: &IndexMap<String, (u64, u64)>) {
let adapter_name_map = get_device_string_to_name_map();
if adapter_name_map.len() > 0 {
println!("{} adapters:", adapter_name_map.len());
for guid in adapter_name_map.keys() {
if let Some(friendly_name) = adapter_name_map.get(guid) {
println!("{} {}", guid, friendly_name);
}
}
}
println!("{} interfaces:", stats.len());
for iface in stats.keys() {
match adapter_name_map.get(iface) {
Some(adapter_name) => println!("{} ({})", iface, adapter_name),
None => println!("{}", iface),
}
}
}