1use std::collections::HashMap;
2
3use scroll::Pread;
4
5use crate::{method, region::Region, string::ABCString, uint32_t};
6
7#[allow(non_camel_case_types)]
9pub enum LiteralTag {
10 TAG_VALUE = 0x00,
11 BOOL = 0x01,
12 INTEGER = 0x02,
15 FLOAT = 0x03,
16 DOUBLE = 0x04,
17 STRING = 0x05,
18 METHOD = 0x06,
19 GENERATORMETHOD = 0x07,
20 ACCESSOR = 0x08,
21 METHODAFFILIATE = 0x09,
22 ARRAY_U1 = 0x0a,
23 ARRAY_U8 = 0x0b,
24 ARRAY_I8 = 0x0c,
25 ARRAY_U16 = 0x0d,
26 ARRAY_I16 = 0x0e,
27 ARRAY_U32 = 0x0f,
28 ARRAY_I32 = 0x10,
29 ARRAY_U64 = 0x11,
30 ARRAY_I64 = 0x12,
31 ARRAY_F32 = 0x13,
32 ARRAY_F64 = 0x14,
33 ARRAY_STRING = 0x15,
34 ASYNC_GENERATOR_METHOD = 0x16,
35 LITERAL_BUFFER_INDEX = 0x17,
36 LITERAL_ARRAY = 0x18,
37 BUILTIN_TYPE_INDEX = 0x19,
38 GETTER = 0x1a,
39 SETTER = 0x1b,
40 NULL_VALUE = 0xff,
41 UNKNOWN = 0xee,
42}
43
44impl LiteralTag {
45 pub fn from_u8(value: u8) -> Self {
46 match value {
47 0x00 => LiteralTag::TAG_VALUE,
48 0x01 => LiteralTag::BOOL,
49 0x02 => LiteralTag::INTEGER,
50 0x03 => LiteralTag::FLOAT,
51 0x04 => LiteralTag::DOUBLE,
52 0x05 => LiteralTag::STRING,
53 0x06 => LiteralTag::METHOD,
54 0x07 => LiteralTag::GENERATORMETHOD,
55 0x08 => LiteralTag::ACCESSOR,
56 0x09 => LiteralTag::METHODAFFILIATE,
57 0x0a => LiteralTag::ARRAY_U1,
58 0x0b => LiteralTag::ARRAY_U8,
59 0x0c => LiteralTag::ARRAY_I8,
60 0x0d => LiteralTag::ARRAY_U16,
61 0x0e => LiteralTag::ARRAY_I16,
62 0x0f => LiteralTag::ARRAY_U32,
63 0x10 => LiteralTag::ARRAY_I32,
64 0x11 => LiteralTag::ARRAY_U64,
65 0x12 => LiteralTag::ARRAY_I64,
66 0x13 => LiteralTag::ARRAY_F32,
67 0x14 => LiteralTag::ARRAY_F64,
68 0x15 => LiteralTag::ARRAY_STRING,
69 0x16 => LiteralTag::ASYNC_GENERATOR_METHOD,
70 0x17 => LiteralTag::LITERAL_BUFFER_INDEX,
71 0x18 => LiteralTag::LITERAL_ARRAY,
72 0x19 => LiteralTag::BUILTIN_TYPE_INDEX,
73 0x1a => LiteralTag::GETTER,
74 0x1b => LiteralTag::SETTER,
75 0xff => LiteralTag::NULL_VALUE,
76 _ => LiteralTag::UNKNOWN,
77 }
78 }
79}
80
81fn parse_literal_array(source: &[u8], offset: usize, region: &Region) -> String {
83 let num_literals = source.pread_with::<uint32_t>(offset, scroll::LE).unwrap();
84
85 let mut off = offset;
86 off += 4;
87
88 let mut result = String::new();
89 let mut counter = 0;
90 loop {
91 if counter >= num_literals {
92 break;
93 }
94
95 counter += 1;
96
97 let tag_value = source.pread::<u8>(off).unwrap();
98 off += 1;
99 match LiteralTag::from_u8(tag_value) {
100 LiteralTag::TAG_VALUE => {
101 tracing::debug!("TaggleValue: Match");
102 off += 1;
103 }
104 LiteralTag::BOOL => {
105 let data = source.pread::<u8>(off).unwrap();
106 off += 1;
107 let s = format!("bool: {}, ", data);
108 result += &s;
109 }
110 LiteralTag::INTEGER => {
111 let data = source.pread::<u32>(off).unwrap();
112 let s = format!("i32: 0x{:X}, ", data);
113 result += &s;
114 off += 4;
115 }
116 LiteralTag::FLOAT => {
117 let data = source.pread_with::<u32>(off, scroll::BE).unwrap();
118 let s = format!("f32: {}, ", f32::from_bits(data));
119 result += &s;
120 off += 4;
121 }
122 LiteralTag::DOUBLE => {
123 let data = source.pread_with::<u64>(off, scroll::BE).unwrap();
124 let s = format!("f64: {}, ", f64::from_bits(data));
125 result += &s;
126
127 off += 8;
128 }
129 LiteralTag::STRING => {
130 let string_off = source.pread::<u32>(off).unwrap();
131 let str = source.pread::<ABCString>(string_off as usize).unwrap();
132 let s = format!("str: \"{}\", ", str.str());
133 result += &s;
134
135 off += 4;
136 }
137 LiteralTag::METHOD => {
138 let method_off = source.pread::<uint32_t>(off).unwrap();
139 let method = method::get_method_sign(source, method_off as usize, region);
140 let s = format!("Method: {}, ", method);
141 result += &s;
142
143 off += 4;
144 }
145 LiteralTag::GENERATORMETHOD => {
146 let _off = source.pread::<uint32_t>(off).unwrap();
147 let s = format!("GeneratorMethod: {}, ", _off);
148 result += &s;
149 off += 4;
150 }
151 LiteralTag::ACCESSOR => {
152 let data = source.pread::<u8>(off).unwrap();
153 let s = format!("Accessor: {}, ", data);
154 result += &s;
155 off += 1;
156 }
157 LiteralTag::METHODAFFILIATE => {
158 let data = source.pread::<u16>(off).unwrap();
159 let s = format!("MethodAffiliate: {}, ", data);
160 result += &s;
161 off += 2;
162 }
163 LiteralTag::ARRAY_U1 => {
164 tracing::debug!("ArrayU1: Match");
165 off += 4;
166 }
167 LiteralTag::ARRAY_U8 => {
168 tracing::debug!("ArrayU8: Match");
169 off += 4;
170 }
171 LiteralTag::ARRAY_I8 => {
172 tracing::debug!("ArrayI8: Match");
173 off += 4;
174 }
175 LiteralTag::ARRAY_U16 => {
176 tracing::debug!("ArrayU16: Match");
177 off += 4;
178 }
179 LiteralTag::ARRAY_I16 => {
180 tracing::debug!("ArrayI16: Match");
181 off += 4;
182 }
183 LiteralTag::ARRAY_U32 => {
184 tracing::debug!("ArrayU32: Match");
185 off += 4;
186 }
187 LiteralTag::ARRAY_I32 => {
188 tracing::debug!("ArrayI32: Match");
189 off += 4;
190 }
191 LiteralTag::ARRAY_U64 => {
192 tracing::debug!("ArrayU64: Match");
193 off += 4;
194 }
195 LiteralTag::ARRAY_I64 => {
196 tracing::debug!("Match ArrayI64");
197 off += 4;
198 }
199 LiteralTag::ARRAY_F32 => {
200 tracing::debug!("Match ArrayF32");
201 off += 4;
202 }
203 LiteralTag::ARRAY_F64 => {
204 tracing::debug!("ArrayF64: {}", tag_value);
205 off += 8;
206 }
207 LiteralTag::ARRAY_STRING => {
208 tracing::debug!("ArrayString: {}", tag_value);
210 off += 4;
211 }
212 LiteralTag::ASYNC_GENERATOR_METHOD => {
213 tracing::debug!("ArrayGeneratorMethod: {}", tag_value);
214 off += 4;
215 }
216 LiteralTag::LITERAL_BUFFER_INDEX => {
217 tracing::debug!("LiteralBufferIndex: {}", tag_value);
218 off += 4;
219 }
220 LiteralTag::LITERAL_ARRAY => {
221 tracing::debug!("LiteralArr: {}", tag_value);
222 off += 4;
223 }
224 LiteralTag::BUILTIN_TYPE_INDEX => {
225 tracing::debug!("BuiltinTypeIndex: {}", tag_value);
226 off += 1;
227 }
228 LiteralTag::GETTER => {
229 let data = source.pread::<uint32_t>(off).unwrap();
230 let s = format!("Getter: 0x{:X}, ", data);
231 result += &s;
232 off += 4;
233 }
234 LiteralTag::SETTER => {
235 tracing::debug!("Setter: {}", tag_value);
236 off += 4;
237 }
238 LiteralTag::NULL_VALUE => {
239 tracing::debug!("NullValue: {}", tag_value);
240 off += 1;
241 }
242 LiteralTag::UNKNOWN => {
243 tracing::warn!("未知的Tag: 0x{:X}", tag_value);
244 break;
245 }
246 }
247 }
248
249 result
250}
251
252pub fn parse_literal_array_index(
253 source: &[u8],
254 offset: uint32_t,
255 num_literals: uint32_t,
256 regions: &[Region],
257) -> HashMap<usize, String> {
258 let mut off = offset as usize;
259 let mut literal_array_map: HashMap<usize, String> = HashMap::new();
260
261 for _ in 0..num_literals {
262 let array_off = source.pread::<uint32_t>(off).unwrap();
263 off += 4;
264
265 let mut region: Option<&Region> = None;
266 for item in regions.iter() {
267 if item.is_here(array_off as usize) {
268 region = Some(item);
269 break;
270 }
271 }
272
273 if region.is_none() {
274 tracing::warn!("region not found");
275 continue;
276 }
277
278 let region = region.unwrap();
279 let literal = parse_literal_array(source, array_off as usize, region);
280 literal_array_map.insert(array_off as usize, literal);
281 }
282
283 literal_array_map
284}