unity_asset_binary/
reader.rs1use crate::error::{BinaryError, Result};
4use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
5use std::io::{Cursor, Read, Seek, SeekFrom};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
9pub enum ByteOrder {
10 Big,
12 #[default]
14 Little,
15}
16
17pub struct BinaryReader<'a> {
19 cursor: Cursor<&'a [u8]>,
20 byte_order: ByteOrder,
21}
22
23impl<'a> BinaryReader<'a> {
24 pub fn new(data: &'a [u8], byte_order: ByteOrder) -> Self {
26 Self {
27 cursor: Cursor::new(data),
28 byte_order,
29 }
30 }
31
32 pub fn position(&self) -> u64 {
34 self.cursor.position()
35 }
36
37 pub fn set_position(&mut self, pos: u64) -> Result<()> {
39 self.cursor.set_position(pos);
40 Ok(())
41 }
42
43 pub fn seek(&mut self, offset: i64) -> Result<u64> {
45 Ok(self.cursor.seek(SeekFrom::Current(offset))?)
46 }
47
48 pub fn len(&self) -> usize {
50 self.cursor.get_ref().len()
51 }
52
53 pub fn is_empty(&self) -> bool {
55 self.len() == 0
56 }
57
58 pub fn remaining(&self) -> usize {
60 self.len().saturating_sub(self.position() as usize)
61 }
62
63 pub fn has_bytes(&self, count: usize) -> bool {
65 self.remaining() >= count
66 }
67
68 pub fn align(&mut self) -> Result<()> {
70 self.align_to(4)
71 }
72
73 pub fn align_to(&mut self, alignment: u64) -> Result<()> {
75 let pos = self.position();
76 let aligned = (pos + alignment - 1) & !(alignment - 1);
77 if aligned != pos {
78 self.set_position(aligned)?;
79 }
80 Ok(())
81 }
82
83 pub fn read_u8(&mut self) -> Result<u8> {
85 if !self.has_bytes(1) {
86 return Err(BinaryError::not_enough_data(1, self.remaining()));
87 }
88 Ok(self.cursor.read_u8()?)
89 }
90
91 pub fn read_bool(&mut self) -> Result<bool> {
93 Ok(self.read_u8()? != 0)
94 }
95
96 pub fn read_i8(&mut self) -> Result<i8> {
98 Ok(self.read_u8()? as i8)
99 }
100
101 pub fn read_u16(&mut self) -> Result<u16> {
103 if !self.has_bytes(2) {
104 return Err(BinaryError::not_enough_data(2, self.remaining()));
105 }
106 match self.byte_order {
107 ByteOrder::Big => Ok(self.cursor.read_u16::<BigEndian>()?),
108 ByteOrder::Little => Ok(self.cursor.read_u16::<LittleEndian>()?),
109 }
110 }
111
112 pub fn read_i16(&mut self) -> Result<i16> {
114 if !self.has_bytes(2) {
115 return Err(BinaryError::not_enough_data(2, self.remaining()));
116 }
117 match self.byte_order {
118 ByteOrder::Big => Ok(self.cursor.read_i16::<BigEndian>()?),
119 ByteOrder::Little => Ok(self.cursor.read_i16::<LittleEndian>()?),
120 }
121 }
122
123 pub fn read_u32(&mut self) -> Result<u32> {
125 if !self.has_bytes(4) {
126 return Err(BinaryError::not_enough_data(4, self.remaining()));
127 }
128 match self.byte_order {
129 ByteOrder::Big => Ok(self.cursor.read_u32::<BigEndian>()?),
130 ByteOrder::Little => Ok(self.cursor.read_u32::<LittleEndian>()?),
131 }
132 }
133
134 pub fn read_i32(&mut self) -> Result<i32> {
136 if !self.has_bytes(4) {
137 return Err(BinaryError::not_enough_data(4, self.remaining()));
138 }
139 match self.byte_order {
140 ByteOrder::Big => Ok(self.cursor.read_i32::<BigEndian>()?),
141 ByteOrder::Little => Ok(self.cursor.read_i32::<LittleEndian>()?),
142 }
143 }
144
145 pub fn read_u64(&mut self) -> Result<u64> {
147 if !self.has_bytes(8) {
148 return Err(BinaryError::not_enough_data(8, self.remaining()));
149 }
150 match self.byte_order {
151 ByteOrder::Big => Ok(self.cursor.read_u64::<BigEndian>()?),
152 ByteOrder::Little => Ok(self.cursor.read_u64::<LittleEndian>()?),
153 }
154 }
155
156 pub fn read_i64(&mut self) -> Result<i64> {
158 if !self.has_bytes(8) {
159 return Err(BinaryError::not_enough_data(8, self.remaining()));
160 }
161 match self.byte_order {
162 ByteOrder::Big => Ok(self.cursor.read_i64::<BigEndian>()?),
163 ByteOrder::Little => Ok(self.cursor.read_i64::<LittleEndian>()?),
164 }
165 }
166
167 pub fn read_f32(&mut self) -> Result<f32> {
169 if !self.has_bytes(4) {
170 return Err(BinaryError::not_enough_data(4, self.remaining()));
171 }
172 match self.byte_order {
173 ByteOrder::Big => Ok(self.cursor.read_f32::<BigEndian>()?),
174 ByteOrder::Little => Ok(self.cursor.read_f32::<LittleEndian>()?),
175 }
176 }
177
178 pub fn read_f64(&mut self) -> Result<f64> {
180 if !self.has_bytes(8) {
181 return Err(BinaryError::not_enough_data(8, self.remaining()));
182 }
183 match self.byte_order {
184 ByteOrder::Big => Ok(self.cursor.read_f64::<BigEndian>()?),
185 ByteOrder::Little => Ok(self.cursor.read_f64::<LittleEndian>()?),
186 }
187 }
188
189 pub fn read_bytes(&mut self, count: usize) -> Result<Vec<u8>> {
191 if !self.has_bytes(count) {
192 return Err(BinaryError::not_enough_data(count, self.remaining()));
193 }
194 let mut buffer = vec![0u8; count];
195 self.cursor.read_exact(&mut buffer)?;
196 Ok(buffer)
197 }
198
199 pub fn read_remaining(&mut self) -> &[u8] {
201 let pos = self.cursor.position() as usize;
202 let data = self.cursor.get_ref();
203 &data[pos..]
204 }
205
206 pub fn read_cstring(&mut self) -> Result<String> {
208 let mut bytes = Vec::new();
209 loop {
210 let byte = self.read_u8()?;
211 if byte == 0 {
212 break;
213 }
214 bytes.push(byte);
215 }
216 Ok(String::from_utf8(bytes)?)
217 }
218
219 pub fn read_string(&mut self) -> Result<String> {
221 let length = self.read_u32()? as usize;
222 let bytes = self.read_bytes(length)?;
223 Ok(String::from_utf8(bytes)?)
224 }
225
226 pub fn read_string_fixed(&mut self, length: usize) -> Result<String> {
228 let bytes = self.read_bytes(length)?;
229 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
231 Ok(String::from_utf8(bytes[..end].to_vec())?)
232 }
233
234 pub fn read_aligned_string(&mut self) -> Result<String> {
236 let string = self.read_string()?;
237 self.align()?;
239 Ok(string)
240 }
241
242 pub fn byte_order(&self) -> ByteOrder {
244 self.byte_order
245 }
246
247 pub fn set_byte_order(&mut self, byte_order: ByteOrder) {
249 self.byte_order = byte_order;
250 }
251
252 pub fn remaining_slice(&self) -> &[u8] {
254 let pos = self.position() as usize;
255 &self.cursor.get_ref()[pos..]
256 }
257
258 pub fn sub_reader(&self, offset: usize, length: usize) -> Result<BinaryReader<'a>> {
260 let data = self.cursor.get_ref();
261 if offset + length > data.len() {
262 return Err(BinaryError::not_enough_data(offset + length, data.len()));
263 }
264 Ok(BinaryReader::new(
265 &data[offset..offset + length],
266 self.byte_order,
267 ))
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274
275 #[test]
276 fn test_basic_reading() {
277 let data = [0x01, 0x02, 0x03, 0x04];
278 let mut reader = BinaryReader::new(&data, ByteOrder::Little);
279
280 assert_eq!(reader.read_u8().unwrap(), 0x01);
281 assert_eq!(reader.read_u8().unwrap(), 0x02);
282 assert_eq!(reader.position(), 2);
283 assert_eq!(reader.remaining(), 2);
284 }
285
286 #[test]
287 fn test_endianness() {
288 let data = [0x01, 0x02, 0x03, 0x04];
289
290 let mut reader_le = BinaryReader::new(&data, ByteOrder::Little);
291 assert_eq!(reader_le.read_u32().unwrap(), 0x04030201);
292
293 let mut reader_be = BinaryReader::new(&data, ByteOrder::Big);
294 assert_eq!(reader_be.read_u32().unwrap(), 0x01020304);
295 }
296
297 #[test]
298 fn test_string_reading() {
299 let data = b"Hello\0World\0";
300 let mut reader = BinaryReader::new(data, ByteOrder::Little);
301
302 assert_eq!(reader.read_cstring().unwrap(), "Hello");
303 assert_eq!(reader.read_cstring().unwrap(), "World");
304 }
305
306 #[test]
307 fn test_alignment() {
308 let data = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
309 let mut reader = BinaryReader::new(&data, ByteOrder::Little);
310
311 reader.read_u8().unwrap(); reader.align().unwrap(); assert_eq!(reader.position(), 4);
314 }
315}