diff options
Diffstat (limited to 'vendor/flate2/src/bufreader.rs')
-rw-r--r-- | vendor/flate2/src/bufreader.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/vendor/flate2/src/bufreader.rs b/vendor/flate2/src/bufreader.rs new file mode 100644 index 000000000..7e6f89d68 --- /dev/null +++ b/vendor/flate2/src/bufreader.rs @@ -0,0 +1,104 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// <https://github.com/rust-lang/rust/blob/HEAD/COPYRIGHT>. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp; +use std::io; +use std::io::prelude::*; +use std::mem; + +pub struct BufReader<R> { + inner: R, + buf: Box<[u8]>, + pos: usize, + cap: usize, +} + +impl<R> ::std::fmt::Debug for BufReader<R> +where + R: ::std::fmt::Debug, +{ + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + fmt.debug_struct("BufReader") + .field("reader", &self.inner) + .field( + "buffer", + &format_args!("{}/{}", self.cap - self.pos, self.buf.len()), + ) + .finish() + } +} + +impl<R: Read> BufReader<R> { + pub fn new(inner: R) -> BufReader<R> { + BufReader::with_buf(vec![0; 32 * 1024], inner) + } + + pub fn with_buf(buf: Vec<u8>, inner: R) -> BufReader<R> { + BufReader { + inner, + buf: buf.into_boxed_slice(), + pos: 0, + cap: 0, + } + } +} + +impl<R> BufReader<R> { + pub fn get_ref(&self) -> &R { + &self.inner + } + + pub fn get_mut(&mut self) -> &mut R { + &mut self.inner + } + + pub fn into_inner(self) -> R { + self.inner + } + + pub fn reset(&mut self, inner: R) -> R { + self.pos = 0; + self.cap = 0; + mem::replace(&mut self.inner, inner) + } +} + +impl<R: Read> Read for BufReader<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= self.buf.len() { + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) + } +} + +impl<R: Read> BufRead for BufReader<R> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + if self.pos == self.cap { + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) + } + + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); + } +} |