use irontide_session::TorrentState;
pub fn format_size(bytes: u64) -> String {
const KIB: u64 = 1024;
const MIB: u64 = 1024 * KIB;
const GIB: u64 = 1024 * MIB;
if bytes >= GIB {
format!("{:.2} 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_rate(bytes_per_sec: u64) -> String {
const KIB: u64 = 1024;
const MIB: u64 = 1024 * KIB;
if bytes_per_sec >= MIB {
format!("{:.1} MB/s", bytes_per_sec as f64 / MIB as f64)
} else if bytes_per_sec >= KIB {
format!("{:.1} KB/s", bytes_per_sec as f64 / KIB as f64)
} else {
format!("{bytes_per_sec} B/s")
}
}
pub fn format_state(state: &TorrentState, user_seed_mode: bool) -> &'static str {
if user_seed_mode && matches!(state, TorrentState::Downloading) {
return "seed only";
}
match state {
TorrentState::FetchingMetadata => "fetching metadata",
TorrentState::Checking => "checking",
TorrentState::Downloading => "downloading",
TorrentState::Complete => "complete",
TorrentState::Seeding => "seeding",
TorrentState::Paused => "paused",
TorrentState::Stopped => "stopped",
TorrentState::Sharing => "sharing",
}
}
pub fn format_ratio(uploaded: u64, downloaded: u64) -> String {
if downloaded == 0 && uploaded > 0 {
return "\u{221e}".to_string(); }
if downloaded == 0 {
return "0.00".to_string();
}
format!("{:.2}", uploaded as f64 / downloaded as f64)
}
pub fn format_eta(remaining_bytes: u64, rate_bps: u64) -> String {
if rate_bps == 0 {
return "\u{2014}".to_string(); }
let secs = remaining_bytes / rate_bps;
if secs >= 86400 {
let days = secs / 86400;
let hours = (secs % 86400) / 3600;
format!("{days}d {hours}h")
} else if secs >= 3600 {
let hours = secs / 3600;
let mins = (secs % 3600) / 60;
format!("{hours}h {mins}m")
} else if secs >= 60 {
let mins = secs / 60;
let s = secs % 60;
format!("{mins}m {s}s")
} else {
format!("{secs}s")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_format_size_boundaries() {
assert_eq!(format_size(0), "0 B");
assert_eq!(format_size(512), "512 B");
assert_eq!(format_size(1024), "1.0 KiB");
assert_eq!(format_size(512 * 1024), "512.0 KiB");
assert_eq!(format_size(1_048_576), "1.0 MiB");
assert_eq!(format_size(512 * 1_048_576), "512.0 MiB");
assert_eq!(format_size(1_073_741_824), "1.00 GiB");
assert_eq!(format_size(512 * 1_073_741_824), "512.00 GiB");
}
#[test]
fn test_format_rate_boundaries() {
assert_eq!(format_rate(0), "0 B/s");
assert_eq!(format_rate(512), "512 B/s");
assert_eq!(format_rate(1024), "1.0 KB/s");
assert_eq!(format_rate(512 * 1024), "512.0 KB/s");
assert_eq!(format_rate(1_048_576), "1.0 MB/s");
assert_eq!(format_rate(1_073_741_824), "1024.0 MB/s");
}
#[test]
fn test_format_state_all_variants() {
assert_eq!(
format_state(&TorrentState::FetchingMetadata, false),
"fetching metadata"
);
assert_eq!(format_state(&TorrentState::Checking, false), "checking");
assert_eq!(
format_state(&TorrentState::Downloading, false),
"downloading"
);
assert_eq!(format_state(&TorrentState::Complete, false), "complete");
assert_eq!(format_state(&TorrentState::Seeding, false), "seeding");
assert_eq!(format_state(&TorrentState::Paused, false), "paused");
assert_eq!(format_state(&TorrentState::Stopped, false), "stopped");
assert_eq!(format_state(&TorrentState::Sharing, false), "sharing");
assert_eq!(
format_state(&TorrentState::Downloading, true),
"seed only"
);
assert_eq!(format_state(&TorrentState::Seeding, true), "seeding");
assert_eq!(format_state(&TorrentState::Paused, true), "paused");
assert_eq!(format_state(&TorrentState::Complete, true), "complete");
assert_eq!(format_state(&TorrentState::Sharing, true), "sharing");
assert_eq!(format_state(&TorrentState::Stopped, true), "stopped");
}
#[test]
fn test_format_ratio() {
assert_eq!(format_ratio(0, 0), "0.00");
assert_eq!(format_ratio(500, 0), "\u{221e}");
assert_eq!(format_ratio(150, 100), "1.50");
assert_eq!(format_ratio(1000, 1000), "1.00");
assert_eq!(format_ratio(1_000_000, 1_000), "1000.00");
assert_eq!(format_ratio(50, 100), "0.50");
}
#[test]
fn test_format_eta() {
assert_eq!(format_eta(0, 1), "0s");
assert_eq!(format_eta(1_000_000, 0), "\u{2014}");
assert_eq!(format_eta(30, 1), "30s");
assert_eq!(format_eta(45 * 60 + 12, 1), "45m 12s");
assert_eq!(format_eta(2 * 3600 + 15 * 60, 1), "2h 15m");
assert_eq!(format_eta(2 * 86400 + 15 * 3600, 1), "2d 15h");
assert_eq!(format_eta(100 * 1_048_576, 1_048_576), "1m 40s");
}
}