hf_hub_simple_progress/
lib.rs#![cfg_attr(feature = "async-closure", feature(async_fn_traits, unboxed_closures))]
#![doc = include_str!("../README.md")]
use serde::{Deserialize, Serialize};
use std::time::{Duration, Instant};
#[cfg(feature = "sync")]
pub mod sync;
#[cfg(feature = "async-closure")]
pub mod async_closure;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgressEvent {
pub url: String,
pub percentage: f32,
pub elapsed_time: Duration,
pub remaining_time: Duration,
}
#[derive(Debug, Clone)]
struct DownloadState {
start_time: Instant,
len: usize,
offset: usize,
url: String,
}
impl DownloadState {
fn new(len: usize, url: &str) -> DownloadState {
DownloadState {
start_time: Instant::now(),
len,
offset: 0,
url: url.to_string(),
}
}
fn update(&mut self, delta: usize) -> Option<ProgressEvent> {
if delta == 0 {
return None;
}
self.offset += delta;
let elapsed_time = Instant::now() - self.start_time;
let progress = self.offset as f32 / self.len as f32;
let progress_100 = progress * 100.;
let remaining_percentage = 100. - progress_100;
let duration_unit = elapsed_time
/ if progress_100 as u32 == 0 {
1
} else {
progress_100 as u32
};
let remaining_time = duration_unit * remaining_percentage as u32;
let event = ProgressEvent {
url: self.url.clone(),
percentage: progress,
elapsed_time,
remaining_time,
};
Some(event)
}
}
#[cfg(test)]
mod tests {
use crate::DownloadState;
use std::thread::sleep;
use std::time::Duration;
#[test]
fn it_works() {
let mut state = DownloadState::new(10, "https://www.rust-lang.org");
assert!(state.update(0).is_none());
sleep(Duration::from_secs(1));
let mid_update = state.update(5).unwrap();
assert_eq!(0.5, mid_update.percentage);
assert!(mid_update.elapsed_time.as_secs_f32() > 1.);
assert!(mid_update.remaining_time.as_secs_f32() > 1.);
let end_update = state.update(5).unwrap();
assert_eq!(1., end_update.percentage);
assert_eq!(0., end_update.remaining_time.as_secs_f32());
}
}