use std::env;
use std::path::{Path, PathBuf};
use std::time::Duration;
pub fn format_bytes(bytes: u64) -> String {
const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
let mut size = bytes as f64;
let mut unit_index = 0;
while size >= 1024.0 && unit_index < UNITS.len() - 1 {
size /= 1024.0;
unit_index += 1;
}
format!("{:.1} {}", size, UNITS[unit_index])
}
pub fn format_duration(duration: Duration) -> String {
let total_seconds = duration.as_secs();
let days = total_seconds / 86400;
let hours = (total_seconds % 86400) / 3600;
let minutes = (total_seconds % 3600) / 60;
let seconds = total_seconds % 60;
let mut parts = Vec::new();
if days > 0 {
parts.push(format!("{days}d"));
}
if hours > 0 {
parts.push(format!("{hours}h"));
}
if minutes > 0 {
parts.push(format!("{minutes}m"));
}
if seconds > 0 || parts.is_empty() {
parts.push(format!("{seconds}s"));
}
parts.join(" ")
}
pub fn expand_path(path: &Path) -> PathBuf {
let path_str = path.to_string_lossy();
#[cfg(unix)]
if path_str.starts_with("~/")
&& let Ok(home) = env::var("HOME")
{
return PathBuf::from(path_str.replacen("~", &home, 1));
}
#[cfg(windows)]
if path_str.contains("%AppData%") {
if let Ok(app_data) = env::var("APPDATA") {
return PathBuf::from(path_str.replace("%AppData%", &app_data));
}
}
path.to_path_buf()
}