]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
85aaf69f | 11 | #![allow(missing_copy_implementations)] |
1a4d82fc | 12 | |
c34b1796 | 13 | use io::{self, Read, Write, ErrorKind, BufRead}; |
1a4d82fc | 14 | |
85aaf69f | 15 | /// Copies the entire contents of a reader into a writer. |
1a4d82fc | 16 | /// |
62682a34 SL |
17 | /// This function will continuously read data from `reader` and then |
18 | /// write it into `writer` in a streaming fashion until `reader` | |
19 | /// returns EOF. | |
85aaf69f | 20 | /// |
62682a34 SL |
21 | /// On success, the total number of bytes that were copied from |
22 | /// `reader` to `writer` is returned. | |
85aaf69f SL |
23 | /// |
24 | /// # Errors | |
25 | /// | |
26 | /// This function will return an error immediately if any call to `read` or | |
27 | /// `write` returns an error. All instances of `ErrorKind::Interrupted` are | |
28 | /// handled by this function and the underlying operation is retried. | |
c1a9b12d SL |
29 | /// |
30 | /// # Examples | |
31 | /// | |
32 | /// ``` | |
33 | /// use std::io; | |
34 | /// | |
35 | /// # fn foo() -> io::Result<()> { | |
36 | /// let mut reader: &[u8] = b"hello"; | |
37 | /// let mut writer: Vec<u8> = vec![]; | |
38 | /// | |
39 | /// try!(io::copy(&mut reader, &mut writer)); | |
40 | /// | |
41 | /// assert_eq!(reader, &writer[..]); | |
42 | /// # Ok(()) | |
43 | /// # } | |
44 | /// ``` | |
c34b1796 | 45 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e SL |
46 | pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> |
47 | where R: Read, W: Write | |
48 | { | |
1a4d82fc | 49 | let mut buf = [0; super::DEFAULT_BUF_SIZE]; |
85aaf69f | 50 | let mut written = 0; |
1a4d82fc | 51 | loop { |
62682a34 | 52 | let len = match reader.read(&mut buf) { |
85aaf69f | 53 | Ok(0) => return Ok(written), |
1a4d82fc | 54 | Ok(len) => len, |
85aaf69f | 55 | Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, |
1a4d82fc JJ |
56 | Err(e) => return Err(e), |
57 | }; | |
54a0048b | 58 | writer.write_all(&buf[..len])?; |
85aaf69f | 59 | written += len as u64; |
1a4d82fc JJ |
60 | } |
61 | } | |
62 | ||
85aaf69f | 63 | /// A reader which is always at EOF. |
c1a9b12d SL |
64 | /// |
65 | /// This struct is generally created by calling [`empty()`][empty]. Please see | |
66 | /// the documentation of `empty()` for more details. | |
67 | /// | |
68 | /// [empty]: fn.empty.html | |
c34b1796 | 69 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 70 | pub struct Empty { _priv: () } |
1a4d82fc | 71 | |
c1a9b12d | 72 | /// Constructs a new handle to an empty reader. |
85aaf69f SL |
73 | /// |
74 | /// All reads from the returned reader will return `Ok(0)`. | |
c1a9b12d SL |
75 | /// |
76 | /// # Examples | |
77 | /// | |
78 | /// A slightly sad example of not reading anything into a buffer: | |
79 | /// | |
80 | /// ``` | |
81 | /// use std::io; | |
82 | /// use std::io::Read; | |
83 | /// | |
84 | /// # fn foo() -> io::Result<String> { | |
85 | /// let mut buffer = String::new(); | |
86 | /// try!(io::empty().read_to_string(&mut buffer)); | |
87 | /// # Ok(buffer) | |
88 | /// # } | |
89 | /// ``` | |
c34b1796 | 90 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 91 | pub fn empty() -> Empty { Empty { _priv: () } } |
1a4d82fc | 92 | |
c34b1796 | 93 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
94 | impl Read for Empty { |
95 | fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } | |
1a4d82fc | 96 | } |
c34b1796 AL |
97 | #[stable(feature = "rust1", since = "1.0.0")] |
98 | impl BufRead for Empty { | |
99 | fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } | |
100 | fn consume(&mut self, _n: usize) {} | |
101 | } | |
1a4d82fc | 102 | |
c1a9b12d SL |
103 | /// A reader which yields one byte over and over and over and over and over and... |
104 | /// | |
105 | /// This struct is generally created by calling [`repeat()`][repeat]. Please | |
106 | /// see the documentation of `repeat()` for more details. | |
107 | /// | |
108 | /// [repeat]: fn.repeat.html | |
c34b1796 | 109 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 110 | pub struct Repeat { byte: u8 } |
1a4d82fc | 111 | |
85aaf69f SL |
112 | /// Creates an instance of a reader that infinitely repeats one byte. |
113 | /// | |
114 | /// All reads from this reader will succeed by filling the specified buffer with | |
115 | /// the given byte. | |
c34b1796 | 116 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
117 | pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } |
118 | ||
c34b1796 | 119 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
120 | impl Read for Repeat { |
121 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
62682a34 | 122 | for slot in &mut *buf { |
85aaf69f | 123 | *slot = self.byte; |
1a4d82fc | 124 | } |
85aaf69f | 125 | Ok(buf.len()) |
1a4d82fc | 126 | } |
85aaf69f | 127 | } |
1a4d82fc | 128 | |
85aaf69f | 129 | /// A writer which will move data into the void. |
c1a9b12d SL |
130 | /// |
131 | /// This struct is generally created by calling [`sink()`][sink]. Please | |
132 | /// see the documentation of `sink()` for more details. | |
133 | /// | |
134 | /// [sink]: fn.sink.html | |
c34b1796 | 135 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 136 | pub struct Sink { _priv: () } |
1a4d82fc | 137 | |
85aaf69f SL |
138 | /// Creates an instance of a writer which will successfully consume all data. |
139 | /// | |
140 | /// All calls to `write` on the returned instance will return `Ok(buf.len())` | |
141 | /// and the contents of the buffer will not be inspected. | |
c34b1796 | 142 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 143 | pub fn sink() -> Sink { Sink { _priv: () } } |
1a4d82fc | 144 | |
c34b1796 | 145 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
146 | impl Write for Sink { |
147 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } | |
148 | fn flush(&mut self) -> io::Result<()> { Ok(()) } | |
149 | } | |
1a4d82fc | 150 | |
85aaf69f | 151 | #[cfg(test)] |
d9579d0f | 152 | mod tests { |
85aaf69f | 153 | use prelude::v1::*; |
1a4d82fc | 154 | |
85aaf69f | 155 | use io::prelude::*; |
e9174d1e SL |
156 | use io::{copy, sink, empty, repeat}; |
157 | ||
158 | #[test] | |
159 | fn copy_copies() { | |
160 | let mut r = repeat(0).take(4); | |
161 | let mut w = sink(); | |
162 | assert_eq!(copy(&mut r, &mut w).unwrap(), 4); | |
163 | ||
164 | let mut r = repeat(0).take(1 << 17); | |
165 | assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17); | |
166 | } | |
1a4d82fc JJ |
167 | |
168 | #[test] | |
85aaf69f SL |
169 | fn sink_sinks() { |
170 | let mut s = sink(); | |
c34b1796 AL |
171 | assert_eq!(s.write(&[]).unwrap(), 0); |
172 | assert_eq!(s.write(&[0]).unwrap(), 1); | |
173 | assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); | |
174 | assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); | |
1a4d82fc JJ |
175 | } |
176 | ||
177 | #[test] | |
85aaf69f SL |
178 | fn empty_reads() { |
179 | let mut e = empty(); | |
c34b1796 AL |
180 | assert_eq!(e.read(&mut []).unwrap(), 0); |
181 | assert_eq!(e.read(&mut [0]).unwrap(), 0); | |
182 | assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); | |
183 | assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); | |
1a4d82fc JJ |
184 | } |
185 | ||
186 | #[test] | |
85aaf69f SL |
187 | fn repeat_repeats() { |
188 | let mut r = repeat(4); | |
189 | let mut b = [0; 1024]; | |
c34b1796 | 190 | assert_eq!(r.read(&mut b).unwrap(), 1024); |
85aaf69f | 191 | assert!(b.iter().all(|b| *b == 4)); |
1a4d82fc JJ |
192 | } |
193 | ||
194 | #[test] | |
85aaf69f SL |
195 | fn take_some_bytes() { |
196 | assert_eq!(repeat(4).take(100).bytes().count(), 100); | |
c34b1796 | 197 | assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); |
85aaf69f | 198 | assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); |
1a4d82fc | 199 | } |
1a4d82fc | 200 | } |