#[derive(Debug, Clone)]
pub struct Progress {
pub bytes_downloaded: u64,
pub total_bytes: Option<u64>,
pub speed_bps: Option<f64>,
pub eta: Option<std::time::Duration>,
}
impl Progress {
pub fn percent(&self) -> Option<f64> {
match self.total_bytes {
Some(total) if total > 0 => Some((self.bytes_downloaded as f64 / total as f64) * 100.0),
_ => None,
}
}
}
pub type ProgressCallback = std::sync::Arc<dyn Fn(Progress) + Send + Sync>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn percent_computes_ratio() {
let p = Progress {
bytes_downloaded: 25,
total_bytes: Some(100),
speed_bps: None,
eta: None,
};
assert_eq!(p.percent(), Some(25.0));
}
#[test]
fn percent_is_none_without_total() {
let p = Progress {
bytes_downloaded: 25,
total_bytes: None,
speed_bps: None,
eta: None,
};
assert_eq!(p.percent(), None);
}
#[test]
fn percent_is_none_for_zero_total() {
let p = Progress {
bytes_downloaded: 0,
total_bytes: Some(0),
speed_bps: None,
eta: None,
};
assert_eq!(p.percent(), None);
}
}