| 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 | |