wasmparser/readers/core/
tables.rs

1/* Copyright 2018 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16use crate::{BinaryReader, ConstExpr, FromReader, Result, SectionLimited, TableType};
17
18/// A reader for the table section of a WebAssembly module.
19pub type TableSectionReader<'a> = SectionLimited<'a, Table<'a>>;
20
21/// Type information about a table defined in the table section of a WebAssembly
22/// module.
23#[derive(Clone, Debug)]
24pub struct Table<'a> {
25    /// The type of this table, including its element type and its limits.
26    pub ty: TableType,
27    /// The initialization expression for the table.
28    pub init: TableInit<'a>,
29}
30
31/// Different modes of initializing a table.
32#[derive(Clone, Debug)]
33pub enum TableInit<'a> {
34    /// The table is initialized to all null elements.
35    RefNull,
36    /// Each element in the table is initialized with the specified constant
37    /// expression.
38    Expr(ConstExpr<'a>),
39}
40
41impl<'a> FromReader<'a> for Table<'a> {
42    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
43        let has_init_expr = if reader.peek()? == 0x40 {
44            reader.read_u8()?;
45            true
46        } else {
47            false
48        };
49
50        if has_init_expr {
51            if reader.read_u8()? != 0x00 {
52                bail!(reader.original_position() - 1, "invalid table encoding");
53            }
54        }
55
56        let ty = reader.read::<TableType>()?;
57        let init = if has_init_expr {
58            TableInit::Expr(reader.read()?)
59        } else {
60            TableInit::RefNull
61        };
62        Ok(Table { ty, init })
63    }
64}
65
66impl<'a> FromReader<'a> for TableType {
67    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
68        let element_type = reader.read()?;
69        let pos = reader.original_position();
70        let flags = reader.read_u8()?;
71        if (flags & !0b111) != 0 {
72            bail!(pos, "invalid table resizable limits flags");
73        }
74        let has_max = (flags & 0b001) != 0;
75        let shared = (flags & 0b010) != 0;
76        let table64 = (flags & 0b100) != 0;
77        Ok(TableType {
78            element_type,
79            table64,
80            initial: if table64 {
81                reader.read_var_u64()?
82            } else {
83                reader.read_var_u32()?.into()
84            },
85            maximum: if !has_max {
86                None
87            } else if table64 {
88                Some(reader.read_var_u64()?)
89            } else {
90                Some(reader.read_var_u32()?.into())
91            },
92            shared,
93        })
94    }
95}