flate2/
bufreader.rs

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
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.debug_struct("BufReader")
29            .field("reader", &self.inner)
30            .field(
31                "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(vec![0; 32 * 1024], inner)
41    }
42
43    pub fn with_buf(buf: Vec<u8>, inner: R) -> BufReader<R> {
44        BufReader {
45            inner: 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, 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 = {
82            let mut rem = self.fill_buf()?;
83            rem.read(buf)?
84        };
85        self.consume(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}