watson/parser/
wasm.rs

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}