remozipsy 0.2.0

Remote Zip Sync - sync remote zip to local fs
Documentation
use indicatif::{MultiProgress, ProgressBar, ProgressState, ProgressStyle};
use remozipsy::{Error, Progress};
use std::fmt::{Debug, Write};

pub(crate) struct Bar {
    mp: MultiProgress,
    evaluating: Option<ProgressBar>,
    download_bar: ProgressBar,
    unzip_bar: ProgressBar,
    delete_bar: ProgressBar,
}

impl Default for Bar {
    fn default() -> Self {
        let sty_download = ProgressStyle::with_template(
            "{msg:<8}: [{elapsed_precise}]  [{wide_bar:.cyan/blue}]  {bytes}/{total_bytes}  ({eta})",
        )
        .unwrap()
        .with_key("eta", |state: &ProgressState, w: &mut dyn Write| {
            write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()
        })
        .progress_chars("##-");

        let sty = ProgressStyle::with_template("[{elapsed_precise}] {wide_bar:.cyan/blue} {msg}")
            .unwrap()
            .progress_chars("##-");

        let mp = MultiProgress::new();

        let evaluating = mp.add(ProgressBar::new(1));
        evaluating.set_style(sty.clone());
        evaluating.set_message("evaluating");
        evaluating.tick();
        let evaluating = Some(evaluating);

        //evaluating.set_prefix(format!("[{}/?]", 1));
        let download_bar = mp.add(ProgressBar::no_length());
        download_bar.set_style(sty_download.clone());
        download_bar.set_message("download");
        let unzip_bar = mp.add(ProgressBar::no_length());
        unzip_bar.set_style(sty_download.clone());
        unzip_bar.set_message("unzip");
        let delete_bar = mp.add(ProgressBar::no_length());
        delete_bar.set_style(sty_download.clone());
        delete_bar.set_message("delete");

        Self {
            mp,
            evaluating,
            download_bar,
            unzip_bar,
            delete_bar,
        }
    }
}

impl Bar {
    fn finish_evaluating(&mut self) {
        if let Some(bar) = self.evaluating.take() {
            bar.tick();
            bar.set_message("done");
            bar.finish();
        }
    }

    pub fn display<RE: Debug, FE: Debug>(&mut self, progress: Progress<RE, FE>) -> Result<(), Error<RE, FE>> {
        match progress {
            Progress::Incomplete {
                download,
                unzip,
                delete,
            } => {
                self.finish_evaluating();

                self.download_bar.set_length(download.total_bytes());
                self.download_bar.set_position(download.processed_bytes());
                if download.is_finished() {
                    self.download_bar.finish();
                }

                self.unzip_bar.set_length(unzip.total_bytes());
                self.unzip_bar.set_position(unzip.processed_bytes());
                if unzip.is_finished() {
                    self.unzip_bar.finish();
                }

                self.delete_bar.set_length(delete.total_bytes());
                self.delete_bar.set_position(delete.processed_bytes());
                if delete.is_finished() {
                    self.delete_bar.finish();
                }
            },
            Progress::Successful => {},
            Progress::Errored(e) => return Err(e),
        };
        Ok(())
    }

    pub fn cleanup(mut self) {
        if let Some(bar) = self.evaluating.take() {
            bar.finish()
        };
        drop(self.download_bar);
        drop(self.unzip_bar);
        drop(self.delete_bar);
        drop(self.mp);
    }
}

// We don't wanna get bad code coverage because of this part
#[cfg(test)]
mod tests {
    use super::*;
    use remozipsy::{Error, Progress};

    #[test]
    fn test_evaluating_finish() {
        let mut bar = Bar::default();
        bar.finish_evaluating();
        assert!(bar.evaluating.is_none());
    }

    #[test]
    fn verify_bar_doesnt_crash() { let _bar = Bar::default(); }

    #[test]
    fn verify_display_doesnt_crash() {
        let mut bar = Bar::default();

        bar.display(Progress::<(), ()>::Successful).unwrap();
        bar.display(Progress::<(), ()>::Errored(Error::JoinError)).unwrap_err();
    }
}