extern crate byteorder;
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use std::io::prelude::*;
pub enum Endian {
Big,
Little,
}
pub struct BinaryReader {
pub data: Vec<u8>,
pub pos: usize,
pub length: usize,
pub endian: Endian
}
impl BinaryReader {
#[doc(hidden)]
fn initialize() -> BinaryReader {
BinaryReader {
data: Vec::new(),
pos: 0,
length: 0,
endian: Endian::Big
}
}
pub fn from_u8(get: &[u8]) -> BinaryReader {
let mut a = BinaryReader::initialize();
a.data = get.to_vec();
a.length = get.len();
a
}
pub fn from_vec(vec: &Vec<u8>) -> BinaryReader {
let mut a = BinaryReader::initialize();
a.data = vec.to_vec();
a.length = vec.len();
a
}
pub fn from_file(file: &mut std::fs::File) -> BinaryReader {
let mut a = BinaryReader::initialize();
let mut v: Vec<u8> = Vec::new();
a.length = file.read_to_end(&mut v).unwrap();
a.data = v;
a
}
pub fn set_endian(&mut self, endian: Endian) {
self.endian = endian
}
pub fn jmp(&mut self, pos: usize) {
self.pos = pos
}
pub fn adv(&mut self, size: usize) {
self.pos += size
}
pub fn align(&mut self, size: usize) {
self.pos = (self.pos + size - 1) / size * size
}
pub fn read(&mut self, size: usize) -> Option<&[u8]> {
let data = self.data.get(self.pos..self.pos + size);
self.pos += size;
data
}
pub fn read_cstr(&mut self) -> String { let mut data = self.data.clone().get(self.pos..self.length).unwrap().to_vec();
data.reverse();
let mut vec: Vec<u8> = Vec::new();
loop {
let a = data.pop().unwrap();
if a == 0x00 { self.pos += vec.len() + 1; return String::from_utf8(vec).unwrap() }
else { vec.push(a); }
}
}
pub fn read_i8(&mut self) -> std::io::Result<i8> {
let mut data = self.data.get(self.pos..self.pos + 1).unwrap();
self.pos += 1;
data.read_i8()
}
pub fn read_i16(&mut self) -> std::io::Result<i16> {
let mut data = self.data.get(self.pos..self.pos + 2).unwrap();
self.pos += 2;
match self.endian {
Endian::Big => data.read_i16::<BigEndian>(),
Endian::Little => data.read_i16::<LittleEndian>()
}
}
pub fn read_i32(&mut self) -> std::io::Result<i32> {
let mut data = self.data.get(self.pos..self.pos + 4).unwrap();
self.pos += 4;
match self.endian {
Endian::Big => data.read_i32::<BigEndian>(),
Endian::Little => data.read_i32::<LittleEndian>()
}
}
pub fn read_i64(&mut self) -> std::io::Result<i64> {
let mut data = self.data.get(self.pos..self.pos + 8).unwrap();
self.pos += 8;
match self.endian {
Endian::Big => data.read_i64::<BigEndian>(),
Endian::Little => data.read_i64::<LittleEndian>()
}
}
pub fn read_u8(&mut self) -> std::io::Result<u8> {
let mut data = self.data.get(self.pos..self.pos + 1).unwrap();
self.pos += 1;
data.read_u8()
}
pub fn read_u16(&mut self) -> std::io::Result<u16> {
let mut data = self.data.get(self.pos..self.pos + 2).unwrap();
self.pos += 2;
match self.endian {
Endian::Big => data.read_u16::<BigEndian>(),
Endian::Little => data.read_u16::<LittleEndian>()
}
}
pub fn read_u32(&mut self) -> std::io::Result<u32> {
let mut data = self.data.get(self.pos..self.pos + 4).unwrap();
self.pos += 4;
match self.endian {
Endian::Big => data.read_u32::<BigEndian>(),
Endian::Little => data.read_u32::<LittleEndian>()
}
}
pub fn read_u64(&mut self) -> std::io::Result<u64> {
let mut data = self.data.get(self.pos..self.pos + 8).unwrap();
self.pos += 8;
match self.endian {
Endian::Big => data.read_u64::<BigEndian>(),
Endian::Little => data.read_u64::<LittleEndian>()
}
}
}
#[cfg(test)]
mod tests;