blockset-lib 0.7.0

BLOCKSET internal library
Documentation
use std::io::{self, Write};

use io_trait::Io;

use crate::uint::u64::div_rem;

pub struct StatusLine<'a, T: Io> {
    io: &'a T,
    prior: usize,
    start_time: T::Instant,
    prior_elapsed: f64,
}

pub fn mb(b: u64) -> String {
    (b / 1_000_000).to_string() + " MB"
}

fn time(s: u64) -> String {
    let (h, s) = div_rem(s, 3600);
    let (m, s) = div_rem(s, 60);
    format!("{}:{:02}:{:02}", h, m, s)
}

impl<'a, T: Io> StatusLine<'a, T> {
    pub fn new(io: &'a T) -> Self {
        Self {
            io,
            prior: 0,
            start_time: io.now(),
            prior_elapsed: -1.0,
        }
    }
    fn set(&mut self, s: &str) -> io::Result<()> {
        let mut vec = Vec::default();
        vec.resize(self.prior, 8);
        vec.extend_from_slice(s.as_bytes());
        if s.len() < self.prior {
            let len = self.prior - s.len();
            vec.resize(self.prior * 2, 0x20);
            vec.resize(vec.len() + len, 8);
        }
        self.io.stdout().write_all(&vec)?;
        self.prior = s.len();
        Ok(())
    }
    pub fn set_progress(&mut self, s: &str, p: f64) -> io::Result<()> {
        if p == 0.0 {
            return Ok(());
        }
        let percent = (p * 100.0) as u8;
        let current = self.io.now();
        let elapsed = (current - self.start_time.clone()).as_secs_f64();
        if elapsed - self.prior_elapsed < 0.01 {
            return Ok(());
        }
        self.prior_elapsed = elapsed;
        let left = elapsed * (1.0 - p) / p;
        let r = s.to_owned() + &percent.to_string() + "%. Time left: " + &time(left as u64) + ".";
        self.set(&r)
    }
}
impl<'a, T: Io> Drop for StatusLine<'a, T> {
    fn drop(&mut self) {
        let _ = self.set("");
    }
}