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}