wasmparser_nostd/readers/core/
names.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::{
17    BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections,
18};
19use ::core::ops::Range;
20
21/// Represents a name map from the names custom section.
22pub type NameMap<'a> = SectionLimited<'a, Naming<'a>>;
23
24/// Represents a name for an index from the names section.
25#[derive(Debug, Copy, Clone)]
26pub struct Naming<'a> {
27    /// The index being named.
28    pub index: u32,
29    /// The name for the index.
30    pub name: &'a str,
31}
32
33impl<'a> FromReader<'a> for Naming<'a> {
34    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
35        let index = reader.read_var_u32()?;
36        let name = reader.read_string()?;
37        Ok(Naming { index, name })
38    }
39}
40
41/// Represents a reader for indirect names from the names custom section.
42pub type IndirectNameMap<'a> = SectionLimited<'a, IndirectNaming<'a>>;
43
44/// Represents an indirect name in the names custom section.
45#[derive(Debug, Clone)]
46pub struct IndirectNaming<'a> {
47    /// The indirect index of the name.
48    pub index: u32,
49    /// The map of names within the `index` prior.
50    pub names: NameMap<'a>,
51}
52
53impl<'a> FromReader<'a> for IndirectNaming<'a> {
54    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
55        let index = reader.read_var_u32()?;
56
57        // Skip the `NameMap` manually here.
58        //
59        // FIXME(#188) shouldn't need to skip here
60        let names = reader.skip(|reader| {
61            let count = reader.read_var_u32()?;
62            for _ in 0..count {
63                reader.read_var_u32()?;
64                reader.skip_string()?;
65            }
66            Ok(())
67        })?;
68
69        Ok(IndirectNaming {
70            index,
71            names: NameMap::new(names.remaining_buffer(), names.original_position())?,
72        })
73    }
74}
75
76/// Represents a name read from the names custom section.
77#[derive(Clone)]
78pub enum Name<'a> {
79    /// The name is for the module.
80    Module {
81        /// The specified name.
82        name: &'a str,
83        /// The byte range that `name` occupies in the original binary.
84        name_range: Range<usize>,
85    },
86    /// The name is for the functions.
87    Function(NameMap<'a>),
88    /// The name is for the function locals.
89    Local(IndirectNameMap<'a>),
90    /// The name is for the function labels.
91    Label(IndirectNameMap<'a>),
92    /// The name is for the types.
93    Type(NameMap<'a>),
94    /// The name is for the tables.
95    Table(NameMap<'a>),
96    /// The name is for the memories.
97    Memory(NameMap<'a>),
98    /// The name is for the globals.
99    Global(NameMap<'a>),
100    /// The name is for the element segments.
101    Element(NameMap<'a>),
102    /// The name is for the data segments.
103    Data(NameMap<'a>),
104    /// An unknown [name subsection](https://webassembly.github.io/spec/core/appendix/custom.html#subsections).
105    Unknown {
106        /// The identifier for this subsection.
107        ty: u8,
108        /// The contents of this subsection.
109        data: &'a [u8],
110        /// The range of bytes, relative to the start of the original data
111        /// stream, that the contents of this subsection reside in.
112        range: Range<usize>,
113    },
114}
115
116/// A reader for the name custom section of a WebAssembly module.
117pub type NameSectionReader<'a> = Subsections<'a, Name<'a>>;
118
119impl<'a> Subsection<'a> for Name<'a> {
120    fn from_reader(id: u8, mut reader: BinaryReader<'a>) -> Result<Self> {
121        let data = reader.remaining_buffer();
122        let offset = reader.original_position();
123        Ok(match id {
124            0 => {
125                let name = reader.read_string()?;
126                if !reader.eof() {
127                    return Err(BinaryReaderError::new(
128                        "trailing data at the end of a name",
129                        reader.original_position(),
130                    ));
131                }
132                Name::Module {
133                    name,
134                    name_range: offset..offset + reader.position,
135                }
136            }
137            1 => Name::Function(NameMap::new(data, offset)?),
138            2 => Name::Local(IndirectNameMap::new(data, offset)?),
139            3 => Name::Label(IndirectNameMap::new(data, offset)?),
140            4 => Name::Type(NameMap::new(data, offset)?),
141            5 => Name::Table(NameMap::new(data, offset)?),
142            6 => Name::Memory(NameMap::new(data, offset)?),
143            7 => Name::Global(NameMap::new(data, offset)?),
144            8 => Name::Element(NameMap::new(data, offset)?),
145            9 => Name::Data(NameMap::new(data, offset)?),
146            ty => Name::Unknown {
147                ty,
148                data,
149                range: offset..offset + data.len(),
150            },
151        })
152    }
153}