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::{BinaryReader, FromReader, OperatorsReader, Result, SectionLimited, ValType};
17use core::ops::Range;
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(reader: BinaryReader<'a>) -> Self {
31        Self { reader }
32    }
33
34    /// Gets a binary reader for this function body.
35    pub fn get_binary_reader(&self) -> BinaryReader<'a> {
36        self.reader.clone()
37    }
38
39    fn skip_locals(reader: &mut BinaryReader) -> Result<()> {
40        let count = reader.read_var_u32()?;
41        for _ in 0..count {
42            reader.read_var_u32()?;
43            reader.read::<ValType>()?;
44        }
45        Ok(())
46    }
47
48    /// Gets the locals reader for this function body.
49    pub fn get_locals_reader(&self) -> Result<LocalsReader<'a>> {
50        let mut reader = self.reader.clone();
51        let declaration_count = reader.read_var_u32()?;
52        Ok(LocalsReader {
53            reader,
54            declaration_count,
55            total_count: 0,
56        })
57    }
58
59    /// Gets the operators reader for this function body, after skipping locals.
60    pub fn get_operators_reader(&self) -> Result<OperatorsReader<'a>> {
61        let mut reader = self.reader.clone();
62        Self::skip_locals(&mut reader)?;
63        Ok(OperatorsReader::new(reader))
64    }
65
66    /// Gets the range of the function body.
67    pub fn range(&self) -> Range<usize> {
68        self.reader.range()
69    }
70
71    /// Returns the body of this function as a list of bytes.
72    ///
73    /// Note that the returned bytes start with the function locals declaration.
74    pub fn as_bytes(&self) -> &'a [u8] {
75        self.reader.remaining_buffer()
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()?;
82        Ok(FunctionBody::new(reader))
83    }
84}
85
86/// A reader for a function body's locals.
87pub struct LocalsReader<'a> {
88    reader: BinaryReader<'a>,
89    declaration_count: u32,
90    total_count: u32,
91}
92
93impl<'a> LocalsReader<'a> {
94    /// Gets the count of locals declarations in the function body.
95    pub fn get_count(&self) -> u32 {
96        self.declaration_count
97    }
98
99    /// Gets the original position of the reader.
100    pub fn original_position(&self) -> usize {
101        self.reader.original_position()
102    }
103
104    /// Reads an item from the reader.
105    pub fn read(&mut self) -> Result<(u32, ValType)> {
106        let count = self.reader.read()?;
107        match self.total_count.checked_add(count) {
108            Some(total) => self.total_count = total,
109            None => bail!(self.reader.original_position(), "too many locals"),
110        }
111        let value_type = self.reader.read()?;
112        Ok((count, value_type))
113    }
114
115    /// Gets the binary reader from this LocalsReader
116    pub fn get_binary_reader(self) -> BinaryReader<'a> {
117        self.reader
118    }
119}
120
121impl<'a> IntoIterator for LocalsReader<'a> {
122    type Item = Result<(u32, ValType)>;
123    type IntoIter = LocalsIterator<'a>;
124    fn into_iter(self) -> Self::IntoIter {
125        let count = self.declaration_count;
126        LocalsIterator {
127            reader: self,
128            left: count,
129            err: false,
130        }
131    }
132}
133
134/// An iterator over locals in a function body.
135pub struct LocalsIterator<'a> {
136    reader: LocalsReader<'a>,
137    left: u32,
138    err: bool,
139}
140
141impl<'a> Iterator for LocalsIterator<'a> {
142    type Item = Result<(u32, ValType)>;
143    fn next(&mut self) -> Option<Self::Item> {
144        if self.err || self.left == 0 {
145            return None;
146        }
147        let result = self.reader.read();
148        self.err = result.is_err();
149        self.left -= 1;
150        Some(result)
151    }
152    fn size_hint(&self) -> (usize, Option<usize>) {
153        let count = self.reader.get_count() as usize;
154        (count, Some(count))
155    }
156}
157
158impl<'a> LocalsIterator<'a> {
159    /// After reading the locals, the BinaryReader is ready to read the operators.
160    pub fn into_operators_reader(self) -> OperatorsReader<'a> {
161        debug_assert!(self.err || self.left == 0);
162        OperatorsReader::new(self.reader.get_binary_reader())
163    }
164}