wasm/core/decoding/modules/
sections.rs1use crate::{
2 core::{
3 decoding::reader::{span::Span, WasmDecoder},
4 utils::ToUsizeExt,
5 },
6 DecodingError,
7};
8
9#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
10pub enum SectionTy {
11 Custom = 0,
12 Type = 1,
13 Import = 2,
14 Function = 3,
15 Table = 4,
16 Memory = 5,
17 Global = 6,
18 Export = 7,
19 Start = 8,
20 Element = 9,
21 Code = 10,
22 Data = 11,
23 DataCount = 12,
24}
25
26impl TryFrom<u8> for SectionTy {
27 type Error = DecodingError;
28
29 fn try_from(value: u8) -> Result<Self, Self::Error> {
30 use SectionTy::*;
31 let ty = match value {
32 0 => Custom,
33 1 => Type,
34 2 => Import,
35 3 => Function,
36 4 => Table,
37 5 => Memory,
38 6 => Global,
39 7 => Export,
40 8 => Start,
41 9 => Element,
42 10 => Code,
43 11 => Data,
44 12 => DataCount,
45 other => return Err(DecodingError::MalformedSectionTypeDiscriminator(other)),
46 };
47 Ok(ty)
48 }
49}
50
51impl SectionTy {
52 pub fn decode(wasm: &mut WasmDecoder) -> Result<Self, DecodingError> {
53 wasm.decode_u8().and_then(Self::try_from)
54 }
55
56 pub fn peek(wasm: &WasmDecoder) -> Result<Self, DecodingError> {
57 wasm.peek_u8().and_then(Self::try_from)
58 }
59}
60
61pub fn decode_section_if_ty_matches<'wasm, T, E>(
63 wasm: &mut WasmDecoder<'wasm>,
64 expected_ty: SectionTy,
65 section_consumer: impl FnOnce(&mut WasmDecoder<'wasm>, Span) -> Result<T, E>,
66) -> Result<Option<T>, E>
67where
68 E: From<DecodingError>,
69{
70 let section_ty = match SectionTy::peek(wasm) {
71 Ok(section_ty) => section_ty,
72 Err(DecodingError::Eof) => return Ok(None),
73 Err(other) => return Err(other.into()),
74 };
75
76 if section_ty != expected_ty {
77 return Ok(None);
78 }
79 let _ = SectionTy::decode(wasm).expect("this to be Ok because of the previous peek call");
80
81 let size: u32 = wasm.decode_var_u32()?;
82 let contents_span = wasm.make_span(size.into_usize())?;
83
84 trace!("Handling section {:?}", section_ty);
85 let t = section_consumer(wasm, contents_span)?;
86
87 if wasm.pc != contents_span.from() + contents_span.len() {
88 return Err(DecodingError::SectionSizeMismatch.into());
89 }
90
91 Ok(Some(t))
92}