summaryrefslogtreecommitdiffstats
path: root/src/openpgp/parse/buffered_reader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/openpgp/parse/buffered_reader.rs')
-rw-r--r--src/openpgp/parse/buffered_reader.rs841
1 files changed, 0 insertions, 841 deletions
diff --git a/src/openpgp/parse/buffered_reader.rs b/src/openpgp/parse/buffered_reader.rs
deleted file mode 100644
index ab6f96c6..00000000
--- a/src/openpgp/parse/buffered_reader.rs
+++ /dev/null
@@ -1,841 +0,0 @@
-//! An improved `BufRead` interface.
-
-use std;
-use std::str;
-use std::io;
-use std::io::{Error,ErrorKind};
-use std::cmp;
-use std::fmt;
-
-// The default buffer size.
-const DEFAULT_BUF_SIZE: usize = 8 * 1024;
-
-/// A `BufferedReader` is a type of `Read`er that has an internal
-/// buffer, and allows working directly from that buffer. Like a
-/// `BufRead`er, the internal buffer amortizes system calls. And,
-/// like a `BufRead`, a `BufferedReader` exposes the internal buffer
-/// so that a user can work with the data in place rather than having
-/// to first copy it to a local buffer. However, unlike `BufRead`,
-/// `BufferedReader` allows the caller to ensure that the internal
-/// buffer has a certain amount of data.
-pub trait BufferedReader : io::Read + fmt::Debug {
- /// Return the data in the internal buffer. Normally, the
- /// returned buffer will contain *at least* `amount` bytes worth
- /// of data. Less data may be returned if the end of the file is
- /// reached or an error occurs. In these cases, any remaining
- /// data is returned. Note: the error is not discarded, but will
- /// be returned when data is called and the internal buffer is
- /// empty.
- ///
- /// This function does not advance the cursor. Thus, multiple
- /// calls will return the same data. To advance the cursor, use
- /// `consume`.
- fn data(&mut self, amount: usize) -> Result<&[u8], io::Error>;
-
- /// Like `data`, but returns an error if there is not at least
- /// `amount` bytes available.
- fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- let result = self.data(amount);
- if let Ok(buffer) = result {
- if buffer.len() < amount {
- return Err(Error::new(ErrorKind::UnexpectedEof, "unepxected EOF"));
- }
- }
- return result;
- }
-
- /// Return all of the data until EOF. Like `data`, this does not
- /// actually consume the data that is read.
- ///
- /// In general, you shouldn't use this function as it can cause an
- /// enormous amount of buffering. But, if you know that the
- /// amount of data is limited, this is acceptable.
- fn data_eof(&mut self) -> Result<&[u8], io::Error> {
- // Don't just read std::usize::MAX bytes at once. The
- // implementation might try to actually allocate a buffer that
- // large! Instead, try with increasingly larger buffers until
- // the read is (strictly) shorter than the specified size.
- let mut s = DEFAULT_BUF_SIZE;
- while s < std::usize::MAX {
- match self.data(s) {
- Ok(ref buffer) =>
- if buffer.len() < s {
- // We really want to do
- //
- // return Ok(buffer);
- //
- // But, the borrower checker won't let us:
- //
- // error[E0499]: cannot borrow `*self` as
- // mutable more than once at a time.
- //
- // Instead, we break out of the loop, and then
- // call self.data(s) again. This extra call
- // shouldn't have any significant cost,
- // because the buffer should already be
- // prepared.
- break;
- } else {
- s *= 2;
- },
- Err(err) =>
- return Err(err),
- }
- }
- return self.data(s);
- }
-
- /// Mark the first `amount` bytes of the internal buffer as
- /// consumed. It is an error to call this function without having
- /// first successfully called `data` (or a related function) to
- /// buffer `amount` bytes.
- ///
- /// This function returns the data that has been consumed.
- fn consume(&mut self, amount: usize) -> &[u8];
-
- /// This is a convenient function that effectively combines data()
- /// and consume().
- fn data_consume(&mut self, amount: usize)
- -> Result<&[u8], std::io::Error>;
-
-
- // This is a convenient function that effectively combines
- // data_hard() and consume().
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error>;
-
- /// A convenience function for reading a 16-bit unsigned integer
- /// in big endian format.
- fn read_be_u16(&mut self) -> Result<u16, std::io::Error> {
- let input = self.data_consume_hard(2)?;
- return Ok(((input[0] as u16) << 8) + (input[1] as u16));
- }
-
- /// A convenience function for reading a 32-bit unsigned integer
- /// in big endian format.
- fn read_be_u32(&mut self) -> Result<u32, std::io::Error> {
- let input = self.data_consume_hard(4)?;
- return Ok(((input[0] as u32) << 24) + ((input[1] as u32) << 16)
- + ((input[2] as u32) << 8) + (input[3] as u32));
- }
-
- /// Reads and consumes `amount` bytes, and returns them in a
- /// caller owned buffer. Implementations may optimize this to
- /// avoid a copy.
- fn steal(&mut self, amount: usize) -> Result<Vec<u8>, std::io::Error> {
- let mut data = self.data_consume_hard(amount)?;
- assert!(data.len() >= amount);
- if data.len() > amount {
- data = &data[..amount];
- }
- return Ok(data.to_vec());
- }
-
- /// Like steal, but instead of stealing a fixed number of bytes,
- /// it steals all of the data it can.
- fn steal_eof(&mut self) -> Result<Vec<u8>, std::io::Error> {
- let len = self.data_eof()?.len();
- let data = self.steal(len)?;
- return Ok(data);
- }
-
- fn into_inner<'a>(self: Box<Self>) -> Option<Box<BufferedReader + 'a>>
- where Self: 'a;
-}
-
-/// This function implements the `std::io::Read::read` method in terms
-/// of the `data_consume` method. We can't use the `io::std::Read`
-/// interface, because the `BufferedReader` may have buffered some
-/// data internally (in which case a read will not return the buffered
-/// data, but the following data). This implementation is generic.
-/// When deriving a `BufferedReader`, you can include the following:
-///
-/// ```text
-/// impl<'a, T: BufferedReader> std::io::Read for BufferedReaderXXX<'a, T> {
-/// fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
-/// return buffered_reader_generic_read_impl(self, buf);
-/// }
-/// }
-/// ```
-///
-/// It would be nice if we could do:
-///
-/// ```text
-/// impl <T: BufferedReader> std::io::Read for T { ... }
-/// ```
-///
-/// but, alas, Rust doesn't like that ("error[E0119]: conflicting
-/// implementations of trait `std::io::Read` for type `&mut _`").
-pub fn buffered_reader_generic_read_impl<T: BufferedReader>
- (bio: &mut T, buf: &mut [u8]) -> Result<usize, io::Error> {
- match bio.data_consume(buf.len()) {
- Ok(inner) => {
- let amount = cmp::min(buf.len(), inner.len());
- buf[0..amount].copy_from_slice(&inner[0..amount]);
- return Ok(amount);
- },
- Err(err) => return Err(err),
- }
-}
-
-/// Make a `Box<BufferedReader>` look like a BufferedReader.
-impl <'a> BufferedReader for Box<BufferedReader + 'a> {
- fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.as_mut().data(amount);
- }
-
- fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.as_mut().data_hard(amount);
- }
-
- fn data_eof(&mut self) -> Result<&[u8], io::Error> {
- return self.as_mut().data_eof();
- }
-
- fn consume(&mut self, amount: usize) -> &[u8] {
- return self.as_mut().consume(amount);
- }
-
- fn data_consume(&mut self, amount: usize)
- -> Result<&[u8], std::io::Error> {
- return self.as_mut().data_consume(amount);
- }
-
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.as_mut().data_consume_hard(amount);
- }
-
- fn read_be_u16(&mut self) -> Result<u16, std::io::Error> {
- return self.as_mut().read_be_u16();
- }
-
- fn read_be_u32(&mut self) -> Result<u32, std::io::Error> {
- return self.as_mut().read_be_u32();
- }
-
- fn steal(&mut self, amount: usize) -> Result<Vec<u8>, std::io::Error> {
- return self.as_mut().steal(amount);
- }
-
- fn steal_eof(&mut self) -> Result<Vec<u8>, std::io::Error> {
- return self.as_mut().steal_eof();
- }
-
- fn into_inner<'b>(self: Box<Self>) -> Option<Box<BufferedReader + 'b>>
- where Self: 'b {
- // Strip the outer box.
- (*self).into_inner()
- }
-}
-
-/// A generic `BufferedReader` implementation that only requires a
-/// source that implements the `Read` trait. This is sufficient when
-/// reading from a file, and it even works with a `&[u8]` (but
-/// `BufferedReaderMemory` is more efficient).
-pub struct BufferedReaderGeneric<T: io::Read> {
- buffer: Option<Box<[u8]>>,
- // The next byte to read in the buffer.
- cursor: usize,
- // The preferred chunk size. This is just a hint.
- preferred_chunk_size: usize,
- // XXX: This is pub for the decompressors. It would be better to
- // change this to some accessor method.
- pub reader: Box<T>,
- // Whether we saw an EOF.
- saw_eof: bool,
- // The last error that we encountered, but have not yet returned.
- error: Option<io::Error>,
-}
-
-impl<T: io::Read> std::fmt::Debug for BufferedReaderGeneric<T> {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- let buffered_data = if let Some(ref buffer) = self.buffer {
- buffer.len() - self.cursor
- } else {
- 0
- };
-
- f.debug_struct("BufferedReaderGeneric")
- .field("preferred_chunk_size", &self.preferred_chunk_size)
- .field("buffer data", &buffered_data)
- .field("saw eof", &self.saw_eof)
- .field("error", &self.error)
- .finish()
- }
-}
-
-impl<T: io::Read> BufferedReaderGeneric<T> {
- /// Instantiate a new generic reader. `reader` is the source to
- /// wrap. `preferred_chuck_size` is the preferred chuck size. If
- /// None, then the default will be used, which is usually what you
- /// want.
- pub fn new(reader: T, preferred_chunk_size: Option<usize>)
- -> BufferedReaderGeneric<T> {
- BufferedReaderGeneric {
- buffer: None,
- cursor: 0,
- preferred_chunk_size:
- if let Some(s) = preferred_chunk_size { s } else { DEFAULT_BUF_SIZE },
- reader: Box::new(reader),
- saw_eof: false,
- error: None,
- }
- }
-
- /// Return the buffer. Ensure that it contains at least `amount`
- /// bytes.
- fn data_helper(&mut self, amount: usize, hard: bool, and_consume: bool)
- -> Result<&[u8], io::Error> {
- // println!("BufferedReaderGeneric.data_helper(\
- // amount: {}, hard: {}, and_consume: {} (cursor: {}, buffer: {:?})",
- // amount, hard, and_consume,
- // self.cursor,
- // if let Some(ref buffer) = self.buffer { Some(buffer.len()) }
- // else { None });
-
-
- if let Some(ref buffer) = self.buffer {
- // We have a buffer. Make sure `cursor` is sane.
- assert!(self.cursor <= buffer.len());
- } else {
- // We don't have a buffer. Make sure cursor is 0.
- assert_eq!(self.cursor, 0);
- }
-
- let amount_buffered =
- if let Some(ref buffer) = self.buffer { buffer.len() } else { 0 }
- - self.cursor;
- if !self.saw_eof && amount > amount_buffered {
- // The caller wants more data than we have readily
- // available. Read some more.
-
- let capacity : usize = cmp::max(cmp::max(
- DEFAULT_BUF_SIZE, 2 * self.preferred_chunk_size), amount);
-
- let mut buffer_new : Vec<u8> = vec![0u8; capacity];
-
- let mut amount_read = 0;
- while amount_buffered + amount_read < amount {
- match self.reader.read(&mut buffer_new
- [amount_buffered + amount_read..]) {
- Ok(read) => {
- if read == 0 {
- // XXX: Likely EOF.
- self.saw_eof = true;
- break;
- } else {
- amount_read += read;
- continue;
- }
- },
- Err(err) => {
- // Don't return yet, because we may have
- // actually read something.
- self.saw_eof = true;
- self.error = Some(err);
- break;
- },
- }
- }
-
- if amount_read > 0 {
- // We read something.
-
- if let Some(ref buffer) = self.buffer {
- // We need to copy in the old data.
- buffer_new[0..amount_buffered]
- .copy_from_slice(
- &buffer[self.cursor..self.cursor + amount_buffered]);
- }
-
- buffer_new.truncate(amount_buffered + amount_read);
- buffer_new.shrink_to_fit();
-
- self.buffer = Some(buffer_new.into_boxed_slice());
- self.cursor = 0;
- }
- }
-
- if self.error.is_some() {
- // An error occured. If we have enough data to fulfill
- // the caller's request, then delay returning the error.
- if let Some(ref buffer) = self.buffer {
- if amount > buffer.len() {
- // We return an error at most once (Recall: take
- // clears self.error).
- return Err(self.error.take().unwrap());
- }
- }
- }
-
- match self.buffer {
- Some(ref buffer) => {
- let amount_buffered = buffer.len() - self.cursor;
- if hard && amount_buffered < amount {
- return Err(Error::new(ErrorKind::UnexpectedEof, "EOF"));
- }
- if and_consume {
- let amount_consumed = cmp::min(amount_buffered, amount);
- self.cursor += amount_consumed;
- assert!(self.cursor <= buffer.len());
- return Ok(&buffer[self.cursor-amount_consumed..]);
- } else {
- return Ok(&buffer[self.cursor..]);
- }
- },
- None if self.saw_eof => {
- return Ok(&b""[..]);
- },
- None => {
- unreachable!();
- }
- }
- }
-}
-
-impl<T: io::Read> io::Read for BufferedReaderGeneric<T> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
- return buffered_reader_generic_read_impl(self, buf);
- }
-}
-
-impl<T: io::Read> BufferedReader for BufferedReaderGeneric<T> {
- fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.data_helper(amount, false, false);
- }
-
- fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.data_helper(amount, true, false);
- }
-
- fn consume(&mut self, amount: usize) -> &[u8] {
- // println!("BufferedReaderGeneric.consume({}) \
- // (cursor: {}, buffer: {:?})",
- // amount, self.cursor,
- // if let Some(ref buffer) = self.buffer { Some(buffer.len()) }
- // else { None });
-
- // The caller can't consume more than is buffered!
- if let Some(ref buffer) = self.buffer {
- assert!(self.cursor <= buffer.len());
- assert!(amount <= buffer.len() - self.cursor,
- "buffer contains just {} bytes, but you are trying to
- consume {} bytes. Did you forget to call data()?",
- buffer.len() - self.cursor, amount);
-
- self.cursor += amount;
- return &self.buffer.as_ref().unwrap()[self.cursor - amount..];
- } else {
- assert_eq!(amount, 0);
- return &b""[..];
- }
- }
-
- fn data_consume(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.data_helper(amount, false, true);
- }
-
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return self.data_helper(amount, true, true);
- }
-
- fn into_inner<'b>(self: Box<Self>) -> Option<Box<BufferedReader + 'b>>
- where Self: 'b {
- None
- }
-}
-
-// The file was created as follows:
-//
-// for i in $(seq 0 9999); do printf "%04d\n" $i; done > buffered-reader-test.txt
-#[cfg(test)]
-fn buffered_reader_test_data_check<'a, T: BufferedReader + 'a>(bio: &mut T) {
- for i in 0 .. 10000 {
- let consumed = {
- // Each number is 4 bytes plus a newline character.
- let d = bio.data_hard(5);
- if d.is_err() {
- println!("Error for i == {}: {:?}", i, d);
- }
- let d = d.unwrap();
- assert!(d.len() >= 5);
- assert_eq!(format!("{:04}\n", i), str::from_utf8(&d[0..5]).unwrap());
-
- 5
- };
-
- bio.consume(consumed);
- }
-}
-
-#[test]
-fn buffered_reader_generic_test() {
- // Test reading from a file.
- {
- use std::path::PathBuf;
- use std::fs::File;
-
- let path : PathBuf = [env!("CARGO_MANIFEST_DIR"),
- "src", "openpgp", "parse", "buffered-reader-test.txt"]
- .iter().collect();
- let mut f = File::open(&path).expect(&path.to_string_lossy());
- let mut bio = BufferedReaderGeneric::new(&mut f, None);
-
- buffered_reader_test_data_check(&mut bio);
- }
-
- // Same test, but as a slice.
- {
- let mut data : &[u8] = include_bytes!("buffered-reader-test.txt");
- let mut bio = BufferedReaderGeneric::new(&mut data, None);
-
- buffered_reader_test_data_check(&mut bio);
- }
-}
-
-/// A `BufferedReader` specialized for reading from memory buffers.
-pub struct BufferedReaderMemory<'a> {
- buffer: &'a [u8],
- // The next byte to read in the buffer.
- cursor: usize,
-}
-
-impl <'a> std::fmt::Debug for BufferedReaderMemory<'a> {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- f.debug_struct("BufferedReaderMemory")
- .field("buffer (bytes)", &&self.buffer.len())
- .field("cursor", &self.cursor)
- .finish()
- }
-}
-
-impl<'a> BufferedReaderMemory<'a> {
- pub fn new(buffer: &'a [u8]) -> BufferedReaderMemory<'a> {
- BufferedReaderMemory {
- buffer: buffer,
- cursor: 0,
- }
- }
-}
-
-impl<'a> io::Read for BufferedReaderMemory<'a> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
- let amount = cmp::min(buf.len(), self.buffer.len() - self.cursor);
- buf[0..amount].copy_from_slice(
- &self.buffer[self.cursor..self.cursor+amount]);
- self.consume(amount);
- return Ok(amount);
- }
-}
-
-impl<'a> BufferedReader for BufferedReaderMemory<'a> {
- /// Return the buffer. Ensure that it contains at least `amount`
- /// bytes.
- fn data(&mut self, _amount: usize) -> Result<&[u8], io::Error> {
- assert!(self.cursor <= self.buffer.len());
- return Ok(&self.buffer[self.cursor..]);
- }
-
- fn consume(&mut self, amount: usize) -> &[u8] {
- // The caller can't consume more than is buffered!
- assert!(amount <= self.buffer.len() - self.cursor,
- "Attempt to consume {} bytes, but buffer only has {} bytes!",
- amount, self.buffer.len() - self.cursor);
- self.cursor += amount;
- assert!(self.cursor <= self.buffer.len());
- return &self.buffer[self.cursor - amount..];
- }
-
- fn data_consume(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- return Ok(self.consume(amount));
- }
-
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- if self.buffer.len() - self.cursor < amount {
- return Err(Error::new(ErrorKind::UnexpectedEof, "EOF"));
- }
- return Ok(self.consume(amount));
- }
-
- fn into_inner<'b>(self: Box<Self>) -> Option<Box<BufferedReader + 'b>>
- where Self: 'b {
- None
- }
-}
-
-#[test]
-fn buffered_reader_memory_test () {
- let data : &[u8] = include_bytes!("buffered-reader-test.txt");
- let mut bio = BufferedReaderMemory::new(data);
-
- buffered_reader_test_data_check(&mut bio);
-}
-
-/// A `BufferedReaderLimitor` limits the amount of data that can be
-/// read from a `BufferedReader`.
-#[derive(Debug)]
-pub struct BufferedReaderLimitor<T: BufferedReader> {
- reader: T,
- limit: u64,
-}
-
-impl<T: BufferedReader> BufferedReaderLimitor<T> {
- pub fn new(reader: T, limit: u64) -> BufferedReaderLimitor<T> {
- BufferedReaderLimitor {
- reader: reader,
- limit: limit,
- }
- }
-}
-
-impl<T: BufferedReader> io::Read for BufferedReaderLimitor<T> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
- let len = cmp::min(self.limit, buf.len() as u64) as usize;
- return self.reader.read(&mut buf[0..len]);
- }
-}
-
-impl<T: BufferedReader> BufferedReader for BufferedReaderLimitor<T> {
- /// Return the buffer. Ensure that it contains at least `amount`
- /// bytes.
- fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- let amount = cmp::min(amount as u64, self.limit) as usize;
- let result = self.reader.data(amount);
- match result {
- Ok(ref buffer) =>
- if buffer.len() as u64 > self.limit {
- return Ok(&buffer[0..self.limit as usize]);
- } else {
- return Ok(buffer);
- },
- Err(err) => return Err(err),
- }
- }
-
- fn consume(&mut self, amount: usize) -> &[u8] {
- assert!(amount as u64 <= self.limit);
- self.limit -= amount as u64;
- let data = self.reader.consume(amount);
- return &data[..cmp::min(self.limit + amount as u64, data.len() as u64) as usize];
- }
-
- fn data_consume(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- let amount = cmp::min(amount as u64, self.limit) as usize;
- let result = self.reader.data_consume(amount);
- if let Ok(ref buffer) = result {
- self.limit -= amount as u64;
- return Ok(&buffer[
- ..cmp::min(buffer.len() as u64, self.limit + amount as u64) as usize]);
- }
- return result;
- }
-
- fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
- if amount as u64 > self.limit {
- return Err(Error::new(ErrorKind::UnexpectedEof, "EOF"));
- }
- let result = self.reader.data_consume_hard(amount);
- if let Ok(ref buffer) = result {
- self.limit -= amount as u64;
- return Ok(&buffer[
- ..cmp::min(buffer.len() as u64, self.limit + amount as u64) as usize]);
- }
- return result;
- }
-
- fn into_inner<'b>(self: Box<Self>) -> Option<Box<BufferedReader + 'b>>
- where Self: 'b {
- Some(Box::new(self.reader))
- }
-}
-
-#[test]
-fn buffered_reader_limitor_test() {
- let data : &[u8] = b"01234567890123456789";
-
- /* Add a single limitor. */
- {
- let mut bio : Box<BufferedReader>
- = Box::new(BufferedReaderMemory::new(data));
-
- bio = {
- let mut bio2 = Box::new(BufferedReaderLimitor::new(bio, 5));
- {
- let result = bio2.data(5).unwrap();
- assert_eq!(result.len(), 5);
- assert_eq!(result, &b"01234"[..]);
- }
- bio2.consume(5);
- {
- let result = bio2.data(1).unwrap();
- assert_eq!(result.len(), 0);
- assert_eq!(result, &b""[..]);
- }
-
- bio2.into_inner().unwrap()
- };
-
- {
- {
- let result = bio.data(15).unwrap();
- assert_eq!(result.len(), 15);
- assert_eq!(result, &b"567890123456789"[..]);
- }
- bio.consume(15);
- {
- let result = bio.data(1).unwrap();
- assert_eq!(result.len(), 0);
- assert_eq!(result, &b""[..]);
- }
- }
- }
-
- /* Try with two limitors where the first one imposes the real
- * limit. */
- {
- let mut bio : Box<BufferedReader>
- = Box::new(BufferedReaderMemory::new(data));
-
- bio = {
- let bio2 : Box<BufferedReader>
- = Box::new(BufferedReaderLimitor::new(bio, 5));
- // We limit to 15 bytes, but bio2 will still limit us to 5
- // bytes.
- let mut bio3 : Box<BufferedReader>
- = Box::new(BufferedReaderLimitor::new(bio2, 15));
- {
- let result = bio3.data(100).unwrap();
- assert_eq!(result.len(), 5);
- assert_eq!(result, &b"01234"[..]);
- }
- bio3.consume(5);
- {
- let result = bio3.data(1).unwrap();
- assert_eq!(result.len(), 0);
- assert_eq!(result, &b""[..]);
- }
-
- bio3.into_inner().unwrap().into_inner().unwrap()
- };
-
- {
- {
- let result = bio.data(15).unwrap();
- assert_eq!(result.len(), 15);
- assert_eq!(result, &b"567890123456789"[..]);
- }
- bio.consume(15);
- {
- let result = bio.data(1).unwrap();
- assert_eq!(result.len(), 0);
- assert_eq!(result, &b""[..]);
- }
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn buffered_reader_eof_test() {
- let data : &[u8] = include_bytes!("buffered-reader-test.txt");
-
- // Make sure data_eof works.
- {
- let mut bio = BufferedReaderMemory::new(data);
- let amount = {
- bio.data_eof().unwrap().len()
- };
- bio.consume(amount);
- assert_eq!(bio.data(1).unwrap().len(), 0);
- }
-
- // Try it again with a limitor.
- {
- let bio = BufferedReaderMemory::new(data);
- let mut bio2 = BufferedReaderLimitor::new(bio, (data.len() / 2) as u64);
- let amount = {
- bio2.data_eof().unwrap().len()
- };
- assert_eq!(amount, data.len() / 2);
- bio2.consume(amount);
- assert_eq!(bio2.data(1).unwrap().len(), 0);
- }
- }
-
- #[cfg(test)]
- fn buffered_reader_read_test_aux<'a, T: BufferedReader + 'a>
- (mut bio: T, data: &[u8]) {
- let mut buffer = [0; 99];
-
- // Make sure the test file has more than buffer.len() bytes
- // worth of data.
- assert!(buffer.len() < data.len());
-
- // The number of reads we'll have to perform.