]>
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 | /// ``` | |
3157f602 | 81 | /// use std::io::{self, Read}; |
c1a9b12d | 82 | /// |
c1a9b12d | 83 | /// let mut buffer = String::new(); |
3157f602 XL |
84 | /// io::empty().read_to_string(&mut buffer).unwrap(); |
85 | /// assert!(buffer.is_empty()); | |
c1a9b12d | 86 | /// ``` |
c34b1796 | 87 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 88 | pub fn empty() -> Empty { Empty { _priv: () } } |
1a4d82fc | 89 | |
c34b1796 | 90 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
91 | impl Read for Empty { |
92 | fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } | |
1a4d82fc | 93 | } |
c34b1796 AL |
94 | #[stable(feature = "rust1", since = "1.0.0")] |
95 | impl BufRead for Empty { | |
96 | fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } | |
97 | fn consume(&mut self, _n: usize) {} | |
98 | } | |
1a4d82fc | 99 | |
c1a9b12d SL |
100 | /// A reader which yields one byte over and over and over and over and over and... |
101 | /// | |
102 | /// This struct is generally created by calling [`repeat()`][repeat]. Please | |
103 | /// see the documentation of `repeat()` for more details. | |
104 | /// | |
105 | /// [repeat]: fn.repeat.html | |
c34b1796 | 106 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 107 | pub struct Repeat { byte: u8 } |
1a4d82fc | 108 | |
85aaf69f SL |
109 | /// Creates an instance of a reader that infinitely repeats one byte. |
110 | /// | |
111 | /// All reads from this reader will succeed by filling the specified buffer with | |
112 | /// the given byte. | |
3157f602 XL |
113 | /// |
114 | /// # Examples | |
115 | /// | |
116 | /// ``` | |
117 | /// use std::io::{self, Read}; | |
118 | /// | |
119 | /// let mut buffer = [0; 3]; | |
120 | /// io::repeat(0b101).read_exact(&mut buffer).unwrap(); | |
121 | /// assert_eq!(buffer, [0b101, 0b101, 0b101]); | |
122 | /// ``` | |
c34b1796 | 123 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
124 | pub fn repeat(byte: u8) -> Repeat { Repeat { byte: byte } } |
125 | ||
c34b1796 | 126 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
127 | impl Read for Repeat { |
128 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
62682a34 | 129 | for slot in &mut *buf { |
85aaf69f | 130 | *slot = self.byte; |
1a4d82fc | 131 | } |
85aaf69f | 132 | Ok(buf.len()) |
1a4d82fc | 133 | } |
85aaf69f | 134 | } |
1a4d82fc | 135 | |
85aaf69f | 136 | /// A writer which will move data into the void. |
c1a9b12d SL |
137 | /// |
138 | /// This struct is generally created by calling [`sink()`][sink]. Please | |
139 | /// see the documentation of `sink()` for more details. | |
140 | /// | |
141 | /// [sink]: fn.sink.html | |
c34b1796 | 142 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 143 | pub struct Sink { _priv: () } |
1a4d82fc | 144 | |
85aaf69f SL |
145 | /// Creates an instance of a writer which will successfully consume all data. |
146 | /// | |
147 | /// All calls to `write` on the returned instance will return `Ok(buf.len())` | |
148 | /// and the contents of the buffer will not be inspected. | |
3157f602 XL |
149 | /// |
150 | /// # Examples | |
151 | /// | |
152 | /// ```rust | |
153 | /// use std::io::{self, Write}; | |
154 | /// | |
5bcae85e SL |
155 | /// let buffer = vec![1, 2, 3, 5, 8]; |
156 | /// let num_bytes = io::sink().write(&buffer).unwrap(); | |
3157f602 XL |
157 | /// assert_eq!(num_bytes, 5); |
158 | /// ``` | |
c34b1796 | 159 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f | 160 | pub fn sink() -> Sink { Sink { _priv: () } } |
1a4d82fc | 161 | |
c34b1796 | 162 | #[stable(feature = "rust1", since = "1.0.0")] |
85aaf69f SL |
163 | impl Write for Sink { |
164 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } | |
165 | fn flush(&mut self) -> io::Result<()> { Ok(()) } | |
166 | } | |
1a4d82fc | 167 | |
85aaf69f | 168 | #[cfg(test)] |
d9579d0f | 169 | mod tests { |
85aaf69f | 170 | use io::prelude::*; |
e9174d1e SL |
171 | use io::{copy, sink, empty, repeat}; |
172 | ||
173 | #[test] | |
174 | fn copy_copies() { | |
175 | let mut r = repeat(0).take(4); | |
176 | let mut w = sink(); | |
177 | assert_eq!(copy(&mut r, &mut w).unwrap(), 4); | |
178 | ||
179 | let mut r = repeat(0).take(1 << 17); | |
180 | assert_eq!(copy(&mut r as &mut Read, &mut w as &mut Write).unwrap(), 1 << 17); | |
181 | } | |
1a4d82fc JJ |
182 | |
183 | #[test] | |
85aaf69f SL |
184 | fn sink_sinks() { |
185 | let mut s = sink(); | |
c34b1796 AL |
186 | assert_eq!(s.write(&[]).unwrap(), 0); |
187 | assert_eq!(s.write(&[0]).unwrap(), 1); | |
188 | assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); | |
189 | assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); | |
1a4d82fc JJ |
190 | } |
191 | ||
192 | #[test] | |
85aaf69f SL |
193 | fn empty_reads() { |
194 | let mut e = empty(); | |
c34b1796 AL |
195 | assert_eq!(e.read(&mut []).unwrap(), 0); |
196 | assert_eq!(e.read(&mut [0]).unwrap(), 0); | |
197 | assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); | |
198 | assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); | |
1a4d82fc JJ |
199 | } |
200 | ||
201 | #[test] | |
85aaf69f SL |
202 | fn repeat_repeats() { |
203 | let mut r = repeat(4); | |
204 | let mut b = [0; 1024]; | |
c34b1796 | 205 | assert_eq!(r.read(&mut b).unwrap(), 1024); |
85aaf69f | 206 | assert!(b.iter().all(|b| *b == 4)); |
1a4d82fc JJ |
207 | } |
208 | ||
209 | #[test] | |
85aaf69f SL |
210 | fn take_some_bytes() { |
211 | assert_eq!(repeat(4).take(100).bytes().count(), 100); | |
c34b1796 | 212 | assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4); |
85aaf69f | 213 | assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20); |
1a4d82fc | 214 | } |
1a4d82fc | 215 | } |