]>
Commit | Line | Data |
---|---|---|
85aaf69f SL |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
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 | // | |
11 | // ignore-lexer-test FIXME #15883 | |
12 | ||
13 | //! Buffering wrappers for I/O traits | |
14 | ||
15 | use cmp; | |
16 | use fmt; | |
17 | use old_io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult}; | |
c34b1796 | 18 | use iter::{Iterator, ExactSizeIterator, repeat}; |
85aaf69f SL |
19 | use ops::Drop; |
20 | use option::Option; | |
21 | use option::Option::{Some, None}; | |
22 | use result::Result::Ok; | |
85aaf69f SL |
23 | use slice; |
24 | use vec::Vec; | |
25 | ||
26 | /// Wraps a Reader and buffers input from it | |
27 | /// | |
28 | /// It can be excessively inefficient to work directly with a `Reader`. For | |
29 | /// example, every call to `read` on `TcpStream` results in a system call. A | |
30 | /// `BufferedReader` performs large, infrequent reads on the underlying | |
31 | /// `Reader` and maintains an in-memory buffer of the results. | |
32 | /// | |
c34b1796 | 33 | /// # Examples |
85aaf69f | 34 | /// |
c34b1796 AL |
35 | /// ``` |
36 | /// # #![feature(old_io, old_path)] | |
37 | /// use std::old_io::*; | |
38 | /// use std::old_path::Path; | |
85aaf69f SL |
39 | /// |
40 | /// let file = File::open(&Path::new("message.txt")); | |
41 | /// let mut reader = BufferedReader::new(file); | |
42 | /// | |
43 | /// let mut buf = [0; 100]; | |
44 | /// match reader.read(&mut buf) { | |
45 | /// Ok(nread) => println!("Read {} bytes", nread), | |
46 | /// Err(e) => println!("error reading: {}", e) | |
47 | /// } | |
48 | /// ``` | |
49 | pub struct BufferedReader<R> { | |
50 | inner: R, | |
51 | buf: Vec<u8>, | |
c34b1796 AL |
52 | pos: usize, |
53 | cap: usize, | |
85aaf69f SL |
54 | } |
55 | ||
56 | #[stable(feature = "rust1", since = "1.0.0")] | |
57 | impl<R> fmt::Debug for BufferedReader<R> where R: fmt::Debug { | |
58 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | |
59 | write!(fmt, "BufferedReader {{ reader: {:?}, buffer: {}/{} }}", | |
60 | self.inner, self.cap - self.pos, self.buf.len()) | |
61 | } | |
62 | } | |
63 | ||
64 | impl<R: Reader> BufferedReader<R> { | |
65 | /// Creates a new `BufferedReader` with the specified buffer capacity | |
c34b1796 | 66 | pub fn with_capacity(cap: usize, inner: R) -> BufferedReader<R> { |
85aaf69f SL |
67 | BufferedReader { |
68 | inner: inner, | |
69 | // We can't use the same trick here as we do for BufferedWriter, | |
70 | // since this memory is visible to the inner Reader. | |
71 | buf: repeat(0).take(cap).collect(), | |
72 | pos: 0, | |
73 | cap: 0, | |
74 | } | |
75 | } | |
76 | ||
77 | /// Creates a new `BufferedReader` with a default buffer capacity | |
78 | pub fn new(inner: R) -> BufferedReader<R> { | |
79 | BufferedReader::with_capacity(DEFAULT_BUF_SIZE, inner) | |
80 | } | |
81 | ||
82 | /// Gets a reference to the underlying reader. | |
83 | pub fn get_ref<'a>(&self) -> &R { &self.inner } | |
84 | ||
85 | /// Gets a mutable reference to the underlying reader. | |
86 | /// | |
87 | /// # Warning | |
88 | /// | |
89 | /// It is inadvisable to directly read from the underlying reader. | |
90 | pub fn get_mut(&mut self) -> &mut R { &mut self.inner } | |
91 | ||
92 | /// Unwraps this `BufferedReader`, returning the underlying reader. | |
93 | /// | |
94 | /// Note that any leftover data in the internal buffer is lost. | |
95 | pub fn into_inner(self) -> R { self.inner } | |
96 | } | |
97 | ||
98 | impl<R: Reader> Buffer for BufferedReader<R> { | |
99 | fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { | |
100 | if self.pos == self.cap { | |
101 | self.cap = try!(self.inner.read(&mut self.buf)); | |
102 | self.pos = 0; | |
103 | } | |
104 | Ok(&self.buf[self.pos..self.cap]) | |
105 | } | |
106 | ||
c34b1796 | 107 | fn consume(&mut self, amt: usize) { |
85aaf69f SL |
108 | self.pos += amt; |
109 | assert!(self.pos <= self.cap); | |
110 | } | |
111 | } | |
112 | ||
113 | impl<R: Reader> Reader for BufferedReader<R> { | |
c34b1796 | 114 | fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { |
85aaf69f SL |
115 | if self.pos == self.cap && buf.len() >= self.buf.len() { |
116 | return self.inner.read(buf); | |
117 | } | |
118 | let nread = { | |
119 | let available = try!(self.fill_buf()); | |
120 | let nread = cmp::min(available.len(), buf.len()); | |
c34b1796 | 121 | slice::bytes::copy_memory(&available[..nread], buf); |
85aaf69f SL |
122 | nread |
123 | }; | |
124 | self.pos += nread; | |
125 | Ok(nread) | |
126 | } | |
127 | } | |
128 | ||
129 | /// Wraps a Writer and buffers output to it | |
130 | /// | |
131 | /// It can be excessively inefficient to work directly with a `Writer`. For | |
132 | /// example, every call to `write` on `TcpStream` results in a system call. A | |
133 | /// `BufferedWriter` keeps an in memory buffer of data and writes it to the | |
134 | /// underlying `Writer` in large, infrequent batches. | |
135 | /// | |
136 | /// This writer will be flushed when it is dropped. | |
137 | /// | |
c34b1796 | 138 | /// # Examples |
85aaf69f | 139 | /// |
c34b1796 AL |
140 | /// ``` |
141 | /// # #![feature(old_io, old_path)] | |
142 | /// use std::old_io::*; | |
143 | /// use std::old_path::Path; | |
85aaf69f SL |
144 | /// |
145 | /// let file = File::create(&Path::new("message.txt")).unwrap(); | |
146 | /// let mut writer = BufferedWriter::new(file); | |
147 | /// | |
148 | /// writer.write_str("hello, world").unwrap(); | |
149 | /// writer.flush().unwrap(); | |
150 | /// ``` | |
c34b1796 | 151 | pub struct BufferedWriter<W: Writer> { |
85aaf69f SL |
152 | inner: Option<W>, |
153 | buf: Vec<u8>, | |
c34b1796 | 154 | pos: usize |
85aaf69f SL |
155 | } |
156 | ||
157 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 158 | impl<W: Writer> fmt::Debug for BufferedWriter<W> where W: fmt::Debug { |
85aaf69f SL |
159 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
160 | write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}", | |
161 | self.inner.as_ref().unwrap(), self.pos, self.buf.len()) | |
162 | } | |
163 | } | |
164 | ||
165 | impl<W: Writer> BufferedWriter<W> { | |
166 | /// Creates a new `BufferedWriter` with the specified buffer capacity | |
c34b1796 | 167 | pub fn with_capacity(cap: usize, inner: W) -> BufferedWriter<W> { |
85aaf69f SL |
168 | // It's *much* faster to create an uninitialized buffer than it is to |
169 | // fill everything in with 0. This buffer is entirely an implementation | |
170 | // detail and is never exposed, so we're safe to not initialize | |
171 | // everything up-front. This allows creation of BufferedWriter instances | |
172 | // to be very cheap (large mallocs are not nearly as expensive as large | |
173 | // callocs). | |
174 | let mut buf = Vec::with_capacity(cap); | |
175 | unsafe { buf.set_len(cap); } | |
176 | BufferedWriter { | |
177 | inner: Some(inner), | |
178 | buf: buf, | |
179 | pos: 0 | |
180 | } | |
181 | } | |
182 | ||
183 | /// Creates a new `BufferedWriter` with a default buffer capacity | |
184 | pub fn new(inner: W) -> BufferedWriter<W> { | |
185 | BufferedWriter::with_capacity(DEFAULT_BUF_SIZE, inner) | |
186 | } | |
187 | ||
188 | fn flush_buf(&mut self) -> IoResult<()> { | |
189 | if self.pos != 0 { | |
190 | let ret = self.inner.as_mut().unwrap().write_all(&self.buf[..self.pos]); | |
191 | self.pos = 0; | |
192 | ret | |
193 | } else { | |
194 | Ok(()) | |
195 | } | |
196 | } | |
197 | ||
198 | /// Gets a reference to the underlying writer. | |
199 | pub fn get_ref(&self) -> &W { self.inner.as_ref().unwrap() } | |
200 | ||
201 | /// Gets a mutable reference to the underlying write. | |
202 | /// | |
203 | /// # Warning | |
204 | /// | |
205 | /// It is inadvisable to directly read from the underlying writer. | |
206 | pub fn get_mut(&mut self) -> &mut W { self.inner.as_mut().unwrap() } | |
207 | ||
208 | /// Unwraps this `BufferedWriter`, returning the underlying writer. | |
209 | /// | |
210 | /// The buffer is flushed before returning the writer. | |
211 | pub fn into_inner(mut self) -> W { | |
212 | // FIXME(#12628): is panicking the right thing to do if flushing panicks? | |
213 | self.flush_buf().unwrap(); | |
214 | self.inner.take().unwrap() | |
215 | } | |
216 | } | |
217 | ||
218 | impl<W: Writer> Writer for BufferedWriter<W> { | |
219 | fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { | |
220 | if self.pos + buf.len() > self.buf.len() { | |
221 | try!(self.flush_buf()); | |
222 | } | |
223 | ||
224 | if buf.len() > self.buf.len() { | |
225 | self.inner.as_mut().unwrap().write_all(buf) | |
226 | } else { | |
227 | let dst = &mut self.buf[self.pos..]; | |
c34b1796 | 228 | slice::bytes::copy_memory(buf, dst); |
85aaf69f SL |
229 | self.pos += buf.len(); |
230 | Ok(()) | |
231 | } | |
232 | } | |
233 | ||
234 | fn flush(&mut self) -> IoResult<()> { | |
235 | self.flush_buf().and_then(|()| self.inner.as_mut().unwrap().flush()) | |
236 | } | |
237 | } | |
238 | ||
239 | #[unsafe_destructor] | |
240 | impl<W: Writer> Drop for BufferedWriter<W> { | |
241 | fn drop(&mut self) { | |
242 | if self.inner.is_some() { | |
243 | // dtors should not panic, so we ignore a panicked flush | |
244 | let _ = self.flush_buf(); | |
245 | } | |
246 | } | |
247 | } | |
248 | ||
249 | /// Wraps a Writer and buffers output to it, flushing whenever a newline (`0x0a`, | |
250 | /// `'\n'`) is detected. | |
251 | /// | |
252 | /// This writer will be flushed when it is dropped. | |
c34b1796 | 253 | pub struct LineBufferedWriter<W: Writer> { |
85aaf69f SL |
254 | inner: BufferedWriter<W>, |
255 | } | |
256 | ||
257 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 258 | impl<W: Writer> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug { |
85aaf69f SL |
259 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
260 | write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}", | |
261 | self.inner.inner, self.inner.pos, self.inner.buf.len()) | |
262 | } | |
263 | } | |
264 | ||
265 | impl<W: Writer> LineBufferedWriter<W> { | |
266 | /// Creates a new `LineBufferedWriter` | |
267 | pub fn new(inner: W) -> LineBufferedWriter<W> { | |
268 | // Lines typically aren't that long, don't use a giant buffer | |
269 | LineBufferedWriter { | |
270 | inner: BufferedWriter::with_capacity(1024, inner) | |
271 | } | |
272 | } | |
273 | ||
274 | /// Gets a reference to the underlying writer. | |
275 | /// | |
276 | /// This type does not expose the ability to get a mutable reference to the | |
277 | /// underlying reader because that could possibly corrupt the buffer. | |
278 | pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() } | |
279 | ||
280 | /// Unwraps this `LineBufferedWriter`, returning the underlying writer. | |
281 | /// | |
282 | /// The internal buffer is flushed before returning the writer. | |
283 | pub fn into_inner(self) -> W { self.inner.into_inner() } | |
284 | } | |
285 | ||
286 | impl<W: Writer> Writer for LineBufferedWriter<W> { | |
287 | fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { | |
288 | match buf.iter().rposition(|&b| b == b'\n') { | |
289 | Some(i) => { | |
290 | try!(self.inner.write_all(&buf[..i + 1])); | |
291 | try!(self.inner.flush()); | |
292 | try!(self.inner.write_all(&buf[i + 1..])); | |
293 | Ok(()) | |
294 | } | |
295 | None => self.inner.write_all(buf), | |
296 | } | |
297 | } | |
298 | ||
299 | fn flush(&mut self) -> IoResult<()> { self.inner.flush() } | |
300 | } | |
301 | ||
c34b1796 | 302 | struct InternalBufferedWriter<W: Writer>(BufferedWriter<W>); |
85aaf69f | 303 | |
c34b1796 | 304 | impl<W: Writer> InternalBufferedWriter<W> { |
85aaf69f SL |
305 | fn get_mut<'a>(&'a mut self) -> &'a mut BufferedWriter<W> { |
306 | let InternalBufferedWriter(ref mut w) = *self; | |
307 | return w; | |
308 | } | |
309 | } | |
310 | ||
c34b1796 AL |
311 | impl<W: Reader + Writer> Reader for InternalBufferedWriter<W> { |
312 | fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { | |
85aaf69f SL |
313 | self.get_mut().inner.as_mut().unwrap().read(buf) |
314 | } | |
315 | } | |
316 | ||
317 | /// Wraps a Stream and buffers input and output to and from it. | |
318 | /// | |
319 | /// It can be excessively inefficient to work directly with a `Stream`. For | |
320 | /// example, every call to `read` or `write` on `TcpStream` results in a system | |
321 | /// call. A `BufferedStream` keeps in memory buffers of data, making large, | |
322 | /// infrequent calls to `read` and `write` on the underlying `Stream`. | |
323 | /// | |
324 | /// The output half will be flushed when this stream is dropped. | |
325 | /// | |
c34b1796 | 326 | /// # Examples |
85aaf69f | 327 | /// |
c34b1796 AL |
328 | /// ``` |
329 | /// # #![feature(old_io, old_path)] | |
85aaf69f | 330 | /// # #![allow(unused_must_use)] |
c34b1796 AL |
331 | /// use std::old_io::*; |
332 | /// use std::old_path::Path; | |
85aaf69f SL |
333 | /// |
334 | /// let file = File::open(&Path::new("message.txt")); | |
335 | /// let mut stream = BufferedStream::new(file); | |
336 | /// | |
337 | /// stream.write_all("hello, world".as_bytes()); | |
338 | /// stream.flush(); | |
339 | /// | |
340 | /// let mut buf = [0; 100]; | |
341 | /// match stream.read(&mut buf) { | |
342 | /// Ok(nread) => println!("Read {} bytes", nread), | |
343 | /// Err(e) => println!("error reading: {}", e) | |
344 | /// } | |
345 | /// ``` | |
c34b1796 | 346 | pub struct BufferedStream<S: Writer> { |
85aaf69f SL |
347 | inner: BufferedReader<InternalBufferedWriter<S>> |
348 | } | |
349 | ||
350 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 351 | impl<S: Writer> fmt::Debug for BufferedStream<S> where S: fmt::Debug { |
85aaf69f SL |
352 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
353 | let reader = &self.inner; | |
354 | let writer = &self.inner.inner.0; | |
355 | write!(fmt, "BufferedStream {{ stream: {:?}, write_buffer: {}/{}, read_buffer: {}/{} }}", | |
356 | writer.inner, | |
357 | writer.pos, writer.buf.len(), | |
358 | reader.cap - reader.pos, reader.buf.len()) | |
359 | } | |
360 | } | |
361 | ||
362 | impl<S: Stream> BufferedStream<S> { | |
363 | /// Creates a new buffered stream with explicitly listed capacities for the | |
364 | /// reader/writer buffer. | |
c34b1796 | 365 | pub fn with_capacities(reader_cap: usize, writer_cap: usize, inner: S) |
85aaf69f SL |
366 | -> BufferedStream<S> { |
367 | let writer = BufferedWriter::with_capacity(writer_cap, inner); | |
368 | let internal_writer = InternalBufferedWriter(writer); | |
369 | let reader = BufferedReader::with_capacity(reader_cap, | |
370 | internal_writer); | |
371 | BufferedStream { inner: reader } | |
372 | } | |
373 | ||
374 | /// Creates a new buffered stream with the default reader/writer buffer | |
375 | /// capacities. | |
376 | pub fn new(inner: S) -> BufferedStream<S> { | |
377 | BufferedStream::with_capacities(DEFAULT_BUF_SIZE, DEFAULT_BUF_SIZE, | |
378 | inner) | |
379 | } | |
380 | ||
381 | /// Gets a reference to the underlying stream. | |
382 | pub fn get_ref(&self) -> &S { | |
383 | let InternalBufferedWriter(ref w) = self.inner.inner; | |
384 | w.get_ref() | |
385 | } | |
386 | ||
387 | /// Gets a mutable reference to the underlying stream. | |
388 | /// | |
389 | /// # Warning | |
390 | /// | |
391 | /// It is inadvisable to read directly from or write directly to the | |
392 | /// underlying stream. | |
393 | pub fn get_mut(&mut self) -> &mut S { | |
394 | let InternalBufferedWriter(ref mut w) = self.inner.inner; | |
395 | w.get_mut() | |
396 | } | |
397 | ||
398 | /// Unwraps this `BufferedStream`, returning the underlying stream. | |
399 | /// | |
400 | /// The internal buffer is flushed before returning the stream. Any leftover | |
401 | /// data in the read buffer is lost. | |
402 | pub fn into_inner(self) -> S { | |
403 | let InternalBufferedWriter(w) = self.inner.inner; | |
404 | w.into_inner() | |
405 | } | |
406 | } | |
407 | ||
408 | impl<S: Stream> Buffer for BufferedStream<S> { | |
409 | fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() } | |
c34b1796 | 410 | fn consume(&mut self, amt: usize) { self.inner.consume(amt) } |
85aaf69f SL |
411 | } |
412 | ||
413 | impl<S: Stream> Reader for BufferedStream<S> { | |
c34b1796 | 414 | fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> { |
85aaf69f SL |
415 | self.inner.read(buf) |
416 | } | |
417 | } | |
418 | ||
419 | impl<S: Stream> Writer for BufferedStream<S> { | |
420 | fn write_all(&mut self, buf: &[u8]) -> IoResult<()> { | |
421 | self.inner.inner.get_mut().write_all(buf) | |
422 | } | |
423 | fn flush(&mut self) -> IoResult<()> { | |
424 | self.inner.inner.get_mut().flush() | |
425 | } | |
426 | } | |
427 | ||
428 | #[cfg(test)] | |
429 | mod test { | |
430 | extern crate test; | |
c34b1796 | 431 | use old_io::{self, Reader, Writer, Buffer, BufferPrelude}; |
85aaf69f SL |
432 | use prelude::v1::*; |
433 | use super::*; | |
434 | use super::super::{IoResult, EndOfFile}; | |
435 | use super::super::mem::MemReader; | |
436 | use self::test::Bencher; | |
437 | ||
438 | /// A type, free to create, primarily intended for benchmarking creation of | |
439 | /// wrappers that, just for construction, don't need a Reader/Writer that | |
440 | /// does anything useful. Is equivalent to `/dev/null` in semantics. | |
441 | #[derive(Clone,PartialEq,PartialOrd)] | |
442 | pub struct NullStream; | |
443 | ||
444 | impl Reader for NullStream { | |
c34b1796 | 445 | fn read(&mut self, _: &mut [u8]) -> old_io::IoResult<usize> { |
85aaf69f SL |
446 | Err(old_io::standard_error(old_io::EndOfFile)) |
447 | } | |
448 | } | |
449 | ||
450 | impl Writer for NullStream { | |
451 | fn write_all(&mut self, _: &[u8]) -> old_io::IoResult<()> { Ok(()) } | |
452 | } | |
453 | ||
454 | /// A dummy reader intended at testing short-reads propagation. | |
455 | pub struct ShortReader { | |
c34b1796 | 456 | lengths: Vec<usize>, |
85aaf69f SL |
457 | } |
458 | ||
459 | impl Reader for ShortReader { | |
c34b1796 | 460 | fn read(&mut self, _: &mut [u8]) -> old_io::IoResult<usize> { |
85aaf69f SL |
461 | if self.lengths.is_empty() { |
462 | Err(old_io::standard_error(old_io::EndOfFile)) | |
463 | } else { | |
464 | Ok(self.lengths.remove(0)) | |
465 | } | |
466 | } | |
467 | } | |
468 | ||
469 | #[test] | |
470 | fn test_buffered_reader() { | |
471 | let inner = MemReader::new(vec!(5, 6, 7, 0, 1, 2, 3, 4)); | |
472 | let mut reader = BufferedReader::with_capacity(2, inner); | |
473 | ||
474 | let mut buf = [0, 0, 0]; | |
475 | let nread = reader.read(&mut buf); | |
476 | assert_eq!(Ok(3), nread); | |
477 | let b: &[_] = &[5, 6, 7]; | |
478 | assert_eq!(buf, b); | |
479 | ||
480 | let mut buf = [0, 0]; | |
481 | let nread = reader.read(&mut buf); | |
482 | assert_eq!(Ok(2), nread); | |
483 | let b: &[_] = &[0, 1]; | |
484 | assert_eq!(buf, b); | |
485 | ||
486 | let mut buf = [0]; | |
487 | let nread = reader.read(&mut buf); | |
488 | assert_eq!(Ok(1), nread); | |
489 | let b: &[_] = &[2]; | |
490 | assert_eq!(buf, b); | |
491 | ||
492 | let mut buf = [0, 0, 0]; | |
493 | let nread = reader.read(&mut buf); | |
494 | assert_eq!(Ok(1), nread); | |
495 | let b: &[_] = &[3, 0, 0]; | |
496 | assert_eq!(buf, b); | |
497 | ||
498 | let nread = reader.read(&mut buf); | |
499 | assert_eq!(Ok(1), nread); | |
500 | let b: &[_] = &[4, 0, 0]; | |
501 | assert_eq!(buf, b); | |
502 | ||
503 | assert!(reader.read(&mut buf).is_err()); | |
504 | } | |
505 | ||
506 | #[test] | |
507 | fn test_buffered_writer() { | |
508 | let inner = Vec::new(); | |
509 | let mut writer = BufferedWriter::with_capacity(2, inner); | |
510 | ||
511 | writer.write_all(&[0, 1]).unwrap(); | |
512 | let b: &[_] = &[]; | |
c34b1796 | 513 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
514 | |
515 | writer.write_all(&[2]).unwrap(); | |
516 | let b: &[_] = &[0, 1]; | |
c34b1796 | 517 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
518 | |
519 | writer.write_all(&[3]).unwrap(); | |
c34b1796 | 520 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
521 | |
522 | writer.flush().unwrap(); | |
523 | let a: &[_] = &[0, 1, 2, 3]; | |
c34b1796 | 524 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
525 | |
526 | writer.write_all(&[4]).unwrap(); | |
527 | writer.write_all(&[5]).unwrap(); | |
c34b1796 | 528 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
529 | |
530 | writer.write_all(&[6]).unwrap(); | |
531 | let a: &[_] = &[0, 1, 2, 3, 4, 5]; | |
c34b1796 | 532 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
533 | |
534 | writer.write_all(&[7, 8]).unwrap(); | |
535 | let a: &[_] = &[0, 1, 2, 3, 4, 5, 6]; | |
c34b1796 | 536 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
537 | |
538 | writer.write_all(&[9, 10, 11]).unwrap(); | |
539 | let a: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; | |
c34b1796 | 540 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
541 | |
542 | writer.flush().unwrap(); | |
c34b1796 | 543 | assert_eq!(a, &writer.get_ref()[..]); |
85aaf69f SL |
544 | } |
545 | ||
546 | #[test] | |
547 | fn test_buffered_writer_inner_flushes() { | |
548 | let mut w = BufferedWriter::with_capacity(3, Vec::new()); | |
549 | w.write_all(&[0, 1]).unwrap(); | |
550 | let a: &[_] = &[]; | |
c34b1796 | 551 | assert_eq!(&w.get_ref()[..], a); |
85aaf69f SL |
552 | let w = w.into_inner(); |
553 | let a: &[_] = &[0, 1]; | |
554 | assert_eq!(a, &w[..]); | |
555 | } | |
556 | ||
557 | // This is just here to make sure that we don't infinite loop in the | |
558 | // newtype struct autoderef weirdness | |
559 | #[test] | |
560 | fn test_buffered_stream() { | |
561 | struct S; | |
562 | ||
563 | impl old_io::Writer for S { | |
564 | fn write_all(&mut self, _: &[u8]) -> old_io::IoResult<()> { Ok(()) } | |
565 | } | |
566 | ||
567 | impl old_io::Reader for S { | |
c34b1796 | 568 | fn read(&mut self, _: &mut [u8]) -> old_io::IoResult<usize> { |
85aaf69f SL |
569 | Err(old_io::standard_error(old_io::EndOfFile)) |
570 | } | |
571 | } | |
572 | ||
573 | let mut stream = BufferedStream::new(S); | |
574 | let mut buf = []; | |
575 | assert!(stream.read(&mut buf).is_err()); | |
576 | stream.write_all(&buf).unwrap(); | |
577 | stream.flush().unwrap(); | |
578 | } | |
579 | ||
580 | #[test] | |
581 | fn test_read_until() { | |
582 | let inner = MemReader::new(vec!(0, 1, 2, 1, 0)); | |
583 | let mut reader = BufferedReader::with_capacity(2, inner); | |
584 | assert_eq!(reader.read_until(0), Ok(vec!(0))); | |
585 | assert_eq!(reader.read_until(2), Ok(vec!(1, 2))); | |
586 | assert_eq!(reader.read_until(1), Ok(vec!(1))); | |
587 | assert_eq!(reader.read_until(8), Ok(vec!(0))); | |
588 | assert!(reader.read_until(9).is_err()); | |
589 | } | |
590 | ||
591 | #[test] | |
592 | fn test_line_buffer() { | |
593 | let mut writer = LineBufferedWriter::new(Vec::new()); | |
594 | writer.write_all(&[0]).unwrap(); | |
595 | let b: &[_] = &[]; | |
c34b1796 | 596 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f | 597 | writer.write_all(&[1]).unwrap(); |
c34b1796 | 598 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
599 | writer.flush().unwrap(); |
600 | let b: &[_] = &[0, 1]; | |
c34b1796 | 601 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
602 | writer.write_all(&[0, b'\n', 1, b'\n', 2]).unwrap(); |
603 | let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n']; | |
c34b1796 | 604 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
605 | writer.flush().unwrap(); |
606 | let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2]; | |
c34b1796 | 607 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
608 | writer.write_all(&[3, b'\n']).unwrap(); |
609 | let b: &[_] = &[0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']; | |
c34b1796 | 610 | assert_eq!(&writer.get_ref()[..], b); |
85aaf69f SL |
611 | } |
612 | ||
613 | #[test] | |
614 | fn test_read_line() { | |
615 | let in_buf = MemReader::new(b"a\nb\nc".to_vec()); | |
616 | let mut reader = BufferedReader::with_capacity(2, in_buf); | |
617 | assert_eq!(reader.read_line(), Ok("a\n".to_string())); | |
618 | assert_eq!(reader.read_line(), Ok("b\n".to_string())); | |
619 | assert_eq!(reader.read_line(), Ok("c".to_string())); | |
620 | assert!(reader.read_line().is_err()); | |
621 | } | |
622 | ||
623 | #[test] | |
624 | fn test_lines() { | |
625 | let in_buf = MemReader::new(b"a\nb\nc".to_vec()); | |
626 | let mut reader = BufferedReader::with_capacity(2, in_buf); | |
627 | let mut it = reader.lines(); | |
628 | assert_eq!(it.next(), Some(Ok("a\n".to_string()))); | |
629 | assert_eq!(it.next(), Some(Ok("b\n".to_string()))); | |
630 | assert_eq!(it.next(), Some(Ok("c".to_string()))); | |
631 | assert_eq!(it.next(), None); | |
632 | } | |
633 | ||
634 | #[test] | |
635 | fn test_short_reads() { | |
636 | let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]}; | |
637 | let mut reader = BufferedReader::new(inner); | |
638 | let mut buf = [0, 0]; | |
639 | assert_eq!(reader.read(&mut buf), Ok(0)); | |
640 | assert_eq!(reader.read(&mut buf), Ok(1)); | |
641 | assert_eq!(reader.read(&mut buf), Ok(2)); | |
642 | assert_eq!(reader.read(&mut buf), Ok(0)); | |
643 | assert_eq!(reader.read(&mut buf), Ok(1)); | |
644 | assert_eq!(reader.read(&mut buf), Ok(0)); | |
645 | assert!(reader.read(&mut buf).is_err()); | |
646 | } | |
647 | ||
648 | #[test] | |
649 | fn read_char_buffered() { | |
c34b1796 | 650 | let buf = [195, 159]; |
85aaf69f SL |
651 | let mut reader = BufferedReader::with_capacity(1, &buf[..]); |
652 | assert_eq!(reader.read_char(), Ok('ß')); | |
653 | } | |
654 | ||
655 | #[test] | |
656 | fn test_chars() { | |
c34b1796 | 657 | let buf = [195, 159, b'a']; |
85aaf69f SL |
658 | let mut reader = BufferedReader::with_capacity(1, &buf[..]); |
659 | let mut it = reader.chars(); | |
660 | assert_eq!(it.next(), Some(Ok('ß'))); | |
661 | assert_eq!(it.next(), Some(Ok('a'))); | |
662 | assert_eq!(it.next(), None); | |
663 | } | |
664 | ||
665 | #[test] | |
c34b1796 | 666 | #[should_panic] |
85aaf69f SL |
667 | fn dont_panic_in_drop_on_panicked_flush() { |
668 | struct FailFlushWriter; | |
669 | ||
670 | impl Writer for FailFlushWriter { | |
671 | fn write_all(&mut self, _buf: &[u8]) -> IoResult<()> { Ok(()) } | |
672 | fn flush(&mut self) -> IoResult<()> { Err(old_io::standard_error(EndOfFile)) } | |
673 | } | |
674 | ||
675 | let writer = FailFlushWriter; | |
676 | let _writer = BufferedWriter::new(writer); | |
677 | ||
678 | // If writer panics *again* due to the flush error then the process will abort. | |
679 | panic!(); | |
680 | } | |
681 | ||
682 | #[bench] | |
683 | fn bench_buffered_reader(b: &mut Bencher) { | |
684 | b.iter(|| { | |
685 | BufferedReader::new(NullStream) | |
686 | }); | |
687 | } | |
688 | ||
689 | #[bench] | |
690 | fn bench_buffered_writer(b: &mut Bencher) { | |
691 | b.iter(|| { | |
692 | BufferedWriter::new(NullStream) | |
693 | }); | |
694 | } | |
695 | ||
696 | #[bench] | |
697 | fn bench_buffered_stream(b: &mut Bencher) { | |
698 | b.iter(|| { | |
699 | BufferedStream::new(NullStream); | |
700 | }); | |
701 | } | |
702 | } |