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