Added ByteReader abstraction for file types
Getty Ritter
8 years ago
1 | use std::{fs,io,iter,slice,vec}; | |
2 | ||
3 | /// A `ByteReader` is just a tiny wrapper over a mutable byte iterator, so we | |
4 | /// can parse things more easily. | |
5 | pub struct ByteReader<Rd> { | |
6 | bytes: Rd, | |
7 | } | |
8 | ||
9 | pub type ByteReaderT = ByteReader<Iterator<Item=u8>>; | |
10 | ||
11 | const MK_OK: &'static Fn(io::Result<u8>) -> Option<u8> = &|s| s.ok(); | |
12 | ||
13 | impl<R: io::Read> | |
14 | ByteReader<iter::FilterMap<io::Bytes<R>, | |
15 | &'static Fn(io::Result<u8>) -> Option<u8>>> | |
16 | { | |
17 | /// Create a ByteReader from any type that implement Read | |
18 | pub fn from_reader(r: R) -> Self { | |
19 | let bytes = r.bytes().filter_map(MK_OK); | |
20 | ByteReader { bytes: bytes } | |
21 | } | |
22 | } | |
23 | ||
24 | impl ByteReader<iter::FilterMap<io::Bytes<fs::File>, | |
25 | &'static Fn(io::Result<u8>) -> Option<u8>>> | |
26 | { | |
27 | /// Create a reader by opening a named file for reading | |
28 | pub fn from_file(path: &str) -> io::Result<Self> { | |
29 | let f = try!(fs::File::open(path)); | |
30 | Ok(ByteReader::from_reader(f)) | |
31 | } | |
32 | } | |
33 | ||
34 | impl ByteReader<vec::IntoIter<u8>> { | |
35 | /// Create a reader from a vector of u8s | |
36 | pub fn from_vec(lst: Vec<u8>) -> Self { | |
37 | ByteReader { bytes: lst.into_iter() } | |
38 | } | |
39 | } | |
40 | ||
41 | impl<'a> ByteReader<slice::Iter<'a, u8>> { | |
42 | pub fn from_slice(lst: &'a [u8]) -> Self { | |
43 | ByteReader { bytes: lst.iter() } | |
44 | } | |
45 | } | |
46 | ||
47 | impl<T> ByteReader<T> where T: Iterator<Item=u8> { | |
48 | /// This gets the next byte, or fails if it's out of input. | |
49 | pub fn next(&mut self) -> Result<u8, String> { | |
50 | Ok(try!(self.bytes.next().ok_or("out of input"))) | |
51 | } | |
52 | ||
53 | /// This reads a one-byte or two-byte float in the rough range of | |
54 | /// (192 .. -128). We're going to treat all models as if they're | |
55 | /// supposed to be centered in a 64x64x64 square, so this gives | |
56 | /// us 128 units on either side of the central square, as well. | |
57 | pub fn read_twip(&mut self) -> Result<f32, String> { | |
58 | let b1 = try!(self.next()); | |
59 | if (b1 & 0x80) != 0 { | |
60 | let b2 = try!(self.next()); | |
61 | let val = ((b1 as u16 & 0x7f) << 8) | b2 as u16; | |
62 | Ok((val as f32 / 102.0) - 128.0) | |
63 | } else { | |
64 | Ok((b1 as f32) - 32.0) | |
65 | } | |
66 | } | |
67 | ||
68 | /// This reads a single byte and treats it as a ratio. | |
69 | pub fn read_ratio(&mut self) -> Result<f32, String> { | |
70 | let b = try!(self.next()); | |
71 | Ok(b as f32 / 255.0) | |
72 | } | |
73 | ||
74 | /// This reads a 64-bit int with a packed PrefixInteger representation. | |
75 | /// The shorter the int, the shorter the representation. | |
76 | pub fn read_prefix_int(&mut self) -> Result<u64, String> { | |
77 | fn match_bits(n: u8, mask: u8) -> bool { | |
78 | n & mask == mask | |
79 | } | |
80 | let b = try!(self.next()); | |
81 | if match_bits(b, 0xff) { self.continue_prefix_int(8, 0) } | |
82 | else if match_bits(b, 0xfe) { self.continue_prefix_int(7, 0) } | |
83 | else if match_bits(b, 0xfc) { self.continue_prefix_int(6, b & 0x01) } | |
84 | else if match_bits(b, 0xf8) { self.continue_prefix_int(5, b & 0x03) } | |
85 | else if match_bits(b, 0xf0) { self.continue_prefix_int(4, b & 0x07) } | |
86 | else if match_bits(b, 0xe0) { self.continue_prefix_int(3, b & 0x0f) } | |
87 | else if match_bits(b, 0xc0) { self.continue_prefix_int(2, b & 0x1f) } | |
88 | else if match_bits(b, 0x80) { self.continue_prefix_int(1, b & 0x3f) } | |
89 | else { self.continue_prefix_int(0, b) } | |
90 | } | |
91 | ||
92 | /// This is a helper function for parsing prefix ints, too. | |
93 | fn continue_prefix_int(&mut self, mut left: u8, upper: u8) -> Result<u64, String> { | |
94 | let mut ret = upper as u64; | |
95 | while left > 0 { | |
96 | left -= 1; | |
97 | ret = (ret << 8) | try!(self.next()) as u64; | |
98 | } | |
99 | Ok(ret) | |
100 | } | |
101 | ||
102 | /// This reads a PrefixInteger to find out how many other things to read, | |
103 | /// and then reads that number of things. | |
104 | pub fn read_several<F, R>(&mut self, reader: F) -> Result<Vec<R>, String> | |
105 | where F: Fn(&mut ByteReader<T>) -> Result<R, String> | |
106 | { | |
107 | let ct = try!(self.read_prefix_int()); | |
108 | let mut ret = Vec::with_capacity(ct as usize); | |
109 | for _ in 0..ct { | |
110 | ret.push(try!(reader(self))) | |
111 | } | |
112 | Ok(ret) | |
113 | } | |
114 | ||
115 | /// This reads a PrefixInteger number of bytes, and then parses those | |
116 | /// bytes as a UTF-8 string. This means, importantly, that we cannot | |
117 | /// naïvely produce values intended to be parsed with this using a | |
118 | /// basic string length. | |
119 | pub fn read_string(&mut self) -> Result<String, String> { | |
120 | let raw_bytes = try!(self.read_several(|r| r.next())); | |
121 | match String::from_utf8(raw_bytes) { | |
122 | Ok(s) => Ok(s), | |
123 | Err(e) => Err(format!("Exception when parsing UTF-8: {:?}", e)), | |
124 | } | |
125 | } | |
126 | } |