use std::{fs,io,iter,mem,slice,vec}; use bzip2::bufread::BzDecoder; /// A `ByteReader` is just a tiny wrapper over a mutable byte iterator, so we /// can parse things more easily. pub struct ByteReader { bytes: Rd, } impl ByteReader, &'static Fn(io::Result) -> Option>> { /// Create a ByteReader from any type that implement Read pub fn from_reader(r: R) -> Self { const MK_OK: &'static Fn(io::Result) -> Option = &io::Result::::ok; let bytes = r.bytes().filter_map(MK_OK); ByteReader { bytes: bytes } } } impl ByteReader, &'static Fn(io::Result) -> Option>> { /// Create a reader by opening a named file for reading pub fn from_file(path: &str) -> io::Result { let f = try!(fs::File::open(path)); Ok(ByteReader::from_reader(f)) } } impl ByteReader> { /// Create a reader from a vector of u8s pub fn from_vec(lst: Vec) -> Self { ByteReader { bytes: lst.into_iter() } } } impl<'a> ByteReader>> { /// Create a reader from a borrowed slice, with a copy on each access pub fn from_slice(lst: &'a [u8]) -> Self { ByteReader { bytes: lst.iter().cloned() } } } impl ByteReader>, &'static Fn(io::Result) -> Option>> { pub fn from_compressed_reader(r: R) -> Self { ByteReader::from_reader(BzDecoder::new(r)) } } impl ByteReader>>, &'static Fn(io::Result) -> Option>> { pub fn from_compressed_file(path: &str) -> io::Result { let f = try!(fs::File::open(path)); Ok(ByteReader::from_compressed_reader(io::BufReader::new(f))) } } #[test] fn reader_tests() { assert!(ByteReader::from_slice(&[0x00]).read_twip() == Ok(-32.0)); assert!(ByteReader::from_slice(&[0x00]).read_prefix_int() == Ok(0x00)); assert!(ByteReader::from_slice(&[0x7f]).read_prefix_int() == Ok(0x7f)); assert!(ByteReader::from_slice(&[0x80,0xff]).read_prefix_int() == Ok(0xff)); assert!(ByteReader::from_slice(&[0x03,0x00,0x00,0x00]) .read_several(|r| r.read_twip()) == Ok(vec![-32.0,-32.0,-32.0])); } impl ByteReader where T: Iterator { /// This gets the next byte, or fails if it's out of input. pub fn next(&mut self) -> Result { Ok(try!(self.bytes.next().ok_or("out of input"))) } /// This reads a one-byte or two-byte float in the rough range of /// (192 .. -128). We're going to treat all models as if they're /// supposed to be centered in a 64x64x64 square, so this gives /// us 128 units on either side of the central square, as well. pub fn read_twip(&mut self) -> Result { let b1 = try!(self.next()); if (b1 & 0x80) != 0 { let b2 = try!(self.next()); let val = ((b1 as u16 & 0x7f) << 8) | b2 as u16; Ok((val as f32 / 102.0) - 128.0) } else { Ok((b1 as f32) - 32.0) } } /// This reads a single byte and treats it as a ratio. pub fn read_ratio(&mut self) -> Result { let b = try!(self.next()); Ok(b as f32 / 255.0) } pub fn read_u32be(&mut self) -> Result { let a = try!(self.next()); let b = try!(self.next()); let c = try!(self.next()); let d = try!(self.next()); let rs = [ d, c, b, a ]; unsafe { Ok(mem::transmute::<[u8;4],u32>(rs)) } } pub fn read_u16be(&mut self) -> Result { let a = try!(self.next()); let b = try!(self.next()); let rs = [ b, a ]; unsafe { Ok(mem::transmute::<[u8;2],u16>(rs)) } } /// This reads a 64-bit int with a packed PrefixInteger representation. /// The shorter the int, the shorter the representation. pub fn read_prefix_int(&mut self) -> Result { fn match_bits(n: u8, mask: u8) -> bool { n & mask == mask } let b = try!(self.next()); if match_bits(b, 0xff) { self.continue_prefix_int(8, 0) } else if match_bits(b, 0xfe) { self.continue_prefix_int(7, 0) } else if match_bits(b, 0xfc) { self.continue_prefix_int(6, b & 0x01) } else if match_bits(b, 0xf8) { self.continue_prefix_int(5, b & 0x03) } else if match_bits(b, 0xf0) { self.continue_prefix_int(4, b & 0x07) } else if match_bits(b, 0xe0) { self.continue_prefix_int(3, b & 0x0f) } else if match_bits(b, 0xc0) { self.continue_prefix_int(2, b & 0x1f) } else if match_bits(b, 0x80) { self.continue_prefix_int(1, b & 0x3f) } else { self.continue_prefix_int(0, b) } } /// This is a helper function for parsing prefix ints, too. fn continue_prefix_int(&mut self, mut left: u8, upper: u8) -> Result { let mut ret = upper as u64; while left > 0 { left -= 1; ret = (ret << 8) | try!(self.next()) as u64; } Ok(ret) } /// This reads a PrefixInteger to find out how many other things to read, /// and then reads that number of things. pub fn read_several(&mut self, reader: F) -> Result, String> where F: Fn(&mut ByteReader) -> Result { let ct = try!(self.read_prefix_int()); let mut ret = Vec::with_capacity(ct as usize); for _ in 0..ct { ret.push(try!(reader(self))) } Ok(ret) } /// This reads a PrefixInteger number of bytes, and then parses those /// bytes as a UTF-8 string. This means, importantly, that we cannot /// naïvely produce values intended to be parsed with this using a /// basic string length. pub fn read_string(&mut self) -> Result { let raw_bytes = try!(self.read_several(|r| r.next())); match String::from_utf8(raw_bytes) { Ok(s) => Ok(s), Err(e) => Err(format!("Exception when parsing UTF-8: {:?}", e)), } } }