remozipsy 0.0.1

zip implementation independent structs and helpers
Documentation
use core::time::Duration;
use std::time::Instant;

#[derive(Debug, Clone)]
pub struct ProgressDetails {
    total_bytes: u64,
    processed_bytes: u64,
    last_rate_check: Instant,
    processed_since_last_check: u64,
    bytes_per_sec: u64,
}

impl ProgressDetails {
    pub fn new(total_bytes: u64) -> Self {
        Self {
            total_bytes,
            processed_bytes: 0,
            last_rate_check: Instant::now(),
            processed_since_last_check: 0,
            bytes_per_sec: 0,
        }
    }

    pub fn add_chunk(&mut self, data: u64) {
        self.processed_bytes += data;
        self.processed_since_last_check += data;

        if self.processed_bytes > self.total_bytes {
            let process = &self;
            tracing::warn!(
                ?process,
                "Processed Bytes is larger than Total Bytes, something seems off"
            );
        }

        let current_time = Instant::now();
        let since_last_check = current_time - self.last_rate_check;
        let since_last_check_f32 = since_last_check.as_secs_f32();
        if since_last_check >= Duration::from_millis(500) || (since_last_check_f32 > 0.0 && self.bytes_per_sec == 0) {
            let bytes_per_sec = (self.processed_since_last_check as f32 / since_last_check_f32) as u64;
            self.processed_since_last_check = 0;
            self.last_rate_check = current_time;
            if self.bytes_per_sec == 0 {
                self.bytes_per_sec = bytes_per_sec;
            } else {
                self.bytes_per_sec = (self.bytes_per_sec * 3 + bytes_per_sec) / 4;
            }
        }
    }

    pub fn total_bytes(&self) -> u64 { self.total_bytes }

    pub fn processed_bytes(&self) -> u64 { self.processed_bytes }

    pub fn is_finished(&self) -> bool { self.processed_bytes >= self.total_bytes }

    pub fn bytes_per_sec(&self) -> u64 { self.bytes_per_sec }

    pub fn percent_complete(&self) -> u64 { self.processed_bytes * 100 / self.total_bytes }

    pub fn time_remaining(&self) -> Duration {
        Duration::from_secs_f32(
            (self.total_bytes.saturating_sub(self.processed_bytes)) as f32 / self.bytes_per_sec.max(1) as f32,
        )
    }
}