use std::ops; use Result; use binread::BinReadable; #[derive(Debug)] pub struct Block { origin: u32, length: usize, pointer: usize, source: Vec } 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 { 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 for Block { type Output = u8; fn index(&self, index: usize) -> &>::Output { &self.source[index] } } impl BinReadable for Block { fn get(&mut self) -> Result { 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() } }