1#![no_std]
2
3use core::mem;
4use plain;
5
6pub use self::big_endian::Be32;
7mod big_endian;
8
9pub use self::file::File;
10mod file;
11
12pub use self::fmap::Fmap;
13mod fmap;
14
15pub use self::header::Header;
16mod header;
17
18pub struct Rom<'a>(pub &'a [u8]);
19
20impl<'a> Rom<'a> {
21 pub fn new(data: &'a [u8]) -> Self {
22 Self(data)
23 }
24
25 pub fn fmap(&self) -> Option<&Fmap> {
26 let mut offset = 0;
27 while offset + mem::size_of::<Fmap>() < self.0.len() {
28 let fmap: &Fmap = plain::from_bytes(&self.0[offset..]).ok()?;
29
30 if &fmap.signature == b"__FMAP__" {
31 return Some(fmap);
32 }
33
34 offset += 8;
35 }
36 None
37 }
38
39 pub fn header_offset(&self) -> Option<usize> {
40 if self.0.len() < 4 {
41 return None;
42 }
43
44 let i = self.0.len() - 4;
46 let offset = i32::from_le_bytes([self.0[i], self.0[i + 1], self.0[i + 2], self.0[i + 3]]) as isize;
47 let header_pos = (self.0.len() as isize + offset) as usize;
48
49 Some(header_pos)
50 }
51
52 pub fn header(&self) -> Option<&Header> {
53 let offset = self.header_offset()?;
54
55 if offset >= self.0.len() {
56 return None;
57 }
58
59 let header: &Header = plain::from_bytes(&self.0[offset..]).ok()?;
60 if &header.magic == b"ORBC" {
61 Some(header)
62 } else {
63 None
64 }
65 }
66
67 pub fn file(&self, offset: usize) -> Option<&File> {
68 if offset >= self.0.len() {
69 return None;
70 }
71
72 let file: &File = plain::from_bytes(&self.0[offset..]).ok()?;
73 if &file.magic == b"LARCHIVE" {
74 Some(file)
75 } else {
76 None
77 }
78 }
79}