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: bool = 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: TableType = reader.read::<TableType>()?;
57 let init: TableInit<'_> = 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}
96