1extern crate byteorder;
22
23use byteorder::{BigEndian, LittleEndian, NativeEndian, ReadBytesExt};
24use std::io::{prelude::*, Error, ErrorKind};
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum Endian {
29 Big,
31 Little,
33 Native,
36 Network,
39}
40
41#[doc(hidden)]
42macro_rules! read_number {
45 ($name:ident, $ty: ty, $bytes: expr, $doc: expr) => {
46 #[doc = $doc]
47 pub fn $name(&mut self) -> std::io::Result<$ty> {
48 let endianness = self.endian;
49 let mut data = self.read_bytes($bytes)?;
50 match endianness {
51 Endian::Big | Endian::Network => data.$name::<BigEndian>(),
52 Endian::Little => data.$name::<LittleEndian>(),
53 Endian::Native => data.$name::<NativeEndian>(),
54 }
55 }
56 };
57
58 ($name:ident, $ty: ty, $doc: expr) => {
59 #[doc = $doc]
60 pub fn $name(&mut self) -> std::io::Result<$ty> {
61 let mut data = self.read_bytes(1)?;
62 data.$name()
63 }
64 };
65}
66#[derive(Debug, Clone)]
68pub struct BinaryReader {
69 pub data: Vec<u8>,
71 pub pos: usize,
73 pub length: usize,
75 pub endian: Endian,
77}
78
79impl BinaryReader {
80 #[doc(hidden)]
81 fn initialize() -> BinaryReader {
82 BinaryReader {
83 data: Vec::new(),
84 pos: 0,
85 length: 0,
86 endian: Endian::Big,
87 }
88 }
89
90 pub fn from_u8(get: &[u8]) -> BinaryReader {
92 let mut a = BinaryReader::initialize();
93 a.data = get.to_vec();
94 a.length = get.len();
95 a
96 }
97
98 #[allow(clippy::ptr_arg)] pub fn from_vec(vec: &Vec<u8>) -> BinaryReader {
101 let mut a = BinaryReader::initialize();
102 a.data = vec.to_vec();
103 a.length = vec.len();
104 a
105 }
106
107 pub fn from_file(file: &mut std::fs::File) -> BinaryReader {
109 let mut a = BinaryReader::initialize();
110 let mut v: Vec<u8> = Vec::new();
111 a.length = file.read_to_end(&mut v).unwrap();
112 a.data = v;
113 a
114 }
115
116 pub fn set_endian(&mut self, endian: Endian) {
118 self.endian = endian
119 }
120
121 pub fn jmp(&mut self, pos: usize) {
123 self.pos = pos
124 }
125
126 pub fn adv(&mut self, size: usize) {
127 self.pos += size
128 }
129
130 pub fn align(&mut self, size: usize) {
131 self.pos = (self.pos + size - 1) / size * size
132 }
133
134 pub fn read(&mut self, size: usize) -> Option<&[u8]> {
136 let data = self.data.get(self.pos..self.pos + size);
137 self.pos += size;
138 data
139 }
140
141 pub fn read_bytes(&mut self, bytes: usize) -> std::io::Result<&[u8]> {
144 let data = self.data.get(self.pos..self.pos + bytes).ok_or_else(|| {
145 Error::new(
146 ErrorKind::UnexpectedEof,
147 format!("failed to read {} bytes from offset {}", bytes, self.pos),
148 )
149 })?;
150 self.pos += bytes;
151
152 Ok(data)
153 }
154
155 #[doc(hidden)]
156 fn read_cstr_post(&self) -> std::io::Result<Vec<u8>> {
159 let mut data = self
161 .data
162 .clone()
163 .get(self.pos..self.length)
164 .ok_or_else(|| {
165 Error::new(
166 ErrorKind::UnexpectedEof,
167 format!(
168 "failed to read {} bytes from offset {}",
169 self.length - self.pos,
170 self.pos
171 ),
172 )
173 })?
174 .to_vec();
175 data.reverse();
176 Ok(data)
177 }
178
179 pub fn read_cstr(&mut self) -> std::io::Result<String> {
181 let mut data = self.read_cstr_post()?;
182 let mut vec: Vec<u8> = Vec::new();
183 loop {
184 let a = data.pop().unwrap();
185 if a == 0x00 {
186 self.pos += vec.len() + 1;
187 return String::from_utf8(vec).map_err(|err| {
188 Error::new(
189 ErrorKind::InvalidData,
190 format!("failed to convert to string: {:?}", err),
191 )
192 });
193 } else {
194 vec.push(a);
195 }
196 }
197 }
198
199 pub fn read_cstr_lossy(&mut self) -> std::io::Result<String> {
201 let mut data = self.read_cstr_post()?;
202 let mut vec: Vec<u8> = Vec::new();
203 loop {
204 let a = data.pop().unwrap();
205 if a == 0x00 {
206 self.pos += vec.len() + 1;
207 return Ok(String::from_utf8_lossy(&vec).to_string());
208 } else {
209 vec.push(a);
210 }
211 }
212 }
213
214 pub fn read_bool(&mut self) -> std::io::Result<bool> {
217 let data = self.read_bytes(1)?;
218 Ok(data[0] != 0)
219 }
220
221 read_number!(read_i8, i8, "Read signed 8 bit integer.");
223 read_number!(read_i16, i16, 2, "Read signed 16 bit integer.");
224 read_number!(
225 read_i24,
226 i32,
227 3,
228 "Read signed 24 bit integer. Stored in i32."
229 );
230 read_number!(read_i32, i32, 4, "Read signed 32 bit integer.");
231 read_number!(
232 read_i48,
233 i64,
234 6,
235 "Read signed 48 bit integer. Stored in i64."
236 );
237 read_number!(read_i64, i64, 8, "Read signed 64 bit integer.");
238 read_number!(read_i128, i128, 16, "Read signed 128 bit integer.");
239
240 read_number!(read_u8, u8, "Read unsigned 8 bit integer.");
242 read_number!(read_u16, u16, 2, "Read unsigned 16 bit integer.");
243 read_number!(
244 read_u24,
245 u32,
246 3,
247 "Read unsigned 24 bit integer. Stored in u32."
248 );
249 read_number!(read_u32, u32, 4, "Read unsigned 32 bit integer.");
250 read_number!(
251 read_u48,
252 u64,
253 6,
254 "Read unsigned 48 bit integer. Stored in u64."
255 );
256 read_number!(read_u64, u64, 8, "Read unsigned 64 bit integer.");
257 read_number!(read_u128, u128, 16, "Read unsigned 128 bit integer.");
258
259 read_number!(read_f32, f32, 4, "Read 32 bit floating point number.");
261 read_number!(read_f64, f64, 8, "Read 64 bit floating point number.");
262}
263
264#[cfg(test)]
265mod tests;