104 lines
2.2 KiB
Rust
104 lines
2.2 KiB
Rust
use std::ops;
|
|
|
|
use Result;
|
|
use binread::BinReadable;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Block {
|
|
origin: u32,
|
|
|
|
length: usize,
|
|
pointer: usize,
|
|
source: Vec<u8>
|
|
}
|
|
|
|
impl Block {
|
|
pub fn new(origin: u32, source: &[u8]) -> Block {
|
|
Block {
|
|
origin,
|
|
length: source.len(),
|
|
pointer: 0,
|
|
source: source.to_owned()
|
|
}
|
|
}
|
|
|
|
pub fn jump(&mut self, offset: i32) -> Result<()> {
|
|
if offset < 0 {
|
|
if (-offset as usize) > self.pointer {
|
|
return Err("Jump before block")
|
|
}
|
|
self.pointer -= -offset as usize;
|
|
} else {
|
|
if self.pointer + (offset as usize) >= self.length {
|
|
return Err("Jump outside of block")
|
|
}
|
|
self.pointer += offset as usize;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn seek(&mut self, location: usize) -> Result<()> {
|
|
if location >= self.length {
|
|
println!("hoho {}", location);
|
|
return Err("Seek outside of block")
|
|
}
|
|
self.pointer = location;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn read_string(&mut self) -> Result<String> {
|
|
let mut bytes = vec![];
|
|
|
|
loop {
|
|
let c = self.get()?;
|
|
|
|
if c == 0 {
|
|
return match String::from_utf8(bytes) {
|
|
Ok(string) => Ok(string),
|
|
_ => Err("Invalid string in block")
|
|
}
|
|
}
|
|
|
|
bytes.push(c);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
impl ops::Index<usize> for Block {
|
|
type Output = u8;
|
|
|
|
fn index(&self, index: usize) -> &<Self as ops::Index<usize>>::Output {
|
|
&self.source[index]
|
|
}
|
|
}
|
|
|
|
impl BinReadable for Block {
|
|
fn get(&mut self) -> Result<u8> {
|
|
if self.pointer >= self.length {
|
|
return Err("EOF reached")
|
|
}
|
|
let byte = self.source[self.pointer];
|
|
self.pointer += 1;
|
|
Ok(byte)
|
|
}
|
|
|
|
fn len(&self) -> usize {
|
|
self.source.len()
|
|
}
|
|
|
|
fn cur(&self) -> usize {
|
|
self.pointer
|
|
}
|
|
|
|
fn slice(&mut self, len: usize) -> &[u8] {
|
|
let slice = &self.source[self.pointer..self.pointer+len];
|
|
self.pointer += len;
|
|
slice
|
|
}
|
|
|
|
fn is_empty(&self) -> bool {
|
|
self.source.is_empty()
|
|
}
|
|
}
|