]>
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 | |
32a655c1 | 13 | use fmt; |
041b39d2 XL |
14 | use io::{self, Read, Initializer, Write, ErrorKind, BufRead}; |
15 | use mem; | |
1a4d82fc | 16 | |
85aaf69f | 17 | /// Copies the entire contents of a reader into a writer. |
1a4d82fc | 18 | /// |
62682a34 SL |
19 | /// This function will continuously read data from `reader` and then |
20 | /// write it into `writer` in a streaming fashion until `reader` | |
21 | /// returns EOF. | |
85aaf69f | 22 | /// |
62682a34 SL |
23 | /// On success, the total number of bytes that were copied from |
24 | /// `reader` to `writer` is returned. | |
85aaf69f SL |
25 | /// |
26 | /// # Errors | |
27 | /// | |
28 | /// This function will return an error immediately if any call to `read` or | |
29 | /// `write` returns an error. All instances of `ErrorKind::Interrupted` are | |
30 | /// handled by this function and the underlying operation is retried. | |
c1a9b12d SL |
31 | /// |
32 | /// # Examples | |
33 | /// | |
34 | /// ``` | |
35 | /// use std::io; | |
36 | /// | |
0531ce1d XL |
37 | /// fn main() -> io::Result<()> { |
38 | /// let mut reader: &[u8] = b"hello"; | |
39 | /// let mut writer: Vec<u8> = vec![]; | |
c1a9b12d | 40 | /// |
0531ce1d | 41 | /// io::copy(&mut reader, &mut writer)?; |
c1a9b12d | 42 | /// |
0531ce1d XL |
43 | /// assert_eq!(&b"hello"[..], &writer[..]); |
44 | /// Ok(()) | |
45 | /// } | |
c1a9b12d | 46 | /// ``` |
c34b1796 | 47 | #[stable(feature = "rust1", since = "1.0.0")] |
e9174d1e SL |
48 | pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> |
49 | where R: Read, W: Write | |
50 | { | |
041b39d2 XL |
51 | let mut buf = unsafe { |
52 | let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized(); | |
53 | reader.initializer().initialize(&mut buf); | |
54 | buf | |
55 | }; | |
56 | ||
85aaf69f | 57 | let mut written = 0; |
1a4d82fc | 58 | loop { |
62682a34 | 59 | let len = match reader.read(&mut buf) { |
85aaf69f | 60 | Ok(0) => return Ok(written), |
1a4d82fc | 61 | Ok(len) => len, |
85aaf69f | 62 | Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, |
1a4d82fc JJ |
63 | Err(e) => return Err(e), |
64 | }; | |
54a0048b | 65 | writer.write_all(&buf[..len])?; |
85aaf69f | 66 | written += len as u64; |
1a4d82fc JJ |
67 | } |
68 | } | |
69 | ||
85aaf69f | 70 | /// A reader which is always at EOF. |
c1a9b12d | 71 | /// |
ea8adc8c XL |
72 | /// This struct is generally created by calling [`empty`]. Please see |
73 | /// the documentation of [`empty()`][`empty`] for more details. | |
c1a9b12d | 74 | /// |
ea8adc8c | 75 | /// [`empty`]: fn.empty.html |
c34b1796 | 76 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 77 | pub struct Empty { _priv: () } |
1a4d82fc | 78 | |
c1a9b12d | 79 | /// Constructs a new handle to an empty reader. |
85aaf69f | 80 | /// |
ea8adc8c XL |
81 | /// All reads from the returned reader will return [`Ok`]`(0)`. |
82 | /// | |
83 | /// [`Ok`]: ../result/enum.Result.html#variant.Ok | |
c1a9b12d SL |
84 | /// |
85 | /// # Examples | |
86 | /// | |
87 | /// A slightly sad example of not reading anything into a buffer: | |
88 | /// | |
89 | /// ``` | |
3157f602 | 90 | /// use std::io::{self, Read}; |
c1a9b12d | 91 | /// |
c1a9b12d | 92 | /// let mut buffer = String::new(); |
3157f602 XL |
93 | /// io::empty().read_to_string(&mut buffer).unwrap(); |
94 | /// assert!(buffer.is_empty()); | |
c1a9b12d | 95 | /// ``` |
c34b1796 | 96 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 97 | pub fn empty() -> Empty { Empty { _priv: () } } |
1a4d82fc | 98 | |
c34b1796 | 99 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 100 | impl Read for Empty { |
041b39d2 | 101 | #[inline] |
85aaf69f | 102 | fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } |
041b39d2 XL |
103 | |
104 | #[inline] | |
105 | unsafe fn initializer(&self) -> Initializer { | |
106 | Initializer::nop() | |
107 | } | |
1a4d82fc | 108 | } |
c34b1796 AL |
109 | #[stable(feature = "rust1", since = "1.0.0")] |
110 | impl BufRead for Empty { | |
041b39d2 | 111 | #[inline] |
c34b1796 | 112 | fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } |
041b39d2 | 113 | #[inline] |
c34b1796 AL |
114 | fn consume(&mut self, _n: usize) {} |
115 | } | |
1a4d82fc | 116 | |
8bb4bdeb | 117 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
118 | impl fmt::Debug for Empty { |
119 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
120 | f.pad("Empty { .. }") | |
121 | } | |
122 | } | |
123 | ||
c1a9b12d SL |
124 | /// A reader which yields one byte over and over and over and over and over and... |
125 | /// | |
cc61c64b | 126 | /// This struct is generally created by calling [`repeat`][repeat]. Please |
c1a9b12d SL |
127 | /// see the documentation of `repeat()` for more details. |
128 | /// | |
129 | /// [repeat]: fn.repeat.html | |
c34b1796 | 130 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 131 | pub struct Repeat { byte: u8 } |
1a4d82fc | 132 | |
85aaf69f SL |
133 | /// Creates an instance of a reader that infinitely repeats one byte. |
134 | /// | |
135 | /// All reads from this reader will succeed by filling the specified buffer with | |
136 | /// the given byte. | |
3157f602 XL |
137 | /// |
138 | /// # Examples | |
139 | /// | |
140 | /// ``` | |
141 | /// use std::io::{self, Read}; | |
142 | /// | |
143 | /// let mut buffer = [0; 3]; | |
144 | /// io::repeat(0b101).read_exact(&mut buffer).unwrap(); | |
145 | /// assert_eq!(buffer, [0b101, 0b101, 0b101]); | |
146 | /// ``` | |
c34b1796 | 147 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
148 | pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } |
149 | ||
c34b1796 | 150 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 151 | impl Read for Repeat { |
041b39d2 | 152 | #[inline] |
85aaf69f | 153 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
62682a34 | 154 | for slot in &mut *buf { |
85aaf69f | 155 | *slot = self.byte; |
1a4d82fc | 156 | } |
85aaf69f | 157 | Ok(buf.len()) |
1a4d82fc | 158 | } |
041b39d2 XL |
159 | |
160 | #[inline] | |
161 | unsafe fn initializer(&self) -> Initializer { | |
162 | Initializer::nop() | |
163 | } | |
85aaf69f | 164 | } |
1a4d82fc | 165 | |
8bb4bdeb | 166 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
167 | impl fmt::Debug for Repeat { |
168 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
169 | f.pad("Repeat { .. }") | |
170 | } | |
171 | } | |
172 | ||
85aaf69f | 173 | /// A writer which will move data into the void. |
c1a9b12d | 174 | /// |
cc61c64b | 175 | /// This struct is generally created by calling [`sink`][sink]. Please |
c1a9b12d SL |
176 | /// see the documentation of `sink()` for more details. |
177 | /// | |
178 | /// [sink]: fn.sink.html | |
c34b1796 | 179 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 180 | pub struct Sink { _priv: () } |
1a4d82fc | 181 | |
85aaf69f SL |
182 | /// Creates an instance of a writer which will successfully consume all data. |
183 | /// | |
184 | /// All calls to `write` on the returned instance will return `Ok(buf.len())` | |
185 | /// and the contents of the buffer will not be inspected. | |
3157f602 XL |
186 | /// |
187 | /// # Examples | |
188 | /// | |
189 | /// ```rust | |
190 | /// use std::io::{self, Write}; | |
191 | /// | |
5bcae85e SL |
192 | /// let buffer = vec![1, 2, 3, 5, 8]; |
193 | /// let num_bytes = io::sink().write(&buffer).unwrap(); | |
3157f602 XL |
194 | /// assert_eq!(num_bytes, 5); |
195 | /// ``` | |
c34b1796 | 196 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 197 | pub fn sink() -> Sink { Sink { _priv: () } } |
1a4d82fc | 198 | |
c34b1796 | 199 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 200 | impl Write for Sink { |
041b39d2 | 201 | #[inline] |
85aaf69f | 202 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } |
041b39d2 | 203 | #[inline] |
85aaf69f SL |
204 | fn flush(&mut self) -> io::Result<()> { Ok(()) } |
205 | } | |
1a4d82fc | 206 | |
8bb4bdeb | 207 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 SL |
208 | impl fmt::Debug for Sink { |
209 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
210 | f.pad("Sink { .. }") | |
211 | } | |
212 | } | |
213 | ||
85aaf69f | 214 | #[cfg(test)] |
d9579d0f | 215 | mod tests { |
85aaf69f | 216 | use io::prelude::*; |
e9174d1e SL |
217 | use io::{copy, sink, empty, repeat}; |
218 | ||
219 | #[test] | |
220 | fn copy_copies() { | |
221 | let mut r = repeat(0).take(4); | |
222 | let mut w = sink(); | |
223 | assert_eq!(copy(&mut r, &mut w).unwrap(), 4); | |
224 | ||
225 | let mut r = repeat(0).take(1 << 17); | |
226 | assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17); | |
227 | } | |
1a4d82fc JJ |
228 | |
229 | #[test] | |
85aaf69f SL |
230 | fn sink_sinks() { |
231 | let mut s = sink(); | |
c34b1796 AL |
232 | assert_eq!(s.write(&[]).unwrap(), 0); |
233 | assert_eq!(s.write(&[0]).unwrap(), 1); | |
234 | assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); | |
235 | assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); | |
1a4d82fc JJ |
236 | } |
237 | ||
238 | #[test] | |
85aaf69f SL |
239 | fn empty_reads() { |
240 | let mut e = empty(); | |
c34b1796 AL |
241 | assert_eq!(e.read(&mut []).unwrap(), 0); |
242 | assert_eq!(e.read(&mut [0]).unwrap(), 0); | |
243 | assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); | |
244 | assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); | |
1a4d82fc JJ |
245 | } |
246 | ||
247 | #[test] | |
85aaf69f SL |
248 | fn repeat_repeats() { |
249 | let mut r = repeat(4); | |
250 | let mut b = [0; 1024]; | |
c34b1796 | 251 | assert_eq!(r.read(&mut b).unwrap(), 1024); |
85aaf69f | 252 | assert!(b.iter().all(|b| *b == 4)); |
1a4d82fc JJ |
253 | } |
254 | ||
255 | #[test] | |
85aaf69f SL |
256 | fn take_some_bytes() { |
257 | assert_eq!(repeat(4).take(100).bytes().count(), 100); | |
c34b1796 | 258 | assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); |
85aaf69f | 259 | assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); |
1a4d82fc | 260 | } |
1a4d82fc | 261 | } |