Coverage Report

Created: 2021-03-22 08:29

/rust/registry/src/github.com-1ecc6299db9ec823/wast-35.0.0/src/ast/module.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::ast::{self, annotation, kw};
2
use crate::parser::{Parse, Parser, Result};
3
4
pub use crate::resolve::Names;
5
6
/// A `*.wat` file parser, or a parser for one parenthesized module.
7
///
8
/// This is the top-level type which you'll frequently parse when working with
9
/// this crate. A `*.wat` file is either one `module` s-expression or a sequence
10
/// of s-expressions that are module fields.
11
pub struct Wat<'a> {
12
    #[allow(missing_docs)]
13
    pub module: Module<'a>,
14
}
15
16
impl<'a> Parse<'a> for Wat<'a> {
17
75.3k
    fn parse(parser: Parser<'a>) -> Result<Self> {
18
75.3k
        if !parser.has_meaningful_tokens() {
19
192
            return Err(parser.error("expected at least one module field"));
20
75.1k
        }
21
75.1k
        let _r = parser.register_annotation("custom");
22
75.1k
        let module = if !parser.peek2::<kw::module>() {
23
46.2k
            let fields = ModuleField::parse_remaining(parser)?;
24
31.3k
            Module {
25
31.3k
                span: ast::Span { offset: 0 },
26
31.3k
                id: None,
27
31.3k
                name: None,
28
31.3k
                kind: ModuleKind::Text(fields),
29
31.3k
            }
30
        } else {
31
28.9k
            parser.parens(|parser| parser.parse())?
32
        };
33
60.1k
        module.validate(parser)?;
34
60.1k
        Ok(Wat { module })
35
75.3k
    }
36
}
37
38
/// A parsed WebAssembly module.
39
pub struct Module<'a> {
40
    /// Where this `module` was defined
41
    pub span: ast::Span,
42
    /// An optional identifier this module is known by
43
    pub id: Option<ast::Id<'a>>,
44
    /// An optional `@name` annotation for this module
45
    pub name: Option<ast::NameAnnotation<'a>>,
46
    /// What kind of module this was parsed as.
47
    pub kind: ModuleKind<'a>,
48
}
49
50
/// The different kinds of ways to define a module.
51
pub enum ModuleKind<'a> {
52
    /// A module defined in the textual s-expression format.
53
    Text(Vec<ModuleField<'a>>),
54
    /// A module that had its raw binary bytes defined via the `binary`
55
    /// directive.
56
    Binary(Vec<&'a [u8]>),
57
}
58
59
impl<'a> Module<'a> {
60
    /// Performs a name resolution pass on this [`Module`], resolving all
61
    /// symbolic names to indices.
62
    ///
63
    /// The WAT format contains a number of shorthands to make it easier to
64
    /// write, such as inline exports, inline imports, inline type definitions,
65
    /// etc. Additionally it allows using symbolic names such as `$foo` instead
66
    /// of using indices. This module will postprocess an AST to remove all of
67
    /// this syntactic sugar, preparing the AST for binary emission.  This is
68
    /// where expansion and name resolution happens.
69
    ///
70
    /// This function will mutate the AST of this [`Module`] and replace all
71
    /// [`super::Index`] arguments with `Index::Num`. This will also expand inline
72
    /// exports/imports listed on fields and handle various other shorthands of
73
    /// the text format.
74
    ///
75
    /// If successful the AST was modified to be ready for binary encoding. A
76
    /// [`Names`] structure is also returned so if you'd like to do your own
77
    /// name lookups on the result you can do so as well.
78
    ///
79
    /// # Errors
80
    ///
81
    /// If an error happens during resolution, such a name resolution error or
82
    /// items are found in the wrong order, then an error is returned.
83
60.9k
    pub fn resolve(&mut self) -> std::result::Result<Names<'a>, crate::Error> {
84
60.9k
        crate::resolve::resolve(self)
85
60.9k
    }
86
87
    /// Encodes this [`Module`] to its binary form.
88
    ///
89
    /// This function will take the textual representation in [`Module`] and
90
    /// perform all steps necessary to convert it to a binary WebAssembly
91
    /// module, suitable for writing to a `*.wasm` file. This function may
92
    /// internally modify the [`Module`], for example:
93
    ///
94
    /// * Name resolution is performed to ensure that `Index::Id` isn't present
95
    ///   anywhere in the AST.
96
    ///
97
    /// * Inline shorthands such as imports/exports/types are all expanded to be
98
    ///   dedicated fields of the module.
99
    ///
100
    /// * Module fields may be shuffled around to preserve index ordering from
101
    ///   expansions.
102
    ///
103
    /// After all of this expansion has happened the module will be converted to
104
    /// its binary form and returned as a `Vec<u8>`. This is then suitable to
105
    /// hand off to other wasm runtimes and such.
106
    ///
107
    /// # Errors
108
    ///
109
    /// This function can return an error for name resolution errors and other
110
    /// expansion-related errors.
111
    pub fn encode(&mut self) -> std::result::Result<Vec<u8>, crate::Error> {
112
60.9k
        self.resolve()?;
113
59.3k
        Ok(crate::binary::encode(self))
114
60.9k
    }
115
116
60.1k
    fn validate(&self, parser: Parser<'_>) -> Result<()> {
117
60.1k
        let mut starts = 0;
118
60.1k
        if let ModuleKind::Text(fields) = &self.kind {
119
1.80M
            for item in fields.iter() {
120
1.80M
                if let ModuleField::Start(_) = item {
121
284
                    starts += 1;
122
1.80M
                }
123
            }
124
1
        }
125
60.1k
        if starts > 1 {
126
19
            return Err(parser.error("multiple start sections found"));
127
60.1k
        }
128
60.1k
        Ok(())
129
60.1k
    }
130
}
131
132
impl<'a> Parse<'a> for Module<'a> {
133
30.0k
    fn parse(parser: Parser<'a>) -> Result<Self> {
134
30.0k
        let _r = parser.register_annotation("custom");
135
30.0k
        let span = parser.parse::<kw::module>()?.0;
136
30.0k
        let id = parser.parse()?;
137
30.0k
        let name = parser.parse()?;
138
139
30.0k
        let kind = if parser.peek::<kw::binary>() {
140
547
            parser.parse::<kw::binary>()?;
141
547
            let mut data = Vec::new();
142
5.43k
            while !parser.is_empty() {
143
4.88k
                data.push(parser.parse()?);
144
            }
145
546
            ModuleKind::Binary(data)
146
        } else {
147
29.5k
            ModuleKind::Text(ModuleField::parse_remaining(parser)?)
148
        };
149
29.9k
        Ok(Module {
150
29.9k
            span,
151
29.9k
            id,
152
29.9k
            name,
153
29.9k
            kind,
154
29.9k
        })
155
30.0k
    }
156
}
157
158
/// A listing of all possible fields that can make up a WebAssembly module.
159
#[allow(missing_docs)]
160
#[derive(Debug)]
161
pub enum ModuleField<'a> {
162
    Type(ast::Type<'a>),
163
    Import(ast::Import<'a>),
164
    Func(ast::Func<'a>),
165
    Table(ast::Table<'a>),
166
    Memory(ast::Memory<'a>),
167
    Global(ast::Global<'a>),
168
    Export(ast::Export<'a>),
169
    Start(ast::ItemRef<'a, kw::func>),
170
    Elem(ast::Elem<'a>),
171
    Data(ast::Data<'a>),
172
    Event(ast::Event<'a>),
173
    Custom(ast::Custom<'a>),
174
    Instance(ast::Instance<'a>),
175
    NestedModule(ast::NestedModule<'a>),
176
    Alias(ast::Alias<'a>),
177
}
178
179
impl<'a> ModuleField<'a> {
180
75.7k
    fn parse_remaining(parser: Parser<'a>) -> Result<Vec<ModuleField>> {
181
75.7k
        let mut fields = Vec::new();
182
2.08M
        while !parser.is_empty() {
183
2.02M
            fields.push(parser.parens(ModuleField::parse)?);
184
        }
185
60.7k
        Ok(fields)
186
75.7k
    }
187
}
188
189
impl<'a> Parse<'a> for ModuleField<'a> {
190
2.29M
    fn parse(parser: Parser<'a>) -> Result<Self> {
191
2.29M
        if parser.peek::<kw::r#type>() {
192
206k
            return Ok(ModuleField::Type(parser.parse()?));
193
2.09M
        }
194
2.09M
        if parser.peek::<kw::import>() {
195
176
            return Ok(ModuleField::Import(parser.parse()?));
196
2.09M
        }
197
2.09M
        if parser.peek::<kw::func>() {
198
1.57M
            return Ok(ModuleField::Func(parser.parse()?));
199
513k
        }
200
513k
        if parser.peek::<kw::table>() {
201
4.31k
            return Ok(ModuleField::Table(parser.parse()?));
202
509k
        }
203
509k
        if parser.peek::<kw::memory>() {
204
4.07k
            return Ok(ModuleField::Memory(parser.parse()?));
205
505k
        }
206
505k
        if parser.peek::<kw::global>() {
207
16.7k
            return Ok(ModuleField::Global(parser.parse()?));
208
488k
        }
209
488k
        if parser.peek::<kw::export>() {
210
33.9k
            return Ok(ModuleField::Export(parser.parse()?));
211
454k
        }
212
454k
        if parser.peek::<kw::start>() {
213
757
            parser.parse::<kw::start>()?;
214
757
            return Ok(ModuleField::Start(parser.parse::<ast::IndexOrRef<_>>()?.0));
215
453k
        }
216
453k
        if parser.peek::<kw::elem>() {
217
309k
            return Ok(ModuleField::Elem(parser.parse()?));
218
143k
        }
219
143k
        if parser.peek::<kw::data>() {
220
39.2k
            return Ok(ModuleField::Data(parser.parse()?));
221
104k
        }
222
104k
        if parser.peek::<kw::event>() {
223
25.6k
            return Ok(ModuleField::Event(parser.parse()?));
224
78.7k
        }
225
78.7k
        if parser.peek::<annotation::custom>() {
226
0
            return Ok(ModuleField::Custom(parser.parse()?));
227
78.7k
        }
228
78.7k
        if parser.peek::<kw::instance>() {
229
30
            return Ok(ModuleField::Instance(parser.parse()?));
230
78.6k
        }
231
78.6k
        if parser.peek::<kw::module>() {
232
77.8k
            return Ok(ModuleField::NestedModule(parser.parse()?));
233
886
        }
234
886
        if parser.peek::<kw::alias>() {
235
38
            return Ok(ModuleField::Alias(parser.parse()?));
236
848
        }
237
848
        Err(parser.error("expected valid module field"))
238
2.29M
    }
239
}