progress_streams/
lib.rs

1//! Provide progress callbacks for types which implement `io::Read` or `io::Write`.
2//! 
3//! ## Examples
4//! 
5//! ### Reader
6//! 
7//! ```rust,no_run
8//! extern crate progress_streams;
9//! 
10//! use progress_streams::ProgressReader;
11//! use std::fs::File;
12//! use std::io::Read;
13//! use std::sync::Arc;
14//! use std::sync::atomic::{AtomicUsize, Ordering};
15//! use std::thread;
16//! use std::time::Duration;
17//! 
18//! fn main() {
19//!     let total = Arc::new(AtomicUsize::new(0));
20//!     let mut file = File::open("/dev/urandom").unwrap();
21//!     let mut reader = ProgressReader::new(&mut file, |progress: usize| {
22//!         total.fetch_add(progress, Ordering::SeqCst);
23//!     });
24//! 
25//!     {
26//!         let total = total.clone();
27//!         thread::spawn(move || {
28//!             loop {
29//!                 println!("Read {} KiB", total.load(Ordering::SeqCst) / 1024);
30//!                 thread::sleep(Duration::from_millis(16));
31//!             }
32//!         });
33//!     }
34//! 
35//!     let mut buffer = [0u8; 8192];
36//!     while total.load(Ordering::SeqCst) < 100 * 1024 * 1024 {
37//!         reader.read(&mut buffer).unwrap();
38//!     }
39//! }
40//! ```
41//! 
42//! ### Writer
43//! 
44//! ```rust,no_run
45//! extern crate progress_streams;
46//! 
47//! use progress_streams::ProgressWriter;
48//! use std::io::{Cursor, Write};
49//! use std::sync::Arc;
50//! use std::sync::atomic::{AtomicUsize, Ordering};
51//! use std::thread;
52//! use std::time::Duration;
53//! 
54//! fn main() {
55//!     let total = Arc::new(AtomicUsize::new(0));
56//!     let mut file = Cursor::new(Vec::new());
57//!     let mut writer = ProgressWriter::new(&mut file, |progress: usize| {
58//!         total.fetch_add(progress, Ordering::SeqCst);
59//!     });
60//! 
61//!     {
62//!         let total = total.clone();
63//!         thread::spawn(move || {
64//!             loop {
65//!                 println!("Written {} Kib", total.load(Ordering::SeqCst) / 1024);
66//!                 thread::sleep(Duration::from_millis(16));
67//!             }
68//!         });
69//!     }
70//! 
71//!     let buffer = [0u8; 8192];
72//!     while total.load(Ordering::SeqCst) < 1000 * 1024 * 1024 {
73//!         writer.write(&buffer).unwrap();
74//!     }
75//! }
76//! ```
77
78use std::io::{self, Read, Write};
79
80/// Callback-based progress-monitoring writer.
81pub struct ProgressWriter<W: Write, C: FnMut(usize)> {
82    writer: W,
83    callback: C
84}
85
86impl<W: Write, C: FnMut(usize)> ProgressWriter<W, C> {
87    pub fn new(writer: W, callback: C) -> Self {
88        Self { writer, callback }
89    }
90
91    pub fn into_inner(self) -> W {
92        self.writer
93    }
94}
95
96impl<W: Write, C: FnMut(usize)> Write for ProgressWriter<W, C> {
97    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
98        let written = self.writer.write(buf)?;
99        (self.callback)(written);
100        Ok(written)
101    }
102
103    fn flush(&mut self) -> io::Result<()> {
104        self.writer.flush()
105    }
106}
107
108/// Callback-based progress-monitoring reader.
109pub struct ProgressReader<R: Read, C: FnMut(usize)> {
110    reader: R,
111    callback: C
112}
113
114impl<R: Read, C: FnMut(usize)> ProgressReader<R, C> {
115    pub fn new(reader: R, callback: C) -> Self {
116        Self { reader, callback }
117    }
118
119    pub fn into_inner(self) -> R {
120        self.reader
121    }
122}
123
124impl<R: Read, C: FnMut(usize)> Read for ProgressReader<R, C> {
125    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
126        let read = self.reader.read(buf)?;
127        (self.callback)(read);
128        Ok(read)
129    }
130}