finalfrontier_utils/
progress.rs

1use std::fs::File;
2use std::io::{self, Read, Seek, SeekFrom};
3
4use indicatif::{ProgressBar, ProgressStyle};
5
6pub struct FileProgress {
7    inner: File,
8    progress: ProgressBar,
9}
10
11/// A progress bar that implements the `Read` trait.
12///
13/// This wrapper of `indicatif`'s `ProgressBar` updates progress based on the
14/// current offset within the file.
15impl FileProgress {
16    pub fn new(file: File) -> io::Result<Self> {
17        let metadata = file.metadata()?;
18        let progress = ProgressBar::new(metadata.len());
19        progress.set_style(
20            ProgressStyle::default_bar()
21                .template("{bar:40} {bytes}/{total_bytes} ETA: {eta_precise}"),
22        );
23
24        Ok(FileProgress {
25            inner: file,
26            progress,
27        })
28    }
29}
30
31impl Read for FileProgress {
32    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
33        let n_read = self.inner.read(buf)?;
34        let pos = self.inner.seek(SeekFrom::Current(0))?;
35        self.progress.set_position(pos);
36        Ok(n_read)
37    }
38}
39
40impl Drop for FileProgress {
41    fn drop(&mut self) {
42        self.progress.finish();
43    }
44}