1use super::*;
2
3pub struct File {
4 bytes: Vec<u8>,
5 strings: usize,
6 blobs: usize,
7 tables: [Table; 18],
8}
9
10impl File {
11 pub fn read<P: AsRef<std::path::Path>>(path: P) -> Option<Self> {
12 std::fs::read(path).ok().and_then(Self::new)
13 }
14
15 pub fn new(bytes: Vec<u8>) -> Option<Self> {
16 let mut result = Self {
17 bytes,
18 strings: 0,
19 blobs: 0,
20 tables: Default::default(),
21 };
22
23 let dos = result.bytes.view_as::<IMAGE_DOS_HEADER>(0)?;
24
25 if dos.e_magic != IMAGE_DOS_SIGNATURE as u16
26 || result.bytes.copy_as::<u32>(dos.e_lfanew as usize)? != IMAGE_NT_SIGNATURE as u32
27 {
28 return None;
29 }
30
31 let file_offset = dos.e_lfanew as usize + size_of::<u32>();
32 let file = result.bytes.view_as::<IMAGE_FILE_HEADER>(file_offset)?;
33
34 let optional_offset = file_offset + size_of::<IMAGE_FILE_HEADER>();
35
36 let (com_virtual_address, sections) =
37 match result.bytes.copy_as::<u16>(optional_offset)? as i32 {
38 IMAGE_NT_OPTIONAL_HDR32_MAGIC => {
39 let optional = result
40 .bytes
41 .view_as::<IMAGE_OPTIONAL_HEADER32>(optional_offset)?;
42 (
43 optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize]
44 .VirtualAddress,
45 result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(
46 optional_offset + size_of::<IMAGE_OPTIONAL_HEADER32>(),
47 file.NumberOfSections as usize,
48 )?,
49 )
50 }
51 IMAGE_NT_OPTIONAL_HDR64_MAGIC => {
52 let optional = result
53 .bytes
54 .view_as::<IMAGE_OPTIONAL_HEADER64>(optional_offset)?;
55 (
56 optional.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR as usize]
57 .VirtualAddress,
58 result.bytes.view_as_slice_of::<IMAGE_SECTION_HEADER>(
59 optional_offset + size_of::<IMAGE_OPTIONAL_HEADER64>(),
60 file.NumberOfSections as usize,
61 )?,
62 )
63 }
64 _ => return None,
65 };
66
67 let clr = result.bytes.view_as::<IMAGE_COR20_HEADER>(offset_from_rva(
68 section_from_rva(sections, com_virtual_address)?,
69 com_virtual_address,
70 ))?;
71
72 if clr.cb != size_of::<IMAGE_COR20_HEADER>() as u32 {
73 return None;
74 }
75
76 let metadata_offset = offset_from_rva(
77 section_from_rva(sections, clr.MetaData.VirtualAddress)?,
78 clr.MetaData.VirtualAddress,
79 );
80 let metadata = result.bytes.view_as::<METADATA_HEADER>(metadata_offset)?;
81
82 if metadata.signature != METADATA_SIGNATURE {
83 return None;
84 }
85
86 let mut view = metadata_offset + metadata.length as usize + 20;
89 let mut tables_data: (usize, usize) = (0, 0);
90
91 for _ in 0..result
92 .bytes
93 .copy_as::<u16>(metadata_offset + metadata.length as usize + 18)?
94 {
95 let stream_offset = result.bytes.copy_as::<u32>(view)? as usize;
96 let stream_len = result.bytes.copy_as::<u32>(view + 4)? as usize;
97 let stream_name = result.bytes.view_as_str(view + 8)?;
98 match stream_name {
99 b"#Strings" => result.strings = metadata_offset + stream_offset,
100 b"#Blob" => result.blobs = metadata_offset + stream_offset,
101 b"#~" => tables_data = (metadata_offset + stream_offset, stream_len),
102 b"#GUID" | b"#US" => {}
103 rest => panic!("{rest:?}"),
104 }
105 let mut padding = 4 - stream_name.len() % 4;
106 if padding == 0 {
107 padding = 4;
108 }
109 view += 8 + stream_name.len() + padding;
110 }
111
112 let heap_sizes = result.bytes.copy_as::<u8>(tables_data.0 + 6)?;
113 let string_index_size = if (heap_sizes & 1) == 1 { 4 } else { 2 };
114 let guid_index_size = if ((heap_sizes >> 1) & 1) == 1 { 4 } else { 2 };
115 let blob_index_size = if ((heap_sizes >> 2) & 1) == 1 { 4 } else { 2 };
116 let valid_bits = result.bytes.copy_as::<u64>(tables_data.0 + 8)?;
117 view = tables_data.0 + 24;
118
119 let unused_empty = Table::default();
121 let mut unused_assembly_os = Table::default();
122 let mut unused_assembly_processor = Table::default();
123 let mut unused_assembly_ref_os = Table::default();
124 let mut unused_assembly_ref = Table::default();
125 let mut unused_assembly_ref_processor = Table::default();
126 let mut unused_decl_security = Table::default();
127 let mut unused_event = Table::default();
128 let mut unused_event_map = Table::default();
129 let mut unused_exported_type = Table::default();
130 let mut unused_field_layout = Table::default();
131 let mut unused_field_marshal = Table::default();
132 let mut unused_field_rva = Table::default();
133 let mut unused_file = Table::default();
134 let mut unused_generic_param_constraint = Table::default();
135 let mut unused_manifest_resource = Table::default();
136 let mut unused_method_impl = Table::default();
137 let mut unused_method_semantics = Table::default();
138 let mut unused_method_spec = Table::default();
139 let mut unused_property = Table::default();
140 let mut unused_property_map = Table::default();
141 let mut unused_standalone_sig = Table::default();
142 let mut unused_module = Table::default();
143
144 for i in 0..64 {
145 if ((valid_bits >> i) & 1) == 0 {
146 continue;
147 }
148
149 let len = result.bytes.copy_as::<u32>(view)? as usize;
150 view += 4;
151
152 match i {
153 0x00 => unused_module.len = len,
154 0x01 => result.tables[TypeRef::TABLE].len = len,
155 0x02 => result.tables[TypeDef::TABLE].len = len,
156 0x04 => result.tables[Field::TABLE].len = len,
157 0x06 => result.tables[MethodDef::TABLE].len = len,
158 0x08 => result.tables[MethodParam::TABLE].len = len,
159 0x09 => result.tables[InterfaceImpl::TABLE].len = len,
160 0x0a => result.tables[MemberRef::TABLE].len = len,
161 0x0b => result.tables[Constant::TABLE].len = len,
162 0x0c => result.tables[Attribute::TABLE].len = len,
163 0x0d => unused_field_marshal.len = len,
164 0x0e => unused_decl_security.len = len,
165 0x0f => result.tables[ClassLayout::TABLE].len = len,
166 0x10 => unused_field_layout.len = len,
167 0x11 => unused_standalone_sig.len = len,
168 0x12 => unused_event_map.len = len,
169 0x14 => unused_event.len = len,
170 0x15 => unused_property_map.len = len,
171 0x17 => unused_property.len = len,
172 0x18 => unused_method_semantics.len = len,
173 0x19 => unused_method_impl.len = len,
174 0x1a => result.tables[ModuleRef::TABLE].len = len,
175 0x1b => result.tables[TypeSpec::TABLE].len = len,
176 0x1c => result.tables[ImplMap::TABLE].len = len,
177 0x1d => unused_field_rva.len = len,
178 0x20 => result.tables[Assembly::TABLE].len = len,
179 0x21 => unused_assembly_processor.len = len,
180 0x22 => unused_assembly_os.len = len,
181 0x23 => unused_assembly_ref.len = len,
182 0x24 => unused_assembly_ref_processor.len = len,
183 0x25 => unused_assembly_ref_os.len = len,
184 0x26 => unused_file.len = len,
185 0x27 => unused_exported_type.len = len,
186 0x28 => unused_manifest_resource.len = len,
187 0x29 => result.tables[NestedClass::TABLE].len = len,
188 0x2a => result.tables[GenericParam::TABLE].len = len,
189 0x2b => unused_method_spec.len = len,
190 0x2c => unused_generic_param_constraint.len = len,
191 _ => unreachable!(),
192 };
193 }
194
195 let tables = &result.tables;
196 let type_def_or_ref = coded_index_size(&[
197 tables[TypeDef::TABLE].len,
198 tables[TypeRef::TABLE].len,
199 tables[TypeSpec::TABLE].len,
200 ]);
201 let has_constant = coded_index_size(&[
202 tables[Field::TABLE].len,
203 tables[MethodParam::TABLE].len,
204 unused_property.len,
205 ]);
206 let has_field_marshal =
207 coded_index_size(&[tables[Field::TABLE].len, tables[MethodParam::TABLE].len]);
208 let has_decl_security = coded_index_size(&[
209 tables[TypeDef::TABLE].len,
210 tables[MethodDef::TABLE].len,
211 tables[Assembly::TABLE].len,
212 ]);
213 let member_ref_parent = coded_index_size(&[
214 tables[TypeDef::TABLE].len,
215 tables[TypeRef::TABLE].len,
216 tables[ModuleRef::TABLE].len,
217 tables[MethodDef::TABLE].len,
218 tables[TypeSpec::TABLE].len,
219 ]);
220 let has_semantics = coded_index_size(&[unused_event.len, unused_property.len]);
221 let method_def_or_ref =
222 coded_index_size(&[tables[MethodDef::TABLE].len, tables[MemberRef::TABLE].len]);
223 let member_forwarded =
224 coded_index_size(&[tables[Field::TABLE].len, tables[MethodDef::TABLE].len]);
225 let implementation = coded_index_size(&[
226 unused_file.len,
227 unused_assembly_ref.len,
228 unused_exported_type.len,
229 ]);
230 let custom_attribute_type = coded_index_size(&[
231 tables[MethodDef::TABLE].len,
232 tables[MemberRef::TABLE].len,
233 unused_empty.len,
234 unused_empty.len,
235 unused_empty.len,
236 ]);
237 let resolution_scope = coded_index_size(&[
238 unused_module.len,
239 tables[ModuleRef::TABLE].len,
240 unused_assembly_ref.len,
241 tables[TypeRef::TABLE].len,
242 ]);
243 let type_or_method_def =
244 coded_index_size(&[tables[TypeDef::TABLE].len, tables[MethodDef::TABLE].len]);
245
246 let has_custom_attribute = coded_index_size(&[
247 tables[MethodDef::TABLE].len,
248 tables[Field::TABLE].len,
249 tables[TypeRef::TABLE].len,
250 tables[TypeDef::TABLE].len,
251 tables[MethodParam::TABLE].len,
252 tables[InterfaceImpl::TABLE].len,
253 tables[MemberRef::TABLE].len,
254 unused_module.len,
255 unused_property.len,
256 unused_event.len,
257 unused_standalone_sig.len,
258 tables[ModuleRef::TABLE].len,
259 tables[TypeSpec::TABLE].len,
260 tables[Assembly::TABLE].len,
261 unused_assembly_ref.len,
262 unused_file.len,
263 unused_exported_type.len,
264 unused_manifest_resource.len,
265 tables[GenericParam::TABLE].len,
266 unused_generic_param_constraint.len,
267 unused_method_spec.len,
268 ]);
269
270 result.tables[Assembly::TABLE].set_columns(
271 4,
272 8,
273 4,
274 blob_index_size,
275 string_index_size,
276 string_index_size,
277 );
278 unused_assembly_os.set_columns(4, 4, 4, 0, 0, 0);
279 unused_assembly_processor.set_columns(4, 0, 0, 0, 0, 0);
280 unused_assembly_ref.set_columns(
281 8,
282 4,
283 blob_index_size,
284 string_index_size,
285 string_index_size,
286 blob_index_size,
287 );
288 unused_assembly_ref_os.set_columns(4, 4, 4, unused_assembly_ref.index_width(), 0, 0);
289 unused_assembly_ref_processor.set_columns(4, unused_assembly_ref.index_width(), 0, 0, 0, 0);
290 result.tables[ClassLayout::TABLE].set_columns(
291 2,
292 4,
293 result.tables[TypeDef::TABLE].index_width(),
294 0,
295 0,
296 0,
297 );
298 result.tables[Constant::TABLE].set_columns(2, has_constant, blob_index_size, 0, 0, 0);
299 result.tables[Attribute::TABLE].set_columns(
300 has_custom_attribute,
301 custom_attribute_type,
302 blob_index_size,
303 0,
304 0,
305 0,
306 );
307 unused_decl_security.set_columns(2, has_decl_security, blob_index_size, 0, 0, 0);
308 unused_event_map.set_columns(
309 result.tables[TypeDef::TABLE].index_width(),
310 unused_event.index_width(),
311 0,
312 0,
313 0,
314 0,
315 );
316 unused_event.set_columns(2, string_index_size, type_def_or_ref, 0, 0, 0);
317 unused_exported_type.set_columns(
318 4,
319 4,
320 string_index_size,
321 string_index_size,
322 implementation,
323 0,
324 );
325 result.tables[Field::TABLE].set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
326 unused_field_layout.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0);
327 unused_field_marshal.set_columns(has_field_marshal, blob_index_size, 0, 0, 0, 0);
328 unused_field_rva.set_columns(4, result.tables[Field::TABLE].index_width(), 0, 0, 0, 0);
329 unused_file.set_columns(4, string_index_size, blob_index_size, 0, 0, 0);
330 result.tables[GenericParam::TABLE].set_columns(
331 2,
332 2,
333 type_or_method_def,
334 string_index_size,
335 0,
336 0,
337 );
338 unused_generic_param_constraint.set_columns(
339 result.tables[GenericParam::TABLE].index_width(),
340 type_def_or_ref,
341 0,
342 0,
343 0,
344 0,
345 );
346 result.tables[ImplMap::TABLE].set_columns(
347 2,
348 member_forwarded,
349 string_index_size,
350 result.tables[ModuleRef::TABLE].index_width(),
351 0,
352 0,
353 );
354 result.tables[InterfaceImpl::TABLE].set_columns(
355 result.tables[TypeDef::TABLE].index_width(),
356 type_def_or_ref,
357 0,
358 0,
359 0,
360 0,
361 );
362 unused_manifest_resource.set_columns(4, 4, string_index_size, implementation, 0, 0);
363 result.tables[MemberRef::TABLE].set_columns(
364 member_ref_parent,
365 string_index_size,
366 blob_index_size,
367 0,
368 0,
369 0,
370 );
371 result.tables[MethodDef::TABLE].set_columns(
372 4,
373 2,
374 2,
375 string_index_size,
376 blob_index_size,
377 result.tables[MethodParam::TABLE].index_width(),
378 );
379 unused_method_impl.set_columns(
380 result.tables[TypeDef::TABLE].index_width(),
381 method_def_or_ref,
382 method_def_or_ref,
383 0,
384 0,
385 0,
386 );
387 unused_method_semantics.set_columns(
388 2,
389 result.tables[MethodDef::TABLE].index_width(),
390 has_semantics,
391 0,
392 0,
393 0,
394 );
395 unused_method_spec.set_columns(method_def_or_ref, blob_index_size, 0, 0, 0, 0);
396 unused_module.set_columns(
397 2,
398 string_index_size,
399 guid_index_size,
400 guid_index_size,
401 guid_index_size,
402 0,
403 );
404 result.tables[ModuleRef::TABLE].set_columns(string_index_size, 0, 0, 0, 0, 0);
405 result.tables[NestedClass::TABLE].set_columns(
406 result.tables[TypeDef::TABLE].index_width(),
407 result.tables[TypeDef::TABLE].index_width(),
408 0,
409 0,
410 0,
411 0,
412 );
413 result.tables[MethodParam::TABLE].set_columns(2, 2, string_index_size, 0, 0, 0);
414 unused_property.set_columns(2, string_index_size, blob_index_size, 0, 0, 0);
415 unused_property_map.set_columns(
416 result.tables[TypeDef::TABLE].index_width(),
417 unused_property.index_width(),
418 0,
419 0,
420 0,
421 0,
422 );
423 unused_standalone_sig.set_columns(blob_index_size, 0, 0, 0, 0, 0);
424 result.tables[TypeDef::TABLE].set_columns(
425 4,
426 string_index_size,
427 string_index_size,
428 type_def_or_ref,
429 result.tables[Field::TABLE].index_width(),
430 result.tables[MethodDef::TABLE].index_width(),
431 );
432 result.tables[TypeRef::TABLE].set_columns(
433 resolution_scope,
434 string_index_size,
435 string_index_size,
436 0,
437 0,
438 0,
439 );
440 result.tables[TypeSpec::TABLE].set_columns(blob_index_size, 0, 0, 0, 0, 0);
441
442 unused_module.set_data(&mut view);
443 result.tables[TypeRef::TABLE].set_data(&mut view);
444 result.tables[TypeDef::TABLE].set_data(&mut view);
445 result.tables[Field::TABLE].set_data(&mut view);
446 result.tables[MethodDef::TABLE].set_data(&mut view);
447 result.tables[MethodParam::TABLE].set_data(&mut view);
448 result.tables[InterfaceImpl::TABLE].set_data(&mut view);
449 result.tables[MemberRef::TABLE].set_data(&mut view);
450 result.tables[Constant::TABLE].set_data(&mut view);
451 result.tables[Attribute::TABLE].set_data(&mut view);
452 unused_field_marshal.set_data(&mut view);
453 unused_decl_security.set_data(&mut view);
454 result.tables[ClassLayout::TABLE].set_data(&mut view);
455 unused_field_layout.set_data(&mut view);
456 unused_standalone_sig.set_data(&mut view);
457 unused_event_map.set_data(&mut view);
458 unused_event.set_data(&mut view);
459 unused_property_map.set_data(&mut view);
460 unused_property.set_data(&mut view);
461 unused_method_semantics.set_data(&mut view);
462 unused_method_impl.set_data(&mut view);
463 result.tables[ModuleRef::TABLE].set_data(&mut view);
464 result.tables[TypeSpec::TABLE].set_data(&mut view);
465 result.tables[ImplMap::TABLE].set_data(&mut view);
466 unused_field_rva.set_data(&mut view);
467 result.tables[Assembly::TABLE].set_data(&mut view);
468 unused_assembly_processor.set_data(&mut view);
469 unused_assembly_os.set_data(&mut view);
470 unused_assembly_ref.set_data(&mut view);
471 unused_assembly_ref_processor.set_data(&mut view);
472 unused_assembly_ref_os.set_data(&mut view);
473 unused_file.set_data(&mut view);
474 unused_exported_type.set_data(&mut view);
475 unused_manifest_resource.set_data(&mut view);
476 result.tables[NestedClass::TABLE].set_data(&mut view);
477 result.tables[GenericParam::TABLE].set_data(&mut view);
478
479 Some(result)
480 }
481
482 pub(crate) fn usize(&self, row: usize, table: usize, column: usize) -> usize {
483 let table = &self.tables[table];
484 let column = &table.columns[column];
485 let offset = table.offset + row * table.width + column.offset;
486 match column.width {
487 1 => self.bytes.copy_as::<u8>(offset).map_or(0, |v| v as usize),
488 2 => self.bytes.copy_as::<u16>(offset).map_or(0, |v| v as usize),
489 4 => self.bytes.copy_as::<u32>(offset).map_or(0, |v| v as usize),
490 _ => self.bytes.copy_as::<u64>(offset).map_or(0, |v| v as usize),
491 }
492 }
493
494 pub(crate) fn str(&self, row: usize, table: usize, column: usize) -> &str {
495 let offset = self.strings + self.usize(row, table, column);
496 let bytes = &self.bytes[offset..];
497 let nul_pos = bytes
498 .iter()
499 .position(|&c| c == 0)
500 .expect("expected null-terminated C-string");
501 std::str::from_utf8(&bytes[..nul_pos]).expect("expected valid utf-8 C-string")
502 }
503
504 pub(crate) fn blob(&self, row: usize, table: usize, column: usize) -> &[u8] {
505 let offset = self.blobs + self.usize(row, table, column);
506 let initial_byte = self.bytes[offset];
507
508 let (blob_size, blob_size_bytes) = match initial_byte >> 5 {
509 0..=3 => (initial_byte & 0x7f, 1),
510 4..=5 => (initial_byte & 0x3f, 2),
511 6 => (initial_byte & 0x1f, 4),
512 rest => panic!("{rest:?}"),
513 };
514
515 let mut blob_size = blob_size as usize;
516
517 for byte in &self.bytes[offset + 1..offset + blob_size_bytes] {
518 blob_size = blob_size.checked_shl(8).unwrap_or(0) + (*byte as usize);
519 }
520
521 let offset = offset + blob_size_bytes;
522 &self.bytes[offset..offset + blob_size]
523 }
524
525 pub(crate) fn list(
526 &self,
527 row: usize,
528 table: usize,
529 column: usize,
530 other_table: usize,
531 ) -> std::ops::Range<usize> {
532 let first = self.usize(row, table, column) - 1;
533 let next = row + 1;
534 let last = if next < self.tables[table].len {
535 self.usize(next, table, column) - 1
536 } else {
537 self.tables[other_table].len
538 };
539 first..last
540 }
541
542 pub(crate) fn equal_range(
543 &self,
544 table: usize,
545 column: usize,
546 value: usize,
547 ) -> std::ops::Range<usize> {
548 let mut first = 0;
549 let mut last = self.tables[table].len;
550 let mut count = last;
551
552 loop {
553 if count == 0 {
554 last = first;
555 break;
556 }
557
558 let count2 = count / 2;
559 let middle = first + count2;
560 let middle_value = self.usize(middle, table, column);
561
562 match middle_value.cmp(&value) {
563 Ordering::Less => {
564 first = middle + 1;
565 count -= count2 + 1;
566 }
567 Ordering::Greater => count = count2,
568 Ordering::Equal => {
569 let first2 = self.lower_bound(table, first, middle, column, value);
570 first += count;
571 last = self.upper_bound(table, middle + 1, first, column, value);
572 first = first2;
573 break;
574 }
575 }
576 }
577
578 first..last
579 }
580
581 pub(crate) fn parent(&self, row: usize, table: usize, column: usize) -> usize {
582 self.upper_bound(table, 0, self.tables[table].len, column, row + 1) - 1
583 }
584
585 fn lower_bound(
586 &self,
587 table: usize,
588 mut first: usize,
589 last: usize,
590 column: usize,
591 value: usize,
592 ) -> usize {
593 let mut count = last - first;
594 while count > 0 {
595 let count2 = count / 2;
596 let middle = first + count2;
597 if self.usize(middle, table, column) < value {
598 first = middle + 1;
599 count -= count2 + 1;
600 } else {
601 count = count2;
602 }
603 }
604 first
605 }
606
607 fn upper_bound(
608 &self,
609 table: usize,
610 mut first: usize,
611 last: usize,
612 column: usize,
613 value: usize,
614 ) -> usize {
615 let mut count = last - first;
616 while count > 0 {
617 let count2 = count / 2;
618 let middle = first + count2;
619 if value < self.usize(middle, table, column) {
620 count = count2;
621 } else {
622 first = middle + 1;
623 count -= count2 + 1;
624 }
625 }
626 first
627 }
628
629 pub fn assembly_name(&self) -> Option<&str> {
630 match self.tables[Assembly::TABLE].len {
631 0 => None,
632 1 => Some(self.str(0, Assembly::TABLE, 4)),
633 rest => panic!("{rest:?}"),
634 }
635 }
636
637 pub(crate) fn TypeDef(&self) -> std::ops::Range<usize> {
638 0..self.tables[TypeDef::TABLE].len
639 }
640
641 pub(crate) fn NestedClass(&self) -> std::ops::Range<usize> {
642 0..self.tables[NestedClass::TABLE].len
643 }
644}
645
646fn section_from_rva(sections: &[IMAGE_SECTION_HEADER], rva: u32) -> Option<&IMAGE_SECTION_HEADER> {
647 sections.iter().find(|&s| {
648 rva >= s.VirtualAddress && rva < s.VirtualAddress + unsafe { s.Misc.VirtualSize }
649 })
650}
651
652fn offset_from_rva(section: &IMAGE_SECTION_HEADER, rva: u32) -> usize {
653 (rva - section.VirtualAddress + section.PointerToRawData) as usize
654}
655
656trait View {
657 fn view_as<T>(&self, offset: usize) -> Option<&T>;
658 fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Option<&[T]>;
659 fn copy_as<T: Copy>(&self, offset: usize) -> Option<T>;
660 fn view_as_str(&self, offset: usize) -> Option<&[u8]>;
661 fn is_proper_length<T>(&self, offset: usize, count: usize) -> Option<()>;
662 fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Option<*const T>;
663}
664
665impl View for [u8] {
666 fn view_as<T>(&self, offset: usize) -> Option<&T> {
667 unsafe { Some(&*self.is_proper_length_and_alignment(offset, 1)?) }
668 }
669
670 fn view_as_slice_of<T>(&self, offset: usize, len: usize) -> Option<&[T]> {
671 unsafe {
672 Some(std::slice::from_raw_parts(
673 self.is_proper_length_and_alignment(offset, len)?,
674 len,
675 ))
676 }
677 }
678
679 fn copy_as<T>(&self, offset: usize) -> Option<T> {
680 self.is_proper_length::<T>(offset, 1)?;
681
682 Some(unsafe { (self[offset..].as_ptr() as *const T).read_unaligned() })
686 }
687
688 fn view_as_str(&self, offset: usize) -> Option<&[u8]> {
689 let buffer = &self[offset..];
690 let pos = buffer.iter().position(|c| *c == b'\0')?;
691 Some(&self[offset..offset + pos])
692 }
693
694 fn is_proper_length<T>(&self, offset: usize, count: usize) -> Option<()> {
695 if offset.checked_add(count.checked_mul(size_of::<T>())?)? <= self.len() {
696 Some(())
697 } else {
698 None
699 }
700 }
701
702 fn is_proper_length_and_alignment<T>(&self, offset: usize, count: usize) -> Option<*const T> {
703 self.is_proper_length::<T>(offset, count)?;
704 let ptr = &self[offset] as *const u8 as *const T;
705
706 if ptr.align_offset(align_of::<T>()) == 0 {
707 Some(ptr)
708 } else {
709 None
710 }
711 }
712}
713
714#[derive(Default)]
715struct Table {
716 offset: usize,
717 len: usize,
718 width: usize,
719 columns: [Column; 6],
720}
721
722impl Table {
723 fn index_width(&self) -> usize {
724 if self.len < (1 << 16) { 2 } else { 4 }
725 }
726
727 fn set_columns(&mut self, a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) {
728 self.width = a + b + c + d + e + f;
729 self.columns[0] = Column::new(0, a);
730 if b != 0 {
731 self.columns[1] = Column::new(a, b);
732 }
733 if c != 0 {
734 self.columns[2] = Column::new(a + b, c);
735 }
736 if d != 0 {
737 self.columns[3] = Column::new(a + b + c, d);
738 }
739 if e != 0 {
740 self.columns[4] = Column::new(a + b + c + d, e);
741 }
742 if f != 0 {
743 self.columns[5] = Column::new(a + b + c + d + e, f);
744 }
745 }
746
747 fn set_data(&mut self, offset: &mut usize) {
748 if self.len != 0 {
749 let next = *offset + self.len * self.width;
750 self.offset = *offset;
751 *offset = next;
752 }
753 }
754}
755
756#[derive(Default)]
757struct Column {
758 offset: usize,
759 width: usize,
760}
761
762impl Column {
763 fn new(offset: usize, width: usize) -> Self {
764 Self { offset, width }
765 }
766}
767
768#[repr(C)]
769#[derive(Default)]
770struct METADATA_HEADER {
771 signature: u32,
772 major_version: u16,
773 minor_version: u16,
774 reserved: u32,
775 length: u32,
776 version: [u8; 20],
777 flags: u16,
778 streams: u16,
779}
780
781const METADATA_SIGNATURE: u32 = 0x424A_5342;
782
783fn coded_index_size(tables: &[usize]) -> usize {
785 fn small(row_count: usize, bits: u8) -> bool {
786 (row_count as u64) < (1u64 << (16 - bits))
787 }
788
789 fn bits_needed(value: usize) -> u8 {
790 let mut value = value - 1;
791 let mut bits: u8 = 1;
792 while {
793 value >>= 1;
794 value != 0
795 } {
796 bits += 1;
797 }
798 bits
799 }
800
801 let bits_needed = bits_needed(tables.len());
802
803 if tables.iter().all(|table| small(*table, bits_needed)) {
804 2
805 } else {
806 4
807 }
808}