1use crate::core::*;
2use crate::util::*;
3use alloc::vec::Vec;
4use core::convert::TryInto;
5use webassembly::*;
6
7fn wasm_u32(input: &[u8]) -> Result<(&[u8], u32), &'static str> {
8 let (i, byte_count) = match input.try_extract_u32(0) {
9 Ok(r) => r,
10 Err(e) => return Err(e),
11 };
12 let (input, _) = take(byte_count as usize)(input)?;
13 Ok((input, i))
14}
15
16fn wasm_i32(input: &[u8]) -> Result<(&[u8], i32, &[u8]), &'static str> {
17 let original_input = input;
18 let (i, byte_count) = match input.try_extract_i32(0) {
19 Ok(r) => r,
20 Err(e) => return Err(e),
21 };
22 let (input, _) = take(byte_count as usize)(input)?;
23 Ok((input, i, &original_input[..byte_count]))
24}
25
26fn wasm_i64(input: &[u8]) -> Result<(&[u8], i64, &[u8]), &'static str> {
27 let original_input = input;
28 let (i, byte_count) = match input.try_extract_i64(0) {
29 Ok(r) => r,
30 Err(e) => return Err(e),
31 };
32 let (input, _) = take(byte_count as usize)(input)?;
33 Ok((input, i, &original_input[..byte_count]))
34}
35
36fn wasm_f32(input: &[u8]) -> Result<(&[u8], f32, &[u8]), &'static str> {
37 let original_input = input;
38 let (i, byte_count) = match input.try_extract_f32(0) {
39 Ok(r) => r,
40 Err(e) => return Err(e),
41 };
42 let (input, _) = take(byte_count as usize)(input)?;
43 Ok((input, i, &original_input[..byte_count]))
44}
45
46fn wasm_f64(input: &[u8]) -> Result<(&[u8], f64, &[u8]), &'static str> {
47 let original_input = input;
48 let (i, byte_count) = match input.try_extract_f64(0) {
49 Ok(r) => r,
50 Err(e) => return Err(e),
51 };
52 let (input, _) = take(byte_count as usize)(input)?;
53 Ok((input, i, &original_input[..byte_count]))
54}
55
56fn wasm_string(input: &[u8]) -> Result<(&[u8], &str), &'static str> {
57 let (input, num_chars) = wasm_u32(input)?;
58 let (input, chars) = take(num_chars as usize)(input)?;
59 let s = match alloc::str::from_utf8(chars) {
60 Ok(b) => b,
61 Err(_) => return Err("could not parse utf8 string"),
62 };
63 Ok((input, s))
64}
65
66fn wasm_global_type(input: &[u8]) -> Result<(&[u8], ValueType, bool), &'static str> {
67 let (input, global_value_type) = take(1)(input)?;
68 let (input, global_type) = take(1)(input)?;
69 Ok((
70 input,
71 global_value_type[0].try_into()?,
72 global_type[0] == MUTABLE,
73 ))
74}
75
76fn wasm_limit(input: &[u8]) -> Result<(&[u8], usize, Option<usize>), &'static str> {
77 let (input, mem_type) = take(1)(input)?;
78 match mem_type[0] {
79 LIMIT_MIN_MAX => {
80 let (input, min) = wasm_u32(input)?;
81 let (input, max) = wasm_u32(input)?;
82 Ok((input, min as usize, Some(max as usize)))
83 }
84 LIMIT_MIN => {
85 let (input, min) = wasm_u32(input)?;
86 Ok((input, min as usize, None))
87 }
88 _ => Err("unhandled memory type"),
89 }
90}
91
92fn wasm_instruction(op: u8, input: &[u8]) -> Result<(&[u8], Instruction), &'static str> {
93 let mut ip = input;
94 let instruction;
95
96 match op {
97 UNREACHABLE => instruction = Instruction::Unreachable,
98 NOP => instruction = Instruction::Nop,
99 RETURN => instruction = Instruction::Return,
100
101 BLOCK => {
102 let (input, block_type) = take(1)(input)?;
103 let (input, block_instructions) = wasm_expression(input)?;
104 instruction = Instruction::Block(block_type[0], block_instructions);
105 ip = input;
106 }
107
108 LOOP => {
109 let (input, block_type) = take(1)(input)?;
110 let (input, loop_instructions) = wasm_expression(input)?;
111 instruction = Instruction::Loop(block_type[0], loop_instructions);
112 ip = input;
113 }
114
115 IF => {
116 let (input, block_type) = take(1)(input)?;
117 let (input, if_instructions, else_instructions) = wasm_if_else(input)?;
118 instruction = Instruction::If(block_type[0], if_instructions, else_instructions);
119 ip = input;
120 }
121
122 BR => {
123 let (input, idx) = wasm_u32(input)?;
124 instruction = Instruction::Br(idx);
125 ip = input;
126 }
127
128 BR_IF => {
129 let (input, idx) = wasm_u32(input)?;
130 instruction = Instruction::BrIf(idx);
131 ip = input;
132 }
133
134 BR_TABLE => {
135 let (input, num_labels) = wasm_u32(input)?;
136 let parse_label = many_n(num_labels as usize, |input| wasm_u32(input));
137 let (input, labels) = parse_label(input)?;
138 let (input, idx) = wasm_u32(input)?;
139 instruction = Instruction::BrTable(labels, idx);
140 ip = input;
141 }
142
143 CALL => {
144 let (input, idx) = wasm_u32(input)?;
145 instruction = Instruction::Call(idx);
146 ip = input;
147 }
148
149 CALL_INDIRECT => {
150 let (input, idx) = wasm_u32(input)?;
151 let (input, _) = take(1)(input)?;
152 instruction = Instruction::CallIndirect(idx);
153 ip = input;
154 }
155
156 DROP => instruction = Instruction::Drop,
157 SELECT => instruction = Instruction::Select,
158 I32_CONST => {
159 let (input, c, _) = wasm_i32(input)?;
160 instruction = Instruction::I32Const(c);
161 ip = input;
162 }
163 I64_CONST => {
164 let (input, c, _) = wasm_i64(input)?;
165 instruction = Instruction::I64Const(c);
166 ip = input;
167 }
168
169 F32_CONST => {
170 let (input, c, _) = wasm_f32(input)?;
171 instruction = Instruction::F32Const(c);
172 ip = input;
173 }
174
175 F64_CONST => {
176 let (input, c, _) = wasm_f64(input)?;
177 instruction = Instruction::F64Const(c);
178 ip = input;
179 }
180 LOCAL_GET => {
181 let (input, idx) = wasm_u32(input)?;
182 instruction = Instruction::LocalGet(idx);
183 ip = input;
184 }
185 LOCAL_SET => {
186 let (input, idx) = wasm_u32(input)?;
187 instruction = Instruction::LocalSet(idx);
188 ip = input;
189 }
190 LOCAL_TEE => {
191 let (input, idx) = wasm_u32(input)?;
192 instruction = Instruction::LocalTee(idx);
193 ip = input;
194 }
195 GLOBAL_GET => {
196 let (input, idx) = wasm_u32(input)?;
197 instruction = Instruction::GlobalGet(idx);
198 ip = input;
199 }
200 GLOBAL_SET => {
201 let (input, idx) = wasm_u32(input)?;
202 instruction = Instruction::GlobalSet(idx);
203 ip = input;
204 }
205 I32_LOAD => {
206 let (input, align) = wasm_u32(input)?;
207 let (input, offset) = wasm_u32(input)?;
208 instruction = Instruction::I32Load(align, offset);
209 ip = input;
210 }
211
212 I64_LOAD => {
213 let (input, align) = wasm_u32(input)?;
214 let (input, offset) = wasm_u32(input)?;
215 instruction = Instruction::I64Load(align, offset);
216 ip = input;
217 }
218
219 F32_LOAD => {
220 let (input, align) = wasm_u32(input)?;
221 let (input, offset) = wasm_u32(input)?;
222 instruction = Instruction::F32Load(align, offset);
223 ip = input;
224 }
225
226 F64_LOAD => {
227 let (input, align) = wasm_u32(input)?;
228 let (input, offset) = wasm_u32(input)?;
229 instruction = Instruction::F64Load(align, offset);
230 ip = input;
231 }
232
233 I32_LOAD8_S => {
234 let (input, align) = wasm_u32(input)?;
235 let (input, offset) = wasm_u32(input)?;
236 instruction = Instruction::I32Load8S(align, offset);
237 ip = input;
238 }
239
240 I32_LOAD8_U => {
241 let (input, align) = wasm_u32(input)?;
242 let (input, offset) = wasm_u32(input)?;
243 instruction = Instruction::I32Load8U(align, offset);
244 ip = input;
245 }
246
247 I32_LOAD16_S => {
248 let (input, align) = wasm_u32(input)?;
249 let (input, offset) = wasm_u32(input)?;
250 instruction = Instruction::I32Load16S(align, offset);
251 ip = input;
252 }
253
254 I32_LOAD16_U => {
255 let (input, align) = wasm_u32(input)?;
256 let (input, offset) = wasm_u32(input)?;
257 instruction = Instruction::I32Load16U(align, offset);
258 ip = input;
259 }
260
261 I64_LOAD8_S => {
262 let (input, align) = wasm_u32(input)?;
263 let (input, offset) = wasm_u32(input)?;
264 instruction = Instruction::I64Load8S(align, offset);
265 ip = input;
266 }
267
268 I64_LOAD8_U => {
269 let (input, align) = wasm_u32(input)?;
270 let (input, offset) = wasm_u32(input)?;
271 instruction = Instruction::I64Load8U(align, offset);
272 ip = input;
273 }
274
275 I64_LOAD16_S => {
276 let (input, align) = wasm_u32(input)?;
277 let (input, offset) = wasm_u32(input)?;
278 instruction = Instruction::I64Load16S(align, offset);
279 ip = input;
280 }
281
282 I64_LOAD16_U => {
283 let (input, align) = wasm_u32(input)?;
284 let (input, offset) = wasm_u32(input)?;
285 instruction = Instruction::I64Load16U(align, offset);
286 ip = input;
287 }
288
289 I64_LOAD32_S => {
290 let (input, align) = wasm_u32(input)?;
291 let (input, offset) = wasm_u32(input)?;
292 instruction = Instruction::I64Load32S(align, offset);
293 ip = input;
294 }
295
296 I64_LOAD32_U => {
297 let (input, align) = wasm_u32(input)?;
298 let (input, offset) = wasm_u32(input)?;
299 instruction = Instruction::I64Load32U(align, offset);
300 ip = input;
301 }
302
303 I32_STORE => {
304 let (input, align) = wasm_u32(input)?;
305 let (input, offset) = wasm_u32(input)?;
306 instruction = Instruction::I32Store(align, offset);
307 ip = input;
308 }
309
310 I64_STORE => {
311 let (input, align) = wasm_u32(input)?;
312 let (input, offset) = wasm_u32(input)?;
313 instruction = Instruction::I64Store(align, offset);
314 ip = input;
315 }
316
317 F32_STORE => {
318 let (input, align) = wasm_u32(input)?;
319 let (input, offset) = wasm_u32(input)?;
320 instruction = Instruction::F32Store(align, offset);
321 ip = input;
322 }
323 F64_STORE => {
324 let (input, align) = wasm_u32(input)?;
325 let (input, offset) = wasm_u32(input)?;
326 instruction = Instruction::F64Store(align, offset);
327 ip = input;
328 }
329
330 I32_STORE8 => {
331 let (input, align) = wasm_u32(input)?;
332 let (input, offset) = wasm_u32(input)?;
333 instruction = Instruction::I32Store8(align, offset);
334 ip = input;
335 }
336
337 I32_STORE16 => {
338 let (input, align) = wasm_u32(input)?;
339 let (input, offset) = wasm_u32(input)?;
340 instruction = Instruction::I32Store16(align, offset);
341 ip = input;
342 }
343
344 I64_STORE8 => {
345 let (input, align) = wasm_u32(input)?;
346 let (input, offset) = wasm_u32(input)?;
347 instruction = Instruction::I64Store8(align, offset);
348 ip = input;
349 }
350
351 I64_STORE16 => {
352 let (input, align) = wasm_u32(input)?;
353 let (input, offset) = wasm_u32(input)?;
354 instruction = Instruction::I64Store16(align, offset);
355 ip = input;
356 }
357
358 I64_STORE32 => {
359 let (input, align) = wasm_u32(input)?;
360 let (input, offset) = wasm_u32(input)?;
361 instruction = Instruction::I64Store32(align, offset);
362 ip = input;
363 }
364
365 MEMORY_GROW => {
366 let (input, _) = wasm_u32(input)?;
367 instruction = Instruction::MemoryGrow;
368 ip = input;
369 }
370
371 MEMORY_SIZE => {
372 let (input, _) = wasm_u32(input)?;
373 instruction = Instruction::MemorySize;
374 ip = input;
375 }
376
377 I32_EQZ => instruction = Instruction::I32Eqz,
378 I32_EQ => instruction = Instruction::I32Eq,
379 I32_NE => instruction = Instruction::I32Ne,
380 I32_LT_S => instruction = Instruction::I32LtS,
381 I32_LT_U => instruction = Instruction::I32LtU,
382 I32_GT_S => instruction = Instruction::I32GtS,
383 I32_GT_U => instruction = Instruction::I32GtU,
384 I32_LE_S => instruction = Instruction::I32LeS,
385 I32_LE_U => instruction = Instruction::I32LeU,
386 I32_GE_S => instruction = Instruction::I32GeS,
387 I32_GE_U => instruction = Instruction::I32GeU,
388 I64_EQZ => instruction = Instruction::I64Eqz,
389 I64_EQ => instruction = Instruction::I64Eq,
390 I64_NE => instruction = Instruction::I64Ne,
391 I64_LT_S => instruction = Instruction::I64LtS,
392 I64_LT_U => instruction = Instruction::I64LtU,
393 I64_GT_S => instruction = Instruction::I64GtS,
394 I64_GT_U => instruction = Instruction::I64GtU,
395 I64_LE_S => instruction = Instruction::I64LeS,
396 I64_LE_U => instruction = Instruction::I64LeU,
397 I64_GE_S => instruction = Instruction::I64GeS,
398 I64_GE_U => instruction = Instruction::I64GeU,
399 F32_EQ => instruction = Instruction::F32Eq,
400 F32_NE => instruction = Instruction::F32Ne,
401 F32_LT => instruction = Instruction::F32Lt,
402 F32_GT => instruction = Instruction::F32Gt,
403 F32_LE => instruction = Instruction::F32Le,
404 F32_GE => instruction = Instruction::F32Ge,
405 F64_EQ => instruction = Instruction::F64Eq,
406 F64_NE => instruction = Instruction::F64Ne,
407 F64_LT => instruction = Instruction::F64Lt,
408 F64_GT => instruction = Instruction::F64Gt,
409 F64_LE => instruction = Instruction::F64Le,
410 F64_GE => instruction = Instruction::F64Ge,
411 I32_CLZ => instruction = Instruction::I32Clz,
412 I32_CTZ => instruction = Instruction::I32Ctz,
413 I32_POPCNT => instruction = Instruction::I32Popcnt,
414 I32_ADD => instruction = Instruction::I32Add,
415 I32_SUB => instruction = Instruction::I32Sub,
416 I32_MUL => instruction = Instruction::I32Mul,
417 I32_DIV_S => instruction = Instruction::I32DivS,
418 I32_DIV_U => instruction = Instruction::I32DivU,
419 I32_REM_S => instruction = Instruction::I32RemS,
420 I32_REM_U => instruction = Instruction::I32RemU,
421 I32_AND => instruction = Instruction::I32And,
422 I32_OR => instruction = Instruction::I32Or,
423 I32_XOR => instruction = Instruction::I32Xor,
424 I32_SHL => instruction = Instruction::I32Shl,
425 I32_SHR_S => instruction = Instruction::I32ShrS,
426 I32_SHR_U => instruction = Instruction::I32ShrU,
427 I32_ROTL => instruction = Instruction::I32Rotl,
428 I32_ROTR => instruction = Instruction::I32Rotr,
429 I64_CLZ => instruction = Instruction::I64Clz,
430 I64_CTZ => instruction = Instruction::I64Ctz,
431 I64_POPCNT => instruction = Instruction::I64Popcnt,
432 I64_ADD => instruction = Instruction::I64Add,
433 I64_SUB => instruction = Instruction::I64Sub,
434 I64_MUL => instruction = Instruction::I64Mul,
435 I64_DIV_S => instruction = Instruction::I64DivS,
436 I64_DIV_U => instruction = Instruction::I64DivU,
437 I64_REM_S => instruction = Instruction::I64RemS,
438 I64_REM_U => instruction = Instruction::I64RemU,
439 I64_AND => instruction = Instruction::I64And,
440 I64_OR => instruction = Instruction::I64Or,
441 I64_XOR => instruction = Instruction::I64Xor,
442 I64_SHL => instruction = Instruction::I64Shl,
443 I64_SHR_S => instruction = Instruction::I64ShrS,
444 I64_SHR_U => instruction = Instruction::I64ShrU,
445 I64_ROTL => instruction = Instruction::I64Rotl,
446 I64_ROTR => instruction = Instruction::I64Rotr,
447 F32_ABS => instruction = Instruction::F32Abs,
448 F32_NEG => instruction = Instruction::F32Neg,
449 F32_CEIL => instruction = Instruction::F32Ceil,
450 F32_FLOOR => instruction = Instruction::F32Floor,
451 F32_TRUNC => instruction = Instruction::F32Trunc,
452 F32_NEAREST => instruction = Instruction::F32Nearest,
453 F32_SQRT => instruction = Instruction::F32Sqrt,
454 F32_ADD => instruction = Instruction::F32Add,
455 F32_SUB => instruction = Instruction::F32Sub,
456 F32_MUL => instruction = Instruction::F32Mul,
457 F32_DIV => instruction = Instruction::F32Div,
458 F32_MIN => instruction = Instruction::F32Min,
459 F32_MAX => instruction = Instruction::F32Max,
460 F32_COPYSIGN => instruction = Instruction::F32Copysign,
461 F64_ABS => instruction = Instruction::F64Abs,
462 F64_NEG => instruction = Instruction::F64Neg,
463 F64_CEIL => instruction = Instruction::F64Ceil,
464 F64_FLOOR => instruction = Instruction::F64Floor,
465 F64_TRUNC => instruction = Instruction::F64Trunc,
466 F64_NEAREST => instruction = Instruction::F64Nearest,
467 F64_SQRT => instruction = Instruction::F64Sqrt,
468 F64_ADD => instruction = Instruction::F64Add,
469 F64_SUB => instruction = Instruction::F64Sub,
470 F64_MUL => instruction = Instruction::F64Mul,
471 F64_DIV => instruction = Instruction::F64Div,
472 F64_MIN => instruction = Instruction::F64Min,
473 F64_MAX => instruction = Instruction::F64Max,
474 F64_COPYSIGN => instruction = Instruction::F64Copysign,
475 I32_WRAP_F64 => instruction = Instruction::I32wrapF64,
476 I32_TRUNC_S_F32 => instruction = Instruction::I32TruncSF32,
477 I32_TRUNC_U_F32 => instruction = Instruction::I32TruncUF32,
478 I32_TRUNC_S_F64 => instruction = Instruction::I32TruncSF64,
479 I32_TRUNC_U_F64 => instruction = Instruction::I32TruncUF64,
480 I64_EXTEND_S_I32 => instruction = Instruction::I64ExtendSI32,
481 I64_EXTEND_U_I32 => instruction = Instruction::I64ExtendUI32,
482 I64_TRUNC_S_F32 => instruction = Instruction::I64TruncSF32,
483 I64_TRUNC_U_F32 => instruction = Instruction::I64TruncUF32,
484 I64_TRUNC_S_F64 => instruction = Instruction::I64TruncSF64,
485 I64_TRUNC_U_F64 => instruction = Instruction::I64TruncUF64,
486 F32_CONVERT_S_I32 => instruction = Instruction::F32ConvertSI32,
487 F32_CONVERT_U_I32 => instruction = Instruction::F32ConvertUI32,
488 F32_CONVERT_S_I64 => instruction = Instruction::F32ConvertSI64,
489 F32_CONVERT_U_I64 => instruction = Instruction::F32ConvertUI64,
490 F32_DEMOTE_F64 => instruction = Instruction::F32DemoteF64,
491 F64_CONVERT_S_I32 => instruction = Instruction::F64ConvertSI32,
492 F64_CONVERT_U_I32 => instruction = Instruction::F64ConvertUI32,
493 F64_CONVERT_S_I64 => instruction = Instruction::F64ConvertSI64,
494 F64_CONVERT_U_I64 => instruction = Instruction::F64ConvertUI64,
495 F64_PROMOTE_F32 => instruction = Instruction::F64PromoteF32,
496 I32_REINTERPRET_F32 => instruction = Instruction::I32ReinterpretF32,
497 I64_REINTERPRET_F64 => instruction = Instruction::I64ReinterpretF64,
498 F32_REINTERPRET_I32 => instruction = Instruction::F32ReinterpretI32,
499 F64_REINTERPRET_I64 => instruction = Instruction::F64ReinterpretI64,
500 _ => return Err("unknown expression"),
501 };
502 Ok((ip, instruction))
503}
504
505fn wasm_expression(input: &[u8]) -> Result<(&[u8], Vec<Instruction>), &'static str> {
506 let mut instructions = vec![];
507 let mut ip = input;
508 loop {
509 let (input, op) = take(1)(ip)?;
510 ip = input;
511 match op[0] {
512 END => {
513 ip = input;
514 break;
515 }
516
517 _ => {
518 let (input, instruction) = wasm_instruction(op[0], ip)?;
519 instructions.push(instruction);
520 ip = input;
521 }
522 }
523 }
524 Ok((ip, instructions))
525}
526
527type Instructions = Vec<Instruction>;
528
529fn wasm_if_else(input: &[u8]) -> Result<(&[u8], Instructions, Option<Instructions>), &'static str> {
530 let mut if_instructions = vec![];
531 let mut else_instructions = vec![];
532 let mut ip = input;
533 let mut more = false;
534 loop {
535 let (input, op) = take(1)(ip)?;
536 ip = input;
537 match op[0] {
538 END => {
539 break;
540 }
541 ELSE => {
542 more = true;
543 break;
544 }
545
546 _ => {
547 let (input, instruction) = wasm_instruction(op[0], ip)?;
548 if_instructions.push(instruction);
549 ip = input;
550 }
551 }
552 }
553 if more {
554 loop {
555 let (input, op) = take(1)(ip)?;
556 ip = input;
557 match op[0] {
558 END => {
559 break;
560 }
561
562 _ => {
563 let (input, instruction) = wasm_instruction(op[0], ip)?;
564 else_instructions.push(instruction);
565 ip = input;
566 }
567 }
568 }
569 Ok((ip, if_instructions, Some(else_instructions)))
570 } else {
571 Ok((ip, if_instructions, None))
572 }
573}
574
575fn section(input: &[u8]) -> Result<(&[u8], SectionView), &'static str> {
576 let (input, id) = take(1)(input)?;
577 let (input, section_length) = wasm_u32(input)?;
578 match id[0] {
579 SECTION_TYPE => {
580 let (input, num_items) = wasm_u32(input)?;
581 let parse_items = many_n(num_items as usize, |input| {
582 let (input, wasm_type) = take(1)(input)?;
583 match wasm_type[0] {
584 FUNC => {
585 let (input, num_inputs) = wasm_u32(input)?;
586 let (input, inputs) = take(num_inputs as usize)(input)?;
587 let (input, num_outputs) = wasm_u32(input)?;
588 let (input, outputs) = take(num_outputs as usize)(input)?;
589 Ok((
590 input,
591 FunctionType {
592 inputs: inputs.to_vec().try_to_value_types()?,
593 outputs: outputs.to_vec().try_to_value_types()?,
594 },
595 ))
596 }
597 _ => Err("unknown type"),
598 }
599 });
600 let (input, items) = parse_items(input)?;
601 Ok((input, SectionView::Type(TypeSection { types: items })))
602 }
603 SECTION_FUNCTION => {
604 let (input, num_items) = wasm_u32(input)?;
605 let parse_items = many_n(num_items as usize, |input| {
606 let r = wasm_u32(input);
607 match r {
608 Ok(n) => Ok((n.0, n.1 as usize)),
609 Err(e) => Err(e),
610 }
611 });
612 let (input, items) = parse_items(input)?;
613 Ok((
614 input,
615 SectionView::Function(FunctionSection {
616 function_types: items,
617 }),
618 ))
619 }
620 SECTION_START => {
621 let (input, start_function) = wasm_u32(input)?;
622 Ok((
623 input,
624 SectionView::Start(StartSection {
625 start_function: start_function as usize,
626 }),
627 ))
628 }
629 SECTION_EXPORT => {
630 let (input, num_items) = wasm_u32(input)?;
631 let parse_items = many_n(num_items as usize, |input| {
632 let (input, name) = wasm_string(input)?;
633 let (input, export_type) = take(1)(input)?;
634 let (input, export_index) = wasm_u32(input)?;
635 match export_type[0] {
636 DESC_FUNCTION => Ok((
637 input,
638 WasmExportView::Function(ExportView {
639 name,
640 index: export_index as usize,
641 }),
642 )),
643 DESC_MEMORY => Ok((
644 input,
645 WasmExportView::Memory(ExportView {
646 name,
647 index: export_index as usize,
648 }),
649 )),
650 DESC_GLOBAL => Ok((
651 input,
652 WasmExportView::Global(ExportView {
653 name,
654 index: export_index as usize,
655 }),
656 )),
657 DESC_TABLE => Ok((
658 input,
659 WasmExportView::Table(ExportView {
660 name,
661 index: export_index as usize,
662 }),
663 )),
664 _ => Err("unknown export"),
665 }
666 });
667 let (input, items) = parse_items(input)?;
668 Ok((
669 input,
670 SectionView::Export(ExportSectionView { exports: items }),
671 ))
672 }
673 SECTION_CODE => {
674 let (input, num_items) = wasm_u32(input)?;
675 let parse_items = many_n(num_items as usize, |input| {
676 let (input, _) = wasm_u32(input)?;
677 let (input, num_local_vecs) = wasm_u32(input)?;
678 let parse_local_vecs = many_n(num_local_vecs as usize, |input| {
679 let (input, num_locals) = wasm_u32(input)?;
680 let (input, local_type) = take(1 as usize)(input)?;
681 Ok((
682 input,
683 LocalCount {
684 count: num_locals,
685 value_type: local_type[0].try_into()?,
686 },
687 ))
688 });
689 let (input, local_vectors) = parse_local_vecs(input)?;
690
691 let (input, instructions) = wasm_expression(input)?;
692 Ok((
693 input,
694 CodeBlock {
695 locals: local_vectors,
696 instructions,
697 },
698 ))
699 });
700 let (input, items) = parse_items(input)?;
701 Ok((input, SectionView::Code(CodeSection { code_blocks: items })))
702 }
703 SECTION_IMPORT => {
704 let (input, num_items) = wasm_u32(input)?;
705 let parse_items = many_n(num_items as usize, |input| {
706 let (input, module_name) = wasm_string(input)?;
707 let (input, name) = wasm_string(input)?;
708 let (input, import_type) = take(1)(input)?;
709 match import_type[0] {
710 DESC_FUNCTION => {
711 let (input, type_index) = wasm_u32(input)?;
712 Ok((
713 input,
714 WasmImportView::Function(FunctionImportView {
715 module_name,
716 name,
717 type_index: type_index as usize,
718 }),
719 ))
720 }
721 DESC_MEMORY => {
722 let (input, min_pages, max_pages) = wasm_limit(input)?;
723 Ok((
724 input,
725 WasmImportView::Memory(MemoryImportView {
726 module_name,
727 name,
728 min_pages,
729 max_pages,
730 }),
731 ))
732 }
733 DESC_TABLE => {
734 let (input, element_type) = take(1)(input)?;
735 let (input, min, max) = wasm_limit(input)?;
736 Ok((
737 input,
738 WasmImportView::Table(TableImportView {
739 module_name,
740 name,
741 element_type: element_type[0],
742 min,
743 max,
744 }),
745 ))
746 }
747 DESC_GLOBAL => {
748 let (input, value_type, is_mutable) = wasm_global_type(input)?;
749 Ok((
750 input,
751 WasmImportView::Global(GlobalImportView {
752 module_name,
753 name,
754 value_type,
755 is_mutable,
756 }),
757 ))
758 }
759 _ => Err("unknown export"),
760 }
761 });
762 let (input, items) = parse_items(input)?;
763 Ok((
764 input,
765 SectionView::Import(ImportSectionView { imports: items }),
766 ))
767 }
768 SECTION_GLOBAL => {
769 let (input, num_items) = wasm_u32(input)?;
770 let parse_items = many_n(num_items as usize, |input| {
771 let (input, value_type, is_mutable) = wasm_global_type(input)?;
772 let (input, expression) = wasm_expression(input)?;
773 Ok((
774 input,
775 Global {
776 value_type,
777 is_mutable,
778 value_expression: expression,
779 },
780 ))
781 });
782 let (input, items) = parse_items(input)?;
783 Ok((input, SectionView::Global(GlobalSection { globals: items })))
784 }
785 SECTION_CUSTOM => {
786 let mut name_bytes_length = 0;
787 let (num_chars, byte_count) = match input.try_extract_u32(0) {
788 Ok(r) => r,
789 Err(e) => return Err(e),
790 };
791 let (input, _) = take(byte_count as usize)(input)?;
792 let (input, chars) = take(num_chars as usize)(input)?;
793 name_bytes_length += byte_count + num_chars as usize;
794 let name = match core::str::from_utf8(chars) {
795 Ok(b) => b,
796 Err(_) => return Err("could not parse utf8 string"),
797 };
798 let (input, bytes) =
799 take((section_length as usize - name_bytes_length) as usize)(input)?;
800 Ok((
801 input,
802 SectionView::Custom(CustomSectionView { name, data: bytes }),
803 ))
804 }
805 SECTION_TABLE => {
806 let (input, num_items) = wasm_u32(input)?;
807 let parse_items = many_n(num_items as usize, |input| {
808 let (input, element_type) = take(1)(input)?;
809 if element_type[0] == ANYFUNC {
810 let (input, min, max) = wasm_limit(input)?;
811 Ok((
812 input,
813 Table {
814 element_type: element_type[0],
815 min,
816 max,
817 },
818 ))
819 } else {
820 Err("unknown table type")
821 }
822 });
823 let (input, items) = parse_items(input)?;
824 Ok((input, SectionView::Table(TableSection { tables: items })))
825 }
826 SECTION_DATA => {
827 let (input, num_items) = wasm_u32(input)?;
828 let parse_items = many_n(num_items as usize, |input| {
829 let (input, mem_index) = wasm_u32(input)?;
830 let (input, offset_expression) = wasm_expression(input)?;
831 let (input, data_len) = wasm_u32(input)?;
832 let (input, data) = take(data_len as usize)(input)?;
833 Ok((
834 input,
835 DataBlockView {
836 memory: mem_index as usize,
837 offset_expression,
838 data,
839 },
840 ))
841 });
842 let (input, items) = parse_items(input)?;
843 Ok((
844 input,
845 SectionView::Data(DataSectionView { data_blocks: items }),
846 ))
847 }
848 SECTION_MEMORY => {
849 let (input, num_items) = wasm_u32(input)?;
850 let parse_items = many_n(num_items as usize, |input| {
851 let (input, min, max) = wasm_limit(input)?;
852 Ok((
853 input,
854 WasmMemory {
855 min_pages: min,
856 max_pages: max,
857 },
858 ))
859 });
860 let (input, items) = parse_items(input)?;
861 Ok((
862 input,
863 SectionView::Memory(MemorySection { memories: items }),
864 ))
865 }
866 SECTION_ELEMENT => {
867 let (input, num_items) = wasm_u32(input)?;
868 let parse_items = many_n(num_items as usize, |input| {
869 let (input, table) = wasm_u32(input)?;
870 let (input, expression) = wasm_expression(input)?;
871 let (input, num_functions) = wasm_u32(input)?;
872 let parse_functions = many_n(num_functions as usize, |input| {
873 let (input, i) = wasm_u32(input)?;
874 Ok((input, i as usize))
875 });
876 let (input, functions) = parse_functions(input)?;
877 Ok((
878 input,
879 WasmElement {
880 table: table as usize,
881 value_expression: expression,
882 functions,
883 },
884 ))
885 });
886 let (input, items) = parse_items(input)?;
887 Ok((
888 input,
889 SectionView::Element(ElementSection { elements: items }),
890 ))
891 }
892 _ => Err("unknow section"),
893 }
894}
895
896pub fn wasm_module(input: &[u8]) -> Result<ProgramView, &'static str> {
897 let (input, _) = tag(MAGIC_NUMBER)(input)?;
898 let (input, _) = tag(VERSION_1)(input)?;
899 let mut sections = vec![];
900 let mut ip = input;
901 let mut p = ProgramView { sections: vec![] };
902 loop {
903 match section(ip) {
904 Ok((input, item)) => {
905 sections.push(item);
906 ip = input;
907 }
908 Err(e) => {
909 if ip.is_empty() {
910 break;
911 } else {
912 return Err(e);
913 }
914 }
915 }
916 }
917 p.sections = sections;
918 Ok(p)
919}