#[macro_use]
extern crate failure;
pub mod buffer {
use std::io::Error;
use std::io::{Read, Seek, SeekFrom, Write};
#[derive(PartialEq)]
pub enum SeekOrigin {
Begin,
Current,
End,
}
#[derive(PartialEq)]
pub enum Endianness {
Little,
Big,
}
pub struct BufferWriter<W: Write> {
pub writer: W,
}
impl<W: Write> BufferWriter<W>
where
W: Seek + Read + Write,
{
pub fn new(writer: W) -> Self {
BufferWriter { writer: writer }
}
pub fn position(&mut self) -> Result<u64, BufferError> {
self.seek(0, SeekOrigin::Current)
}
pub fn len(&mut self) -> Result<u64, BufferError> {
let old_pos = self.position()?;
let len = self.seek(0, SeekOrigin::End)?;
if old_pos != len {
self.seek(old_pos as i64, SeekOrigin::Begin)?;
}
Ok(len)
}
pub fn to_vec(&mut self) -> Result<Vec<u8>, BufferError> {
let mut out: Vec<u8> = vec![];
self.seek(0, SeekOrigin::Begin)?;
self.writer.read_to_end(&mut out).unwrap();
Ok(out)
}
pub fn seek(&mut self, position: i64, origin: SeekOrigin) -> Result<u64, BufferError> {
match origin {
SeekOrigin::Begin => self.writer.seek(SeekFrom::Start(position as u64)),
SeekOrigin::Current => self.writer.seek(SeekFrom::Current(position)),
SeekOrigin::End => self.writer.seek(SeekFrom::End(position)),
}
.map(|o| o)
.map_err(|_e| BufferError::IndexOutOfRange { index: position })
}
pub fn write_u32(&mut self, value: u32) -> Result<u64, BufferError> {
let data = &[
(value >> 0) as u8,
(value >> 8) as u8,
(value >> 16) as u8,
(value >> 24) as u8,
];
self.writer
.write(data)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_u64(&mut self, value: u64) -> Result<u64, BufferError> {
let data = &[
(value >> 0) as u8,
(value >> 8) as u8,
(value >> 16) as u8,
(value >> 24) as u8,
(value >> 32) as u8,
(value >> 40) as u8,
(value >> 48) as u8,
(value >> 56) as u8,
];
self.writer
.write(data)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_i32(&mut self, value: i32) -> Result<u64, BufferError> {
let data = &[
(value >> 0) as u8,
(value >> 8) as u8,
(value >> 16) as u8,
(value >> 24) as u8,
];
self.writer
.write(data)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_u16(&mut self, value: u16) -> Result<u64, BufferError> {
let data = &[(value >> 0) as u8, (value >> 8) as u8];
self.writer
.write(data)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_u8(&mut self, value: u8) -> Result<u64, BufferError> {
self.writer
.write(&[value])
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_7bit_int(&mut self, value: i32) -> Result<(), BufferError> {
let mut v = value as u32;
while v >= 0x80 {
self.write_u8((v | 0x80) as u8)?;
v >>= 7;
}
self.write_u8(v as u8)?;
Ok(())
}
pub fn write_string(&mut self, value: String) -> Result<u64, BufferError> {
let bytes = value.as_bytes();
self.write_7bit_int(bytes.len() as i32)?;
self.writer
.write(bytes)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
pub fn write_bytes(&mut self, value: &Vec<u8>) -> Result<u64, BufferError> {
self.writer
.write(value)
.map(|o| o as u64)
.map_err(|_e| BufferError::IOFailure)
}
}
pub struct BufferReader<R: Read> {
pub reader: R,
}
impl<R: Read> BufferReader<R>
where
R: Seek + Read + Write,
{
pub fn new(reader: R) -> Self {
BufferReader { reader: reader }
}
pub fn position(&mut self) -> Result<u64, BufferError> {
self.seek(0, SeekOrigin::Current)
}
pub fn len(&mut self) -> Result<u64, BufferError> {
let old_pos = self.position()?;
let len = self.seek(0, SeekOrigin::End)?;
if old_pos != len {
self.seek(old_pos as i64, SeekOrigin::Begin)?;
}
Ok(len)
}
pub fn seek(&mut self, position: i64, origin: SeekOrigin) -> Result<u64, BufferError> {
match origin {
SeekOrigin::Begin => self.reader.seek(SeekFrom::Start(position as u64)),
SeekOrigin::Current => self.reader.seek(SeekFrom::Current(position)),
SeekOrigin::End => self.reader.seek(SeekFrom::End(position)),
}
.map(|o| o as u64)
.map_err(|_e| BufferError::IndexOutOfRange { index: position })
}
pub fn read_7bit_int(&mut self) -> Result<i32, BufferError> {
let mut count: i32 = 0;
let mut shift = 0;
let mut b: u8 = 0;
while {
if shift == 5 * 7 {
return Err(BufferError::IOFailure);
}
b = self.read_u8()?;
count |= ((b & 0x7F) as i32) << shift;
shift += 7;
(b & 0x80) != 0
} {}
Ok(count)
}
pub fn read_string(&mut self) -> Result<String, BufferError> {
let string_length = self.read_7bit_int()?;
if string_length < 0 {
return Err(BufferError::IOFailure);
}
if string_length == 0 {
return Ok(String::default());
}
let chars = self.read_bytes(string_length as u64)?;
String::from_utf8(chars)
.map(|o| o)
.map_err(|_e| BufferError::IOFailure)
}
pub fn read_u32(&mut self) -> Result<u32, BufferError> {
let size = std::mem::size_of::<u32>() as u64;
if self.position()? + size > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = [0u8; 4];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| {
((buffer[0] as u32) << 0)
| ((buffer[1] as u32) << 8)
| ((buffer[2] as u32) << 16)
| ((buffer[3] as u32) << 24)
})
}
pub fn read_u64(&mut self) -> Result<u64, BufferError> {
let size = std::mem::size_of::<u64>() as u64;
if self.position()? + size > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = vec![0u8; 8];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| {
let lo = (buffer[0] as u32)
| (buffer[1] as u32) << 8
| (buffer[2] as u32) << 16
| (buffer[3] as u32) << 24;
let hi = (buffer[4] as u32)
| (buffer[5] as u32) << 8
| (buffer[6] as u32) << 16
| (buffer[7] as u32) << 24;
(hi as u64) << 32 | lo as u64
})
}
pub fn read_i32(&mut self) -> Result<i32, BufferError> {
let size = std::mem::size_of::<i32>() as u64;
if self.position()? + size > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = [0u8; 4];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| {
((buffer[0] as i32) << 0)
| ((buffer[1] as i32) << 8)
| ((buffer[2] as i32) << 16)
| ((buffer[3] as i32) << 24)
})
}
pub fn read_u16(&mut self) -> Result<u16, BufferError> {
let size = std::mem::size_of::<u16>() as u64;
if self.position()? + size > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = [0u8; 2];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| (buffer[0] as u16) | (buffer[1] as u16))
}
pub fn read_u8(&mut self) -> Result<u8, BufferError> {
let size = std::mem::size_of::<u8>() as u64;
if self.position()? + size > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = [0u8; 1];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| buffer[0])
}
pub fn read_bytes(&mut self, count: u64) -> Result<Vec<u8>, BufferError> {
if self.position()? + count > self.len()? {
return Err(BufferError::EndOfStream);
}
let mut buffer = vec![0u8; count as usize];
self.reader
.read_exact(&mut buffer)
.map_err(|e| BufferError::ReadFailure { error: e })
.map(|_b| buffer)
}
pub fn read_bytes_at(&mut self, offset: u64, count: u64) -> Result<Vec<u8>, BufferError> {
if offset + count > self.len()? {
return Err(BufferError::EndOfStream);
}
let current_pos = self.position()?;
self.seek(offset as i64, SeekOrigin::Begin)?;
let buffer = self.read_bytes(count)?;
self.seek(current_pos as i64, SeekOrigin::Begin)?;
Ok(buffer)
}
}
#[derive(Debug, Fail)]
pub enum BufferError {
#[fail(
display = "seek index ({}) was out of range. Must be non-negative and less than the size of the collection.",
index
)]
IndexOutOfRange { index: i64 },
#[fail(display = "attempted to read past the end of a stream.")]
EndOfStream,
#[fail(display = "unable to read bytes from buffer: {:?}", error)]
ReadFailure { error: Error },
#[fail(display = "unable to write data to buffer.")]
IOFailure,
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
use crate::buffer::{BufferReader, BufferWriter, SeekOrigin};
use std::io::Cursor;
let mut buffer = BufferWriter::new(Cursor::new(Vec::new()));
buffer.write_u32(9001).unwrap();
buffer.write_u32(9002).unwrap();
buffer.write_string("Hello World!".to_string()).unwrap();
buffer.seek(0, SeekOrigin::Begin).unwrap();
buffer.write_u32(9003).unwrap();
let data = buffer.to_vec().unwrap();
let mut reader = BufferReader::new(Cursor::new(data));
assert_eq!(9003, reader.read_u32().unwrap());
assert_eq!(9002, reader.read_u32().unwrap());
assert_eq!("Hello World!", reader.read_string().unwrap());
}
}