windows_metadata/reader/
blob.rs1use super::*;
2
3pub struct Blob<'a> {
4 index: &'a Index,
5 file: usize,
6 slice: &'a [u8],
7}
8
9impl Drop for Blob<'_> {
10 fn drop(&mut self) {
11 debug_assert_eq!(self.len(), 0);
12 }
13}
14
15impl std::fmt::Debug for Blob<'_> {
16 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
17 write!(f, "{:?}", self.slice)
18 }
19}
20
21impl std::ops::Deref for Blob<'_> {
22 type Target = [u8];
23
24 fn deref(&self) -> &[u8] {
25 self.slice
26 }
27}
28
29impl<'a> Blob<'a> {
30 pub fn new(index: &'a Index, file: usize, slice: &'a [u8]) -> Self {
31 Self { index, file, slice }
32 }
33
34 fn peek(&self) -> (usize, usize) {
35 if self[0] & 0x80 == 0 {
36 (self[0] as usize, 1)
37 } else if self[0] & 0xC0 == 0x80 {
38 ((((self[0] & 0x3F) as usize) << 8) | self[1] as usize, 2)
39 } else {
40 (
41 (((self[0] & 0x1F) as usize) << 24)
42 | ((self[1] as usize) << 16)
43 | ((self[2] as usize) << 8)
44 | self[3] as usize,
45 4,
46 )
47 }
48 }
49
50 pub fn decode<D: Decode<'a>>(&mut self) -> D {
51 D::decode(self.index, self.file, self.read_compressed())
52 }
53
54 pub fn try_read(&mut self, expected: usize) -> bool {
55 let (value, offset) = self.peek();
56 if value == expected {
57 self.offset(offset);
58 true
59 } else {
60 false
61 }
62 }
63
64 pub fn read_modifiers(&mut self) -> Vec<TypeDefOrRef<'a>> {
65 let mut mods = vec![];
66 loop {
67 let (value, offset) = self.peek();
68 if value != ELEMENT_TYPE_CMOD_OPT as usize && value != ELEMENT_TYPE_CMOD_REQD as usize {
69 break;
70 } else {
71 self.offset(offset);
72 mods.push(TypeDefOrRef::decode(
73 self.index,
74 self.file,
75 self.read_compressed(),
76 ));
77 }
78 }
79 mods
80 }
81
82 pub fn read_method_signature(&mut self, generics: &[Type]) -> Signature {
83 let flags = MethodCallAttributes(self.read_u8());
84 let param_count = self.read_compressed();
85 let return_type = self.read_type_signature(generics);
86
87 let mut types = vec![];
88
89 for _ in 0..param_count {
90 types.push(self.read_type_signature(generics));
91 }
92
93 Signature {
94 flags,
95 return_type,
96 types,
97 }
98 }
99
100 pub fn read_type_signature(&mut self, generics: &[Type]) -> Type {
102 let is_const = self.read_modifiers().iter().any(|def| {
103 def.namespace() == "System.Runtime.CompilerServices" && def.name() == "IsConst"
104 });
105
106 let is_ref = self.try_read(ELEMENT_TYPE_BYREF as usize);
107
108 if self.try_read(ELEMENT_TYPE_VOID as usize) {
109 return Type::Void;
110 }
111
112 let is_array = self.try_read(ELEMENT_TYPE_SZARRAY as usize);
113
114 let mut pointers = 0;
115
116 while self.try_read(ELEMENT_TYPE_PTR as usize) {
117 pointers += 1;
118 }
119
120 let ty = self.read_type_code(generics);
121
122 if pointers > 0 {
123 let ptr = if is_const {
124 Type::PtrConst(Box::new(ty), pointers)
125 } else {
126 Type::PtrMut(Box::new(ty), pointers)
127 };
128 if is_array {
129 Type::Array(Box::new(ptr))
130 } else {
131 ptr
132 }
133 } else if is_const {
134 Type::RefConst(Box::new(ty))
135 } else if is_array {
136 let ty = Type::Array(Box::new(ty));
137
138 if is_ref {
139 Type::RefMut(Box::new(ty))
140 } else {
141 ty
142 }
143 } else if is_ref {
144 Type::RefMut(Box::new(ty))
145 } else {
146 ty
147 }
148 }
149
150 pub fn read_type_code(&mut self, generics: &[Type]) -> Type {
151 match self.read_u8() {
152 ELEMENT_TYPE_VOID => Type::Void,
153 ELEMENT_TYPE_BOOLEAN => Type::Bool,
154 ELEMENT_TYPE_CHAR => Type::Char,
155 ELEMENT_TYPE_I1 => Type::I8,
156 ELEMENT_TYPE_U1 => Type::U8,
157 ELEMENT_TYPE_I2 => Type::I16,
158 ELEMENT_TYPE_U2 => Type::U16,
159 ELEMENT_TYPE_I4 => Type::I32,
160 ELEMENT_TYPE_U4 => Type::U32,
161 ELEMENT_TYPE_I8 => Type::I64,
162 ELEMENT_TYPE_U8 => Type::U64,
163 ELEMENT_TYPE_R4 => Type::F32,
164 ELEMENT_TYPE_R8 => Type::F64,
165 ELEMENT_TYPE_I => Type::ISize,
166 ELEMENT_TYPE_U => Type::USize,
167 ELEMENT_TYPE_STRING => Type::String,
168 ELEMENT_TYPE_OBJECT => Type::Object,
169 ELEMENT_TYPE_VALUETYPE => {
170 let tdr = self.decode::<TypeDefOrRef>();
171 if let TypeDefOrRef::TypeSpec(def) = tdr {
172 def.ty(generics)
173 } else {
174 Type::ValueName(TypeName::named(tdr.namespace(), tdr.name()))
175 }
176 }
177 ELEMENT_TYPE_CLASS => {
178 let tdr = self.decode::<TypeDefOrRef>();
179 if let TypeDefOrRef::TypeSpec(def) = tdr {
180 def.ty(generics)
181 } else {
182 Type::ClassName(TypeName::named(tdr.namespace(), tdr.name()))
183 }
184 }
185 ELEMENT_TYPE_VAR => generics[self.read_compressed()].clone(),
186 ELEMENT_TYPE_ARRAY => {
187 let ty = self.read_type_signature(generics);
189 let rank = self.read_compressed();
190 debug_assert_eq!(rank, 1);
191 let num_sizes = self.read_compressed();
192 debug_assert_eq!(num_sizes, 1);
193 let size = self.read_compressed();
194 let num_lo_bounds = self.read_compressed();
195 debug_assert!(num_lo_bounds == 0 || num_lo_bounds == 1);
196
197 for _ in 0..num_lo_bounds {
198 let lo_bounds = self.read_compressed();
199 debug_assert_eq!(lo_bounds, 0);
200 }
201
202 Type::ArrayFixed(Box::new(ty), size)
203 }
204 ELEMENT_TYPE_GENERICINST => {
205 let type_code = self.read_u8();
206
207 debug_assert!(matches!(
208 type_code,
209 ELEMENT_TYPE_VALUETYPE | ELEMENT_TYPE_CLASS
210 ));
211
212 let ty = self.decode::<TypeDefOrRef>();
213 let mut ty_generics = vec![];
214
215 for _ in 0..self.read_compressed() {
216 ty_generics.push(self.read_type_code(generics));
217 }
218
219 let type_name = TypeName {
220 namespace: ty.namespace().to_string(),
221 name: ty.name().to_string(),
222 generics: ty_generics,
223 };
224
225 if type_code == ELEMENT_TYPE_VALUETYPE {
226 Type::ValueName(type_name)
227 } else {
228 Type::ClassName(type_name)
229 }
230 }
231 0x55 => {
232 let name = self.read_utf8();
236 if let Some(dot) = name.rfind('.') {
237 Type::ValueName(TypeName::named(&name[..dot], &name[dot + 1..]))
238 } else {
239 Type::ValueName(TypeName::named("", &name))
240 }
241 }
242 rest => panic!("{rest:?}"),
243 }
244 }
245
246 pub fn read_compressed(&mut self) -> usize {
247 let (value, offset) = self.peek();
248 self.offset(offset);
249 value
250 }
251
252 pub fn read_utf8(&mut self) -> String {
253 let len = self.read_compressed();
254 let value = std::str::from_utf8(&self.slice[..len]).expect("expected valid UTF-8 string");
255 self.offset(len);
256 value.to_string()
257 }
258
259 pub fn read_utf16(&mut self) -> String {
260 let slice = self.slice;
261
262 let value = if cfg!(target_endian = "little") {
263 let (prefix, chars, suffix) = unsafe { slice.align_to::<u16>() };
268 if prefix.is_empty() && suffix.is_empty() {
269 String::from_utf16_lossy(chars)
270 } else {
271 let chars: Vec<u16> = slice
272 .as_chunks::<2>()
273 .0
274 .iter()
275 .map(|chunk| u16::from_le_bytes(*chunk))
276 .collect();
277 String::from_utf16_lossy(&chars)
278 }
279 } else {
280 let chars: Vec<u16> = slice
281 .as_chunks::<2>()
282 .0
283 .iter()
284 .map(|chunk| u16::from_le_bytes(*chunk))
285 .collect();
286 String::from_utf16_lossy(&chars)
287 };
288
289 self.offset(slice.len());
290 value
291 }
292
293 pub fn read_bool(&mut self) -> bool {
294 match self.read_u8() {
296 0 => false,
297 1 => true,
298 _ => panic!(),
299 }
300 }
301
302 pub fn read_i8(&mut self) -> i8 {
303 let value = i8::from_le_bytes(self[..1].try_into().unwrap());
304 self.offset(1);
305 value
306 }
307
308 pub fn read_u8(&mut self) -> u8 {
309 let value = u8::from_le_bytes(self[..1].try_into().unwrap());
310 self.offset(1);
311 value
312 }
313
314 pub fn read_i16(&mut self) -> i16 {
315 let value = i16::from_le_bytes(self[..2].try_into().unwrap());
316 self.offset(2);
317 value
318 }
319
320 pub fn read_u16(&mut self) -> u16 {
321 let value = u16::from_le_bytes(self[..2].try_into().unwrap());
322 self.offset(2);
323 value
324 }
325
326 pub fn read_i32(&mut self) -> i32 {
327 let value = i32::from_le_bytes(self[..4].try_into().unwrap());
328 self.offset(4);
329 value
330 }
331
332 pub fn read_u32(&mut self) -> u32 {
333 let value = u32::from_le_bytes(self[..4].try_into().unwrap());
334 self.offset(4);
335 value
336 }
337
338 pub fn read_i64(&mut self) -> i64 {
339 let value = i64::from_le_bytes(self[..8].try_into().unwrap());
340 self.offset(8);
341 value
342 }
343
344 pub fn read_u64(&mut self) -> u64 {
345 let value = u64::from_le_bytes(self[..8].try_into().unwrap());
346 self.offset(8);
347 value
348 }
349
350 pub fn read_f32(&mut self) -> f32 {
351 let value = f32::from_le_bytes(self[..4].try_into().unwrap());
352 self.offset(4);
353 value
354 }
355
356 pub fn read_f64(&mut self) -> f64 {
357 let value = f64::from_le_bytes(self[..8].try_into().unwrap());
358 self.offset(8);
359 value
360 }
361
362 fn offset(&mut self, offset: usize) {
363 self.slice = &self.slice[offset..];
364 }
365}