1 | use super::*; |
2 | |
3 | pub struct Blob { |
4 | file: &'static File, |
5 | slice: &'static [u8], |
6 | } |
7 | |
8 | impl std::ops::Deref for Blob { |
9 | type Target = [u8]; |
10 | |
11 | fn deref(&self) -> &[u8] { |
12 | self.slice |
13 | } |
14 | } |
15 | |
16 | impl Blob { |
17 | pub fn new(file: &'static File, slice: &'static [u8]) -> Self { |
18 | Self { file, slice } |
19 | } |
20 | |
21 | pub fn reader(&self) -> &'static Reader { |
22 | self.file.reader() |
23 | } |
24 | |
25 | fn peek(&self) -> (usize, usize) { |
26 | if self[0] & 0x80 == 0 { |
27 | (self[0] as usize, 1) |
28 | } else if self[0] & 0xC0 == 0x80 { |
29 | ((((self[0] & 0x3F) as usize) << 8) | self[1] as usize, 2) |
30 | } else { |
31 | ( |
32 | (((self[0] & 0x1F) as usize) << 24) |
33 | | ((self[1] as usize) << 16) |
34 | | ((self[2] as usize) << 8) |
35 | | self[3] as usize, |
36 | 4, |
37 | ) |
38 | } |
39 | } |
40 | |
41 | pub fn decode<D: Decode>(&mut self) -> D { |
42 | D::decode(self.file, self.read_usize()) |
43 | } |
44 | |
45 | pub fn try_read(&mut self, expected: usize) -> bool { |
46 | let (value, offset) = self.peek(); |
47 | if value == expected { |
48 | self.offset(offset); |
49 | true |
50 | } else { |
51 | false |
52 | } |
53 | } |
54 | |
55 | pub fn read_modifiers(&mut self) -> Vec<TypeDefOrRef> { |
56 | let mut mods = vec![]; |
57 | loop { |
58 | let (value, offset) = self.peek(); |
59 | if value != ELEMENT_TYPE_CMOD_OPT as usize && value != ELEMENT_TYPE_CMOD_REQD as usize { |
60 | break; |
61 | } else { |
62 | self.offset(offset); |
63 | mods.push(TypeDefOrRef::decode(self.file, self.read_usize())) |
64 | } |
65 | } |
66 | mods |
67 | } |
68 | |
69 | pub fn read_usize(&mut self) -> usize { |
70 | let (value, offset) = self.peek(); |
71 | self.offset(offset); |
72 | value |
73 | } |
74 | |
75 | pub fn read_str(&mut self) -> &'static str { |
76 | let len = self.read_usize(); |
77 | let value = unsafe { std::str::from_utf8_unchecked(&self.slice[..len]) }; |
78 | self.offset(len); |
79 | value |
80 | } |
81 | |
82 | pub fn read_utf16(self) -> String { |
83 | let slice = self.slice; |
84 | if slice.as_ptr().align_offset(std::mem::align_of::<u16>()) > 0 { |
85 | let slice = slice |
86 | .chunks_exact(2) |
87 | .take(slice.len() / 2) |
88 | .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())) |
89 | .collect::<Vec<u16>>(); |
90 | String::from_utf16_lossy(&slice) |
91 | } else { |
92 | let slice = unsafe { |
93 | std::slice::from_raw_parts(slice.as_ptr() as *const u16, slice.len() / 2) |
94 | }; |
95 | String::from_utf16_lossy(slice) |
96 | } |
97 | } |
98 | |
99 | pub fn read_bool(&mut self) -> bool { |
100 | // A bool is specified as "a single byte with value 0 (false) or 1 (true)". |
101 | match self.read_u8() { |
102 | 0 => false, |
103 | 1 => true, |
104 | _ => panic!(), |
105 | } |
106 | } |
107 | |
108 | pub fn read_i8(&mut self) -> i8 { |
109 | let value = i8::from_le_bytes(self[..1].try_into().unwrap()); |
110 | self.offset(1); |
111 | value |
112 | } |
113 | |
114 | pub fn read_u8(&mut self) -> u8 { |
115 | let value = u8::from_le_bytes(self[..1].try_into().unwrap()); |
116 | self.offset(1); |
117 | value |
118 | } |
119 | |
120 | pub fn read_i16(&mut self) -> i16 { |
121 | let value = i16::from_le_bytes(self[..2].try_into().unwrap()); |
122 | self.offset(2); |
123 | value |
124 | } |
125 | |
126 | pub fn read_u16(&mut self) -> u16 { |
127 | let value = u16::from_le_bytes(self[..2].try_into().unwrap()); |
128 | self.offset(2); |
129 | value |
130 | } |
131 | |
132 | pub fn read_i32(&mut self) -> i32 { |
133 | let value = i32::from_le_bytes(self[..4].try_into().unwrap()); |
134 | self.offset(4); |
135 | value |
136 | } |
137 | |
138 | pub fn read_u32(&mut self) -> u32 { |
139 | let value = u32::from_le_bytes(self[..4].try_into().unwrap()); |
140 | self.offset(4); |
141 | value |
142 | } |
143 | |
144 | pub fn read_i64(&mut self) -> i64 { |
145 | let value = i64::from_le_bytes(self[..8].try_into().unwrap()); |
146 | self.offset(8); |
147 | value |
148 | } |
149 | |
150 | pub fn read_u64(&mut self) -> u64 { |
151 | let value = u64::from_le_bytes(self[..8].try_into().unwrap()); |
152 | self.offset(8); |
153 | value |
154 | } |
155 | |
156 | pub fn read_f32(&mut self) -> f32 { |
157 | let value = f32::from_le_bytes(self[..4].try_into().unwrap()); |
158 | self.offset(4); |
159 | value |
160 | } |
161 | |
162 | pub fn read_f64(&mut self) -> f64 { |
163 | let value = f64::from_le_bytes(self[..8].try_into().unwrap()); |
164 | self.offset(8); |
165 | value |
166 | } |
167 | |
168 | pub fn read_integer(&mut self, ty: Type) -> Value { |
169 | match ty { |
170 | Type::I8 => Value::I8(self.read_i8()), |
171 | Type::U8 => Value::U8(self.read_u8()), |
172 | Type::I16 => Value::I16(self.read_i16()), |
173 | Type::U16 => Value::U16(self.read_u16()), |
174 | Type::I32 => Value::I32(self.read_i32()), |
175 | Type::U32 => Value::U32(self.read_u32()), |
176 | Type::I64 => Value::I64(self.read_i64()), |
177 | Type::U64 => Value::U64(self.read_u64()), |
178 | _ => panic!(), |
179 | } |
180 | } |
181 | |
182 | fn offset(&mut self, offset: usize) { |
183 | self.slice = &self.slice[offset..]; |
184 | } |
185 | } |
186 | |