read_write_pipe/lib.rs
1use std::io::{ErrorKind, Read, Result, Write};
2
3/// A trait for objects implementing [`Write`], to write all content from a [`Read`] object.
4///
5/// This trait adds one method to the writers implementing it.
6/// * `write_reader`
7/// This method allows to read a whole reader object into the writer.
8/// There is no garantee about the state of both reader and writer in case of an error.
9/// ```
10/// use std::io;
11/// use read_write_pipe::*;
12/// let _ = io::stdout().write_reader(io::stdin()).unwrap();
13/// ```
14///
15/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
16/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Read.html
17pub trait ReadWritePipe: Write {
18 fn write_reader<R: Read>(&mut self, mut r: R) -> Result<usize> {
19 let ret;
20 let mut bytes_written = 0;
21 let mut buffer = [0; 1024];
22
23 loop {
24 match r.read(&mut buffer[..]) {
25 Ok(0) => {
26 ret = Ok(bytes_written);
27 break;
28 }
29 Ok(n) => {
30 self.write_all(&buffer[0..n])?;
31 bytes_written += n;
32 }
33 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
34 Err(e) => {
35 ret = Err(e);
36 break;
37 }
38 }
39 }
40 ret
41 }
42}
43
44impl<W: Write> ReadWritePipe for W {}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn writes_all_bytes_from_reader_into_writer() {
52 let reader = b"a small little text";
53 let mut writer: Vec<u8> = Vec::new();
54 let size = writer.write_reader(reader as &[u8]).unwrap();
55 assert_eq!(size, 19);
56 let mut expected_result: Vec<u8> = Vec::new();
57 expected_result.write_all(b"a small little text").unwrap();
58 assert_eq!(writer, expected_result);
59 }
60}