summaryrefslogtreecommitdiffstats
path: root/buffered-reader/src/memory.rs
diff options
context:
space:
mode:
Diffstat (limited to 'buffered-reader/src/memory.rs')
-rw-r--r--buffered-reader/src/memory.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/buffered-reader/src/memory.rs b/buffered-reader/src/memory.rs
new file mode 100644
index 00000000..327e4bcb
--- /dev/null
+++ b/buffered-reader/src/memory.rs
@@ -0,0 +1,91 @@
+use std::io;
+use std::fmt;
+use std::cmp;
+
+use std::io::{Error,ErrorKind};
+
+use super::*;
+
+/// 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> fmt::Debug for BufferedReaderMemory<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> 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,
+ }
+ }
+
+ /// Returns the number of bytes that have been consumed by this
+ /// reader.
+ pub fn total_out(&self) -> usize {
+ return self.cursor;
+ }
+}
+
+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);
+}