tinywasm_wasmparser/readers/core/
code.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::std::ops::Range;
17use crate::{BinaryReader, FromReader, OperatorsReader, Result, SectionLimited, ValType};
18
19/// A reader for the code section of a WebAssembly module.
20pub type CodeSectionReader<'a> = SectionLimited<'a, FunctionBody<'a>>;
21
22/// Represents a WebAssembly function body.
23#[derive(Debug, Clone)]
24pub struct FunctionBody<'a> {
25    reader: BinaryReader<'a>,
26}
27
28impl<'a> FunctionBody<'a> {
29    /// Constructs a new `FunctionBody` for the given data and offset.
30    pub fn new(offset: usize, data: &'a [u8]) -> Self {
31        Self {
32            reader: BinaryReader::new_with_offset(data, offset),
33        }
34    }
35
36    /// Whether or not to allow 64-bit memory arguments in the
37    /// function body.
38    ///
39    /// This is intended to be `true` when support for the memory64
40    /// WebAssembly proposal is also enabled.
41    pub fn allow_memarg64(&mut self, allow: bool) {
42        self.reader.allow_memarg64(allow);
43    }
44
45    /// Gets a binary reader for this function body.
46    pub fn get_binary_reader(&self) -> BinaryReader<'a> {
47        self.reader.clone()
48    }
49
50    fn skip_locals(reader: &mut BinaryReader) -> Result<()> {
51        let count = reader.read_var_u32()?;
52        for _ in 0..count {
53            reader.read_var_u32()?;
54            reader.read::<ValType>()?;
55        }
56        Ok(())
57    }
58
59    /// Gets the locals reader for this function body.
60    pub fn get_locals_reader(&self) -> Result<LocalsReader<'a>> {
61        let mut reader = self.reader.clone();
62        let count = reader.read_var_u32()?;
63        Ok(LocalsReader { reader, count })
64    }
65
66    /// Gets the operators reader for this function body.
67    pub fn get_operators_reader(&self) -> Result<OperatorsReader<'a>> {
68        let mut reader = self.reader.clone();
69        Self::skip_locals(&mut reader)?;
70        Ok(OperatorsReader::new(reader))
71    }
72
73    /// Gets the range of the function body.
74    pub fn range(&self) -> Range<usize> {
75        self.reader.range()
76    }
77}
78
79impl<'a> FromReader<'a> for FunctionBody<'a> {
80    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
81        let reader = reader.read_reader("function body extends past end of the code section")?;
82        Ok(FunctionBody { reader })
83    }
84}
85
86/// A reader for a function body's locals.
87pub struct LocalsReader<'a> {
88    reader: BinaryReader<'a>,
89    count: u32,
90}
91
92impl<'a> LocalsReader<'a> {
93    /// Gets the count of locals in the function body.
94    pub fn get_count(&self) -> u32 {
95        self.count
96    }
97
98    /// Gets the original position of the reader.
99    pub fn original_position(&self) -> usize {
100        self.reader.original_position()
101    }
102
103    /// Reads an item from the reader.
104    pub fn read(&mut self) -> Result<(u32, ValType)> {
105        let count = self.reader.read()?;
106        let value_type = self.reader.read()?;
107        Ok((count, value_type))
108    }
109}
110
111impl<'a> IntoIterator for LocalsReader<'a> {
112    type Item = Result<(u32, ValType)>;
113    type IntoIter = LocalsIterator<'a>;
114    fn into_iter(self) -> Self::IntoIter {
115        let count = self.count;
116        LocalsIterator {
117            reader: self,
118            left: count,
119            err: false,
120        }
121    }
122}
123
124/// An iterator over locals in a function body.
125pub struct LocalsIterator<'a> {
126    reader: LocalsReader<'a>,
127    left: u32,
128    err: bool,
129}
130
131impl<'a> Iterator for LocalsIterator<'a> {
132    type Item = Result<(u32, ValType)>;
133    fn next(&mut self) -> Option<Self::Item> {
134        if self.err || self.left == 0 {
135            return None;
136        }
137        let result = self.reader.read();
138        self.err = result.is_err();
139        self.left -= 1;
140        Some(result)
141    }
142    fn size_hint(&self) -> (usize, Option<usize>) {
143        let count = self.reader.get_count() as usize;
144        (count, Some(count))
145    }
146}