1// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// <https://github.com/rust-lang/rust/blob/HEAD/COPYRIGHT>.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use std::cmp;
12use std::io;
13use std::io::prelude::*;
14use std::mem;
15
16pub struct BufReader<R> {
17 inner: R,
18 buf: Box<[u8]>,
19 pos: usize,
20 cap: usize,
21}
22
23impl<R> ::std::fmt::Debug for BufReader<R>
24where
25 R: ::std::fmt::Debug,
26{
27 fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
28 fmt&mut DebugStruct<'_, '_>.debug_struct("BufReader")
29 .field("reader", &self.inner)
30 .field(
31 name:"buffer",
32 &format_args!("{}/{}", self.cap - self.pos, self.buf.len()),
33 )
34 .finish()
35 }
36}
37
38impl<R: Read> BufReader<R> {
39 pub fn new(inner: R) -> BufReader<R> {
40 BufReader::with_buf(buf:vec![0; 32 * 1024], inner)
41 }
42
43 pub fn with_buf(buf: Vec<u8>, inner: R) -> BufReader<R> {
44 BufReader {
45 inner,
46 buf: buf.into_boxed_slice(),
47 pos: 0,
48 cap: 0,
49 }
50 }
51}
52
53impl<R> BufReader<R> {
54 pub fn get_ref(&self) -> &R {
55 &self.inner
56 }
57
58 pub fn get_mut(&mut self) -> &mut R {
59 &mut self.inner
60 }
61
62 pub fn into_inner(self) -> R {
63 self.inner
64 }
65
66 pub fn reset(&mut self, inner: R) -> R {
67 self.pos = 0;
68 self.cap = 0;
69 mem::replace(&mut self.inner, src:inner)
70 }
71}
72
73impl<R: Read> Read for BufReader<R> {
74 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
75 // If we don't have any buffered data and we're doing a massive read
76 // (larger than our internal buffer), bypass our internal buffer
77 // entirely.
78 if self.pos == self.cap && buf.len() >= self.buf.len() {
79 return self.inner.read(buf);
80 }
81 let nread: usize = {
82 let mut rem: &[u8] = self.fill_buf()?;
83 rem.read(buf)?
84 };
85 self.consume(amt:nread);
86 Ok(nread)
87 }
88}
89
90impl<R: Read> BufRead for BufReader<R> {
91 fn fill_buf(&mut self) -> io::Result<&[u8]> {
92 // If we've reached the end of our internal buffer then we need to fetch
93 // some more data from the underlying reader.
94 if self.pos == self.cap {
95 self.cap = self.inner.read(&mut self.buf)?;
96 self.pos = 0;
97 }
98 Ok(&self.buf[self.pos..self.cap])
99 }
100
101 fn consume(&mut self, amt: usize) {
102 self.pos = cmp::min(self.pos + amt, self.cap);
103 }
104}
105