Coverage Report

Created: 2021-03-22 08:29

/rust/registry/src/github.com-1ecc6299db9ec823/wast-35.0.0/src/ast/token.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::ast::{annotation, kw};
2
use crate::lexer::FloatVal;
3
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
4
use std::fmt;
5
use std::hash::{Hash, Hasher};
6
use std::str;
7
8
/// A position in the original source stream, used to render errors.
9
0
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
10
pub struct Span {
11
    pub(crate) offset: usize,
12
}
13
14
impl Span {
15
    /// Construct a `Span` from a byte offset in the source file.
16
2.43M
    pub fn from_offset(offset: usize) -> Self {
17
2.43M
        Span { offset }
18
2.43M
    }
19
20
    /// Returns the line/column information of this span within `text`.
21
    /// Line and column numbers are 0-indexed. User presentation is typically
22
    /// 1-indexed, but 0-indexing is appropriate for internal use with
23
    /// iterators and slices.
24
19.5k
    pub fn linecol_in(&self, text: &str) -> (usize, usize) {
25
19.5k
        let mut cur = 0;
26
        // Use split_terminator instead of lines so that if there is a `\r`,
27
        // it is included in the offset calculation. The `+1` values below
28
        // account for the `\n`.
29
1.96M
        for (i, line) in text.split_terminator('\n').enumerate() {
30
1.96M
            if cur + line.len() + 1 > self.offset {
31
19.3k
                return (i, self.offset - cur);
32
1.94M
            }
33
1.94M
            cur += line.len() + 1;
34
        }
35
158
        (text.lines().count(), 0)
36
19.5k
    }
37
}
38
39
/// An identifier in a WebAssembly module, prefixed by `$` in the textual
40
/// format.
41
///
42
/// An identifier is used to symbolically refer to items in a a wasm module,
43
/// typically via the [`Index`] type.
44
1.48k
#[derive(Copy, Clone)]
45
pub struct Id<'a> {
46
    name: &'a str,
47
    gen: u32,
48
    span: Span,
49
}
50
51
impl<'a> Id<'a> {
52
616k
    fn new(name: &'a str, span: Span) -> Id<'a> {
53
616k
        Id { name, gen: 0, span }
54
616k
    }
55
56
331k
    pub(crate) fn gensym(span: Span, gen: u32) -> Id<'a> {
57
331k
        Id {
58
331k
            name: "gensym",
59
331k
            gen,
60
331k
            span,
61
331k
        }
62
331k
    }
63
64
    /// Returns the underlying name of this identifier.
65
    ///
66
    /// The name returned does not contain the leading `$`.
67
40.4k
    pub fn name(&self) -> &'a str {
68
40.4k
        self.name
69
40.4k
    }
70
71
    /// Returns span of this identifier in the original source
72
1.48M
    pub fn span(&self) -> Span {
73
1.48M
        self.span
74
1.48M
    }
75
76
86.2k
    pub(crate) fn is_gensym(&self) -> bool {
77
86.2k
        self.gen != 0
78
86.2k
    }
79
}
80
81
impl<'a> Hash for Id<'a> {
82
2.60M
    fn hash<H: Hasher>(&self, hasher: &mut H) {
83
2.60M
        self.name.hash(hasher);
84
2.60M
        self.gen.hash(hasher);
85
2.60M
    }
86
}
87
88
impl<'a> PartialEq for Id<'a> {
89
1.79M
    fn eq(&self, other: &Id<'a>) -> bool {
90
1.79M
        self.name == other.name && self.gen == other.gen
91
1.79M
    }
92
}
93
94
impl<'a> Eq for Id<'a> {}
95
96
impl<'a> Parse<'a> for Id<'a> {
97
616k
    fn parse(parser: Parser<'a>) -> Result<Self> {
98
616k
        parser.step(|c| {
99
616k
            if let Some((name, rest)) = c.id() {
100
616k
                return Ok((Id::new(name, c.cur_span()), rest));
101
0
            }
102
0
            Err(c.error("expected an identifier"))
103
616k
        })
104
616k
    }
105
}
106
107
impl fmt::Debug for Id<'_> {
108
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109
0
        if self.gen != 0 {
110
0
            f.debug_struct("Id").field("gen", &self.gen).finish()
111
        } else {
112
0
            self.name.fmt(f)
113
        }
114
0
    }
115
}
116
117
impl Peek for Id<'_> {
118
3.72M
    fn peek(cursor: Cursor<'_>) -> bool {
119
3.72M
        cursor.id().is_some()
120
3.72M
    }
121
122
483k
    fn display() -> &'static str {
123
483k
        "an identifier"
124
483k
    }
125
}
126
127
/// A reference to another item in a wasm module.
128
///
129
/// This type is used for items referring to other items (such as `call $foo`
130
/// referencing function `$foo`). References can be either an index (u32) or an
131
/// [`Id`] in the textual format.
132
///
133
/// The emission phase of a module will ensure that `Index::Id` is never used
134
/// and switch them all to `Index::Num`.
135
1.36M
#[derive(Copy, Clone, Debug)]
136
pub enum Index<'a> {
137
    /// A numerical index that this references. The index space this is
138
    /// referencing is implicit based on where this [`Index`] is stored.
139
    Num(u32, Span),
140
    /// A human-readable identifier this references. Like `Num`, the namespace
141
    /// this references is based on where this is stored.
142
    Id(Id<'a>),
143
}
144
145
impl Index<'_> {
146
    /// Returns the source location where this `Index` was defined.
147
17.7k
    pub fn span(&self) -> Span {
148
17.7k
        match self {
149
0
            Index::Num(_, span) => *span,
150
17.7k
            Index::Id(id) => id.span(),
151
        }
152
17.7k
    }
153
154
3.41k
    pub(crate) fn is_resolved(&self) -> bool {
155
3.41k
        match self {
156
3.41k
            Index::Num(..) => true,
157
0
            _ => false,
158
        }
159
3.41k
    }
160
}
161
162
impl<'a> Parse<'a> for Index<'a> {
163
551k
    fn parse(parser: Parser<'a>) -> Result<Self> {
164
551k
        let mut l = parser.lookahead1();
165
551k
        if l.peek::<Id>() {
166
68.2k
            Ok(Index::Id(parser.parse()?))
167
483k
        } else if l.peek::<u32>() {
168
483k
            let (val, span) = parser.parse()?;
169
482k
            Ok(Index::Num(val, span))
170
        } else {
171
211
            Err(l.error())
172
        }
173
551k
    }
174
}
175
176
impl Peek for Index<'_> {
177
849k
    fn peek(cursor: Cursor<'_>) -> bool {
178
849k
        u32::peek(cursor) || Id::peek(cursor)
179
849k
    }
180
181
30
    fn display() -> &'static str {
182
30
        "an index"
183
30
    }
184
}
185
186
impl<'a> From<Id<'a>> for Index<'a> {
187
100k
    fn from(id: Id<'a>) -> Index<'a> {
188
100k
        Index::Id(id)
189
100k
    }
190
}
191
192
impl PartialEq for Index<'_> {
193
1.61k
    fn eq(&self, other: &Index<'_>) -> bool {
194
1.61k
        match (self, other) {
195
0
            (Index::Num(a, _), Index::Num(b, _)) => a == b,
196
1.61k
            (Index::Id(a), Index::Id(b)) => a == b,
197
0
            _ => false,
198
        }
199
1.61k
    }
200
}
201
202
impl Eq for Index<'_> {}
203
204
impl Hash for Index<'_> {
205
41.4k
    fn hash<H: Hasher>(&self, hasher: &mut H) {
206
41.4k
        match self {
207
0
            Index::Num(a, _) => {
208
0
                0u8.hash(hasher);
209
0
                a.hash(hasher);
210
0
            }
211
41.4k
            Index::Id(a) => {
212
41.4k
                1u8.hash(hasher);
213
41.4k
                a.hash(hasher);
214
41.4k
            }
215
        }
216
41.4k
    }
217
}
218
219
/// Parses `(func $foo)`
220
///
221
/// Optionally includes export strings for module-linking sugar syntax for alias
222
/// injection.
223
15.2k
#[derive(Clone, Debug)]
224
#[allow(missing_docs)]
225
pub enum ItemRef<'a, K> {
226
    Outer {
227
        kind: K,
228
        module: Index<'a>,
229
        idx: Index<'a>,
230
    },
231
    Item {
232
        kind: K,
233
        idx: Index<'a>,
234
        exports: Vec<&'a str>,
235
    },
236
}
237
238
impl<'a, K> ItemRef<'a, K> {
239
    /// Unwraps the underlying `Index` for `ItemRef::Item`.
240
    ///
241
    /// Panics if this is `ItemRef::Outer` or if exports haven't been expanded
242
    /// yet.
243
0
    pub fn unwrap_index(&self) -> &Index<'a> {
244
0
        match self {
245
0
            ItemRef::Item { idx, exports, .. } => {
246
                debug_assert!(exports.len() == 0);
247
0
                idx
248
            }
249
0
            ItemRef::Outer { .. } => panic!("unwrap_index called on Parent"),
250
        }
251
0
    }
Unexecuted instantiation: <wast::ast::token::ItemRef<wast::ast::kw::type>>::unwrap_index
Unexecuted instantiation: <wast::ast::token::ItemRef<wast::ast::kw::instance>>::unwrap_index
252
}
253
254
impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> {
255
34.6k
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
34.5k
        parser.parens(|parser| {
257
34.5k
            let kind = parser.parse::<K>()?;
258
34.4k
            if parser.peek::<kw::outer>() {
259
2
                parser.parse::<kw::outer>()?;
260
2
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
34.4k
                let idx = parser.parse()?;
265
34.3k
                let mut exports = Vec::new();
266
52.2k
                while !parser.is_empty() {
267
17.9k
                    exports.push(parser.parse()?);
268
                }
269
34.3k
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
34.6k
        })
<wast::ast::token::ItemRef<wast::ast::kw::type> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
211
        parser.parens(|parser| {
257
211
            let kind = parser.parse::<K>()?;
258
211
            if parser.peek::<kw::outer>() {
259
1
                parser.parse::<kw::outer>()?;
260
1
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
210
                let idx = parser.parse()?;
265
198
                let mut exports = Vec::new();
266
239
                while !parser.is_empty() {
267
53
                    exports.push(parser.parse()?);
268
                }
269
186
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
211
        })
<wast::ast::token::ItemRef<wast::ast::kw::func> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
314
        parser.parens(|parser| {
257
314
            let kind = parser.parse::<K>()?;
258
272
            if parser.peek::<kw::outer>() {
259
0
                parser.parse::<kw::outer>()?;
260
0
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
272
                let idx = parser.parse()?;
265
261
                let mut exports = Vec::new();
266
18.0k
                while !parser.is_empty() {
267
17.8k
                    exports.push(parser.parse()?);
268
                }
269
247
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
314
        })
<wast::ast::token::ItemRef<wast::ast::kw::memory> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
72
        parser.parens(|parser| {
257
72
            let kind = parser.parse::<K>()?;
258
58
            if parser.peek::<kw::outer>() {
259
1
                parser.parse::<kw::outer>()?;
260
1
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
57
                let idx = parser.parse()?;
265
16
                let mut exports = Vec::new();
266
16
                while !parser.is_empty() {
267
10
                    exports.push(parser.parse()?);
268
                }
269
6
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
72
        })
<wast::ast::token::ItemRef<wast::ast::kw::global> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
17
        parser.parens(|parser| {
257
17
            let kind = parser.parse::<K>()?;
258
3
            if parser.peek::<kw::outer>() {
259
0
                parser.parse::<kw::outer>()?;
260
0
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
3
                let idx = parser.parse()?;
265
1
                let mut exports = Vec::new();
266
1
                while !parser.is_empty() {
267
1
                    exports.push(parser.parse()?);
268
                }
269
0
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
17
        })
<wast::ast::token::ItemRef<wast::ast::export::ExportKind> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
33.9k
        parser.parens(|parser| {
257
33.9k
            let kind = parser.parse::<K>()?;
258
33.8k
            if parser.peek::<kw::outer>() {
259
0
                parser.parse::<kw::outer>()?;
260
0
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
33.8k
                let idx = parser.parse()?;
265
33.8k
                let mut exports = Vec::new();
266
33.8k
                while !parser.is_empty() {
267
6
                    exports.push(parser.parse()?);
268
                }
269
33.8k
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
33.9k
        })
Unexecuted instantiation: <wast::ast::token::ItemRef<wast::ast::kw::module> as wast::parser::Parse>::parse::{closure#0}
<wast::ast::token::ItemRef<wast::ast::kw::table> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
19
        parser.parens(|parser| {
257
19
            let kind = parser.parse::<K>()?;
258
10
            if parser.peek::<kw::outer>() {
259
0
                parser.parse::<kw::outer>()?;
260
0
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
10
                let idx = parser.parse()?;
265
5
                let mut exports = Vec::new();
266
5
                while !parser.is_empty() {
267
3
                    exports.push(parser.parse()?);
268
                }
269
2
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
19
        })
<wast::ast::token::ItemRef<wast::ast::kw::instance> as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
256
14
        parser.parens(|parser| {
257
14
            let kind = parser.parse::<K>()?;
258
0
            if parser.peek::<kw::outer>() {
259
0
                parser.parse::<kw::outer>()?;
260
0
                let module = parser.parse()?;
261
0
                let idx = parser.parse()?;
262
0
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
0
                let idx = parser.parse()?;
265
0
                let mut exports = Vec::new();
266
0
                while !parser.is_empty() {
267
0
                    exports.push(parser.parse()?);
268
                }
269
0
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
14
        })
272
34.6k
    }
<wast::ast::token::ItemRef<wast::ast::kw::func> as wast::parser::Parse>::parse
Line
Count
Source
255
356
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
356
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
356
        })
272
356
    }
<wast::ast::token::ItemRef<wast::ast::kw::table> as wast::parser::Parse>::parse
Line
Count
Source
255
32
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
32
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
32
        })
272
32
    }
<wast::ast::token::ItemRef<wast::ast::export::ExportKind> as wast::parser::Parse>::parse
Line
Count
Source
255
33.9k
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
33.9k
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
33.9k
        })
272
33.9k
    }
Unexecuted instantiation: <wast::ast::token::ItemRef<wast::ast::kw::module> as wast::parser::Parse>::parse
<wast::ast::token::ItemRef<wast::ast::kw::instance> as wast::parser::Parse>::parse
Line
Count
Source
255
26
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
26
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
26
        })
272
26
    }
<wast::ast::token::ItemRef<wast::ast::kw::type> as wast::parser::Parse>::parse
Line
Count
Source
255
225
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
225
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
225
        })
272
225
    }
<wast::ast::token::ItemRef<wast::ast::kw::memory> as wast::parser::Parse>::parse
Line
Count
Source
255
81
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
81
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
81
        })
272
81
    }
<wast::ast::token::ItemRef<wast::ast::kw::global> as wast::parser::Parse>::parse
Line
Count
Source
255
43
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
43
        parser.parens(|parser| {
257
            let kind = parser.parse::<K>()?;
258
            if parser.peek::<kw::outer>() {
259
                parser.parse::<kw::outer>()?;
260
                let module = parser.parse()?;
261
                let idx = parser.parse()?;
262
                Ok(ItemRef::Outer { kind, module, idx })
263
            } else {
264
                let idx = parser.parse()?;
265
                let mut exports = Vec::new();
266
                while !parser.is_empty() {
267
                    exports.push(parser.parse()?);
268
                }
269
                Ok(ItemRef::Item { kind, idx, exports })
270
            }
271
43
        })
272
43
    }
273
}
274
275
impl<'a, K: Peek> Peek for ItemRef<'a, K> {
276
856k
    fn peek(cursor: Cursor<'_>) -> bool {
277
856k
        match cursor.lparen() {
278
10.9k
            Some(remaining) => K::peek(remaining),
279
845k
            None => false,
280
        }
281
856k
    }
<wast::ast::token::ItemRef<wast::ast::kw::func> as wast::parser::Peek>::peek
Line
Count
Source
276
291k
    fn peek(cursor: Cursor<'_>) -> bool {
277
291k
        match cursor.lparen() {
278
35
            Some(remaining) => K::peek(remaining),
279
291k
            None => false,
280
        }
281
291k
    }
<wast::ast::token::ItemRef<wast::ast::kw::table> as wast::parser::Peek>::peek
Line
Count
Source
276
29.7k
    fn peek(cursor: Cursor<'_>) -> bool {
277
29.7k
        match cursor.lparen() {
278
5.31k
            Some(remaining) => K::peek(remaining),
279
24.4k
            None => false,
280
        }
281
29.7k
    }
<wast::ast::token::ItemRef<wast::ast::kw::memory> as wast::parser::Peek>::peek
Line
Count
Source
276
535k
    fn peek(cursor: Cursor<'_>) -> bool {
277
535k
        match cursor.lparen() {
278
5.57k
            Some(remaining) => K::peek(remaining),
279
529k
            None => false,
280
        }
281
535k
    }
282
283
0
    fn display() -> &'static str {
284
0
        "an item reference"
285
0
    }
286
}
287
288
/// Convenience structure to parse `$f` or `(item $f)`.
289
0
#[derive(Clone, Debug)]
290
pub struct IndexOrRef<'a, K>(pub ItemRef<'a, K>);
291
292
impl<'a, K> Parse<'a> for IndexOrRef<'a, K>
293
where
294
    K: Parse<'a> + Default,
295
{
296
409k
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
409k
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
409k
                kind: K::default(),
300
409k
                idx: parser.parse()?,
301
408k
                exports: Vec::new(),
302
            }))
303
        } else {
304
492
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
409k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::instance> as wast::parser::Parse>::parse
Line
Count
Source
296
38
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
38
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
12
                kind: K::default(),
300
12
                idx: parser.parse()?,
301
11
                exports: Vec::new(),
302
            }))
303
        } else {
304
26
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
38
    }
Unexecuted instantiation: <wast::ast::token::IndexOrRef<wast::ast::kw::module> as wast::parser::Parse>::parse
<wast::ast::token::IndexOrRef<wast::ast::kw::table> as wast::parser::Parse>::parse
Line
Count
Source
296
13.7k
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
13.7k
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
13.6k
                kind: K::default(),
300
13.6k
                idx: parser.parse()?,
301
13.6k
                exports: Vec::new(),
302
            }))
303
        } else {
304
32
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
13.7k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::func> as wast::parser::Parse>::parse
Line
Count
Source
296
389k
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
389k
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
389k
                kind: K::default(),
300
389k
                idx: parser.parse()?,
301
389k
                exports: Vec::new(),
302
            }))
303
        } else {
304
356
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
389k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::global> as wast::parser::Parse>::parse
Line
Count
Source
296
4.96k
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
4.96k
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
4.92k
                kind: K::default(),
300
4.92k
                idx: parser.parse()?,
301
4.92k
                exports: Vec::new(),
302
            }))
303
        } else {
304
43
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
4.96k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::memory> as wast::parser::Parse>::parse
Line
Count
Source
296
1.17k
    fn parse(parser: Parser<'a>) -> Result<Self> {
297
1.17k
        if parser.peek::<Index<'_>>() {
298
            Ok(IndexOrRef(ItemRef::Item {
299
1.13k
                kind: K::default(),
300
1.13k
                idx: parser.parse()?,
301
1.12k
                exports: Vec::new(),
302
            }))
303
        } else {
304
35
            Ok(IndexOrRef(parser.parse()?))
305
        }
306
1.17k
    }
307
}
308
309
impl<'a, K: Peek> Peek for IndexOrRef<'a, K> {
310
393k
    fn peek(cursor: Cursor<'_>) -> bool {
311
393k
        Index::peek(cursor) || ItemRef::<K>::peek(cursor)
312
393k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::table> as wast::parser::Peek>::peek
Line
Count
Source
310
34.6k
    fn peek(cursor: Cursor<'_>) -> bool {
311
34.6k
        Index::peek(cursor) || ItemRef::<K>::peek(cursor)
312
34.6k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::func> as wast::parser::Peek>::peek
Line
Count
Source
310
309k
    fn peek(cursor: Cursor<'_>) -> bool {
311
309k
        Index::peek(cursor) || ItemRef::<K>::peek(cursor)
312
309k
    }
<wast::ast::token::IndexOrRef<wast::ast::kw::memory> as wast::parser::Peek>::peek
Line
Count
Source
310
50.1k
    fn peek(cursor: Cursor<'_>) -> bool {
311
50.1k
        Index::peek(cursor) || ItemRef::<K>::peek(cursor)
312
50.1k
    }
313
314
0
    fn display() -> &'static str {
315
0
        "an item reference"
316
0
    }
317
}
318
319
/// An `@name` annotation in source, currently of the form `@name "foo"`
320
0
#[derive(Copy, Clone, PartialEq, Debug)]
321
pub struct NameAnnotation<'a> {
322
    /// The name specified for the item
323
    pub name: &'a str,
324
}
325
326
impl<'a> Parse<'a> for NameAnnotation<'a> {
327
    fn parse(parser: Parser<'a>) -> Result<Self> {
328
3
        parser.parse::<annotation::name>()?;
329
3
        let name = parser.parse()?;
330
0
        Ok(NameAnnotation { name })
331
3
    }
332
}
333
334
impl<'a> Parse<'a> for Option<NameAnnotation<'a>> {
335
1.79M
    fn parse(parser: Parser<'a>) -> Result<Self> {
336
1.79M
        let _r = parser.register_annotation("name");
337
1.79M
        Ok(if parser.peek2::<annotation::name>() {
338
3
            Some(parser.parens(|p| p.parse())?)
339
        } else {
340
1.79M
            None
341
        })
342
1.79M
    }
343
}
344
345
macro_rules! integers {
346
    ($($i:ident($u:ident))*) => ($(
347
        impl<'a> Parse<'a> for $i {
348
1.39M
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
1.39M
                Ok(parser.parse::<($i, Span)>()?.0)
350
1.39M
            }
<i8 as wast::parser::Parse>::parse
Line
Count
Source
348
23
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
23
                Ok(parser.parse::<($i, Span)>()?.0)
350
23
            }
Unexecuted instantiation: <u16 as wast::parser::Parse>::parse
<u64 as wast::parser::Parse>::parse
Line
Count
Source
348
22
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
22
                Ok(parser.parse::<($i, Span)>()?.0)
350
22
            }
<i16 as wast::parser::Parse>::parse
Line
Count
Source
348
1.67k
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
1.67k
                Ok(parser.parse::<($i, Span)>()?.0)
350
1.67k
            }
<i64 as wast::parser::Parse>::parse
Line
Count
Source
348
824k
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
824k
                Ok(parser.parse::<($i, Span)>()?.0)
350
824k
            }
<u8 as wast::parser::Parse>::parse
Line
Count
Source
348
320
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
320
                Ok(parser.parse::<($i, Span)>()?.0)
350
320
            }
<u32 as wast::parser::Parse>::parse
Line
Count
Source
348
18.2k
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
18.2k
                Ok(parser.parse::<($i, Span)>()?.0)
350
18.2k
            }
<i32 as wast::parser::Parse>::parse
Line
Count
Source
348
553k
            fn parse(parser: Parser<'a>) -> Result<Self> {
349
553k
                Ok(parser.parse::<($i, Span)>()?.0)
350
553k
            }
351
        }
352
353
        impl<'a> Parse<'a> for ($i, Span) {
354
1.88M
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
1.88M
                parser.step(|c| {
356
1.88M
                    if let Some((i, rest)) = c.integer() {
357
1.88M
                        let (s, base) = i.val();
358
1.88M
                        let val = $i::from_str_radix(s, base)
359
38.9k
                            .or_else(|_| {
360
38.8k
                                $u::from_str_radix(s, base).map(|i| i as $i)
<(i64, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Line
Count
Source
360
7.74k
                                $u::from_str_radix(s, base).map(|i| i as $i)
<(i16, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Line
Count
Source
360
1
                                $u::from_str_radix(s, base).map(|i| i as $i)
<(i32, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Line
Count
Source
360
31.1k
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
1.88M
                            });
<(i64, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
7.74k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
7.74k
                            });
<(i8, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
2
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
2
                            });
<(i16, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
5
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
5
                            });
Unexecuted instantiation: <(u16, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
<(u32, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
58
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
58
                            });
<(u64, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
2
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
2
                            });
<(u8, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
2
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
2
                            });
<(i32, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Line
Count
Source
359
31.1k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
31.1k
                            });
362
1.88M
                        return match val {
363
1.88M
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
72
                            Err(_) => Err(c.error(concat!(
365
72
                                "invalid ",
366
72
                                stringify!($i),
367
72
                                " number: constant out of range",
368
72
                            ))),
369
                        };
370
193
                    }
371
193
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
1.88M
                })
Unexecuted instantiation: <(u16, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
<(i32, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
553k
                parser.step(|c| {
356
553k
                    if let Some((i, rest)) = c.integer() {
357
553k
                        let (s, base) = i.val();
358
553k
                        let val = $i::from_str_radix(s, base)
359
553k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
553k
                            });
362
553k
                        return match val {
363
553k
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
2
                            Err(_) => Err(c.error(concat!(
365
2
                                "invalid ",
366
2
                                stringify!($i),
367
2
                                " number: constant out of range",
368
2
                            ))),
369
                        };
370
43
                    }
371
43
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
553k
                })
<(i16, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
1.67k
                parser.step(|c| {
356
1.67k
                    if let Some((i, rest)) = c.integer() {
357
1.64k
                        let (s, base) = i.val();
358
1.64k
                        let val = $i::from_str_radix(s, base)
359
1.64k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
1.64k
                            });
362
1.64k
                        return match val {
363
1.64k
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
4
                            Err(_) => Err(c.error(concat!(
365
4
                                "invalid ",
366
4
                                stringify!($i),
367
4
                                " number: constant out of range",
368
4
                            ))),
369
                        };
370
27
                    }
371
27
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
1.67k
                })
<(u32, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
501k
                parser.step(|c| {
356
501k
                    if let Some((i, rest)) = c.integer() {
357
501k
                        let (s, base) = i.val();
358
501k
                        let val = $i::from_str_radix(s, base)
359
501k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
501k
                            });
362
501k
                        return match val {
363
501k
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
58
                            Err(_) => Err(c.error(concat!(
365
58
                                "invalid ",
366
58
                                stringify!($i),
367
58
                                " number: constant out of range",
368
58
                            ))),
369
                        };
370
19
                    }
371
19
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
501k
                })
<(i64, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
824k
                parser.step(|c| {
356
824k
                    if let Some((i, rest)) = c.integer() {
357
824k
                        let (s, base) = i.val();
358
824k
                        let val = $i::from_str_radix(s, base)
359
824k
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
824k
                            });
362
824k
                        return match val {
363
824k
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
2
                            Err(_) => Err(c.error(concat!(
365
2
                                "invalid ",
366
2
                                stringify!($i),
367
2
                                " number: constant out of range",
368
2
                            ))),
369
                        };
370
39
                    }
371
39
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
824k
                })
<(u8, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
320
                parser.step(|c| {
356
320
                    if let Some((i, rest)) = c.integer() {
357
280
                        let (s, base) = i.val();
358
280
                        let val = $i::from_str_radix(s, base)
359
280
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
280
                            });
362
280
                        return match val {
363
278
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
2
                            Err(_) => Err(c.error(concat!(
365
2
                                "invalid ",
366
2
                                stringify!($i),
367
2
                                " number: constant out of range",
368
2
                            ))),
369
                        };
370
40
                    }
371
40
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
320
                })
<(u64, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
22
                parser.step(|c| {
356
22
                    if let Some((i, rest)) = c.integer() {
357
13
                        let (s, base) = i.val();
358
13
                        let val = $i::from_str_radix(s, base)
359
13
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
13
                            });
362
13
                        return match val {
363
11
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
2
                            Err(_) => Err(c.error(concat!(
365
2
                                "invalid ",
366
2
                                stringify!($i),
367
2
                                " number: constant out of range",
368
2
                            ))),
369
                        };
370
9
                    }
371
9
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
22
                })
<(i8, wast::ast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
355
23
                parser.step(|c| {
356
23
                    if let Some((i, rest)) = c.integer() {
357
7
                        let (s, base) = i.val();
358
7
                        let val = $i::from_str_radix(s, base)
359
7
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
7
                            });
362
7
                        return match val {
363
5
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
2
                            Err(_) => Err(c.error(concat!(
365
2
                                "invalid ",
366
2
                                stringify!($i),
367
2
                                " number: constant out of range",
368
2
                            ))),
369
                        };
370
16
                    }
371
16
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
23
                })
373
1.88M
            }
<(u8, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
320
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
320
            }
<(u32, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
501k
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
501k
            }
<(i16, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
1.67k
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
1.67k
            }
<(i64, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
824k
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
824k
            }
<(i32, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
553k
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
553k
            }
Unexecuted instantiation: <(u16, wast::ast::token::Span) as wast::parser::Parse>::parse
<(u64, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
22
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
22
            }
<(i8, wast::ast::token::Span) as wast::parser::Parse>::parse
Line
Count
Source
354
23
            fn parse(parser: Parser<'a>) -> Result<Self> {
355
                parser.step(|c| {
356
                    if let Some((i, rest)) = c.integer() {
357
                        let (s, base) = i.val();
358
                        let val = $i::from_str_radix(s, base)
359
                            .or_else(|_| {
360
                                $u::from_str_radix(s, base).map(|i| i as $i)
361
                            });
362
                        return match val {
363
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
364
                            Err(_) => Err(c.error(concat!(
365
                                "invalid ",
366
                                stringify!($i),
367
                                " number: constant out of range",
368
                            ))),
369
                        };
370
                    }
371
                    Err(c.error(concat!("expected a ", stringify!($i))))
372
                })
373
23
            }
374
        }
375
376
        impl Peek for $i {
377
1.65M
            fn peek(cursor: Cursor<'_>) -> bool {
<u64 as wast::parser::Peek>::peek
Line
Count
Source
377
9
            fn peek(cursor: Cursor<'_>) -> bool {
<u32 as wast::parser::Peek>::peek
Line
Count
Source
377
1.65M
            fn peek(cursor: Cursor<'_>) -> bool {
378
                cursor.integer().is_some()
379
            }
380
381
274
            fn display() -> &'static str {
382
                stringify!($i)
383
            }
384
        }
385
    )*)
386
}
387
388
integers! {
389
    u8(u8) u16(u16) u32(u32) u64(u64)
390
    i8(u8) i16(u16) i32(u32) i64(u64)
391
}
392
393
impl<'a> Parse<'a> for &'a [u8] {
394
596k
    fn parse(parser: Parser<'a>) -> Result<Self> {
395
596k
        parser.step(|c| {
396
596k
            if let Some((i, rest)) = c.string() {
397
596k
                return Ok((i, rest));
398
150
            }
399
150
            Err(c.error("expected a string"))
400
596k
        })
401
596k
    }
402
}
403
404
impl Peek for &'_ [u8] {
405
49.6k
    fn peek(cursor: Cursor<'_>) -> bool {
406
49.6k
        cursor.string().is_some()
407
49.6k
    }
408
409
    fn display() -> &'static str {
410
        "string"
411
    }
412
}
413
414
impl<'a> Parse<'a> for &'a str {
415
190k
    fn parse(parser: Parser<'a>) -> Result<Self> {
416
190k
        str::from_utf8(parser.parse()?).map_err(|_| parser.error("malformed UTF-8 encoding"))
417
190k
    }
418
}
419
420
impl Parse<'_> for String {
421
0
    fn parse(parser: Parser<'_>) -> Result<Self> {
422
0
        Ok(<&str>::parse(parser)?.to_string())
423
0
    }
424
}
425
426
impl Peek for &'_ str {
427
10.3k
    fn peek(cursor: Cursor<'_>) -> bool {
428
10.3k
        <&[u8]>::peek(cursor)
429
10.3k
    }
430
431
    fn display() -> &'static str {
432
        <&[u8]>::display()
433
    }
434
}
435
436
macro_rules! float {
437
    ($($name:ident => {
438
        bits: $int:ident,
439
        float: $float:ident,
440
        exponent_bits: $exp_bits:tt,
441
        name: $parse:ident,
442
    })*) => ($(
443
        /// A parsed floating-point type
444
        #[derive(Debug)]
445
        pub struct $name {
446
            /// The raw bits that this floating point number represents.
447
            pub bits: $int,
448
        }
449
450
        impl<'a> Parse<'a> for $name {
451
2.24M
            fn parse(parser: Parser<'a>) -> Result<Self> {
452
2.24M
                parser.step(|c| {
453
2.24M
                    let (val, rest) = if let Some((f, rest)) = c.float() {
454
148k
                        ($parse(f.val()), rest)
455
2.09M
                    } else if let Some((i, rest)) = c.integer() {
456
2.09M
                        let (s, base) = i.val();
457
2.09M
                        (
458
2.09M
                            $parse(&FloatVal::Val {
459
2.09M
                                hex: base == 16,
460
2.09M
                                integral: s.into(),
461
2.09M
                                decimal: None,
462
2.09M
                                exponent: None,
463
2.09M
                            }),
464
2.09M
                            rest,
465
2.09M
                        )
466
                    } else {
467
295
                        return Err(c.error("expected a float"));
468
                    };
469
2.24M
                    match val {
470
2.24M
                        Some(bits) => Ok(($name { bits }, rest)),
471
83
                        None => Err(c.error("invalid float value: constant out of range")),
472
                    }
473
2.24M
                })
<wast::ast::token::Float64 as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
452
1.92M
                parser.step(|c| {
453
1.92M
                    let (val, rest) = if let Some((f, rest)) = c.float() {
454
68.6k
                        ($parse(f.val()), rest)
455
1.85M
                    } else if let Some((i, rest)) = c.integer() {
456
1.85M
                        let (s, base) = i.val();
457
1.85M
                        (
458
1.85M
                            $parse(&FloatVal::Val {
459
1.85M
                                hex: base == 16,
460
1.85M
                                integral: s.into(),
461
1.85M
                                decimal: None,
462
1.85M
                                exponent: None,
463
1.85M
                            }),
464
1.85M
                            rest,
465
1.85M
                        )
466
                    } else {
467
141
                        return Err(c.error("expected a float"));
468
                    };
469
1.92M
                    match val {
470
1.92M
                        Some(bits) => Ok(($name { bits }, rest)),
471
33
                        None => Err(c.error("invalid float value: constant out of range")),
472
                    }
473
1.92M
                })
<wast::ast::token::Float32 as wast::parser::Parse>::parse::{closure#0}
Line
Count
Source
452
314k
                parser.step(|c| {
453
314k
                    let (val, rest) = if let Some((f, rest)) = c.float() {
454
79.8k
                        ($parse(f.val()), rest)
455
234k
                    } else if let Some((i, rest)) = c.integer() {
456
234k
                        let (s, base) = i.val();
457
234k
                        (
458
234k
                            $parse(&FloatVal::Val {
459
234k
                                hex: base == 16,
460
234k
                                integral: s.into(),
461
234k
                                decimal: None,
462
234k
                                exponent: None,
463
234k
                            }),
464
234k
                            rest,
465
234k
                        )
466
                    } else {
467
154
                        return Err(c.error("expected a float"));
468
                    };
469
314k
                    match val {
470
313k
                        Some(bits) => Ok(($name { bits }, rest)),
471
50
                        None => Err(c.error("invalid float value: constant out of range")),
472
                    }
473
314k
                })
474
2.24M
            }
<wast::ast::token::Float32 as wast::parser::Parse>::parse
Line
Count
Source
451
314k
            fn parse(parser: Parser<'a>) -> Result<Self> {
452
                parser.step(|c| {
453
                    let (val, rest) = if let Some((f, rest)) = c.float() {
454
                        ($parse(f.val()), rest)
455
                    } else if let Some((i, rest)) = c.integer() {
456
                        let (s, base) = i.val();
457
                        (
458
                            $parse(&FloatVal::Val {
459
                                hex: base == 16,
460
                                integral: s.into(),
461
                                decimal: None,
462
                                exponent: None,
463
                            }),
464
                            rest,
465
                        )
466
                    } else {
467
                        return Err(c.error("expected a float"));
468
                    };
469
                    match val {
470
                        Some(bits) => Ok(($name { bits }, rest)),
471
                        None => Err(c.error("invalid float value: constant out of range")),
472
                    }
473
                })
474
314k
            }
<wast::ast::token::Float64 as wast::parser::Parse>::parse
Line
Count
Source
451
1.92M
            fn parse(parser: Parser<'a>) -> Result<Self> {
452
                parser.step(|c| {
453
                    let (val, rest) = if let Some((f, rest)) = c.float() {
454
                        ($parse(f.val()), rest)
455
                    } else if let Some((i, rest)) = c.integer() {
456
                        let (s, base) = i.val();
457
                        (
458
                            $parse(&FloatVal::Val {
459
                                hex: base == 16,
460
                                integral: s.into(),
461
                                decimal: None,
462
                                exponent: None,
463
                            }),
464
                            rest,
465
                        )
466
                    } else {
467
                        return Err(c.error("expected a float"));
468
                    };
469
                    match val {
470
                        Some(bits) => Ok(($name { bits }, rest)),
471
                        None => Err(c.error("invalid float value: constant out of range")),
472
                    }
473
                })
474
1.92M
            }
475
        }
476
477
2.24M
        fn $parse(val: &FloatVal<'_>) -> Option<$int> {
478
            // Compute a few well-known constants about the float representation
479
            // given the parameters to the macro here.
480
2.24M
            let width = std::mem::size_of::<$int>() * 8;
481
2.24M
            let neg_offset = width - 1;
482
2.24M
            let exp_offset = neg_offset - $exp_bits;
483
2.24M
            let signif_bits = width - 1 - $exp_bits;
484
2.24M
            let signif_mask = (1 << exp_offset) - 1;
485
2.24M
            let bias = (1 << ($exp_bits - 1)) - 1;
486
487
2.24M
            let (hex, integral, decimal, exponent_str) = match val {
488
                // Infinity is when the exponent bits are all set and
489
                // the significand is zero.
490
1.78k
                FloatVal::Inf { negative } => {
491
1.78k
                    let exp_bits = (1 << $exp_bits) - 1;
492
1.78k
                    let neg_bit = *negative as $int;
493
1.78k
                    return Some(
494
1.78k
                        (neg_bit << neg_offset) |
495
1.78k
                        (exp_bits << exp_offset)
496
1.78k
                    );
497
                }
498
499
                // NaN is when the exponent bits are all set and
500
                // the significand is nonzero. The default of NaN is
501
                // when only the highest bit of the significand is set.
502
3.74k
                FloatVal::Nan { negative, val } => {
503
3.74k
                    let exp_bits = (1 << $exp_bits) - 1;
504
3.74k
                    let neg_bit = *negative as $int;
505
3.74k
                    let signif = val.unwrap_or(1 << (signif_bits - 1)) as $int;
506
3.74k
                    // If the significand is zero then this is actually infinity
507
3.74k
                    // so we fail to parse it.
508
3.74k
                    if signif & signif_mask == 0 {
509
5
                        return None;
510
3.73k
                    }
511
3.73k
                    return Some(
512
3.73k
                        (neg_bit << neg_offset) |
513
3.73k
                        (exp_bits << exp_offset) |
514
3.73k
                        (signif & signif_mask)
515
3.73k
                    );
516
                }
517
518
                // This is trickier, handle this below
519
2.23M
                FloatVal::Val { hex, integral, decimal, exponent } => {
520
2.23M
                    (hex, integral, decimal, exponent)
521
2.23M
                }
522
2.23M
            };
523
2.23M
524
2.23M
            // Rely on Rust's standard library to parse base 10 floats
525
2.23M
            // correctly.
526
2.23M
            if !*hex {
527
2.16M
                let mut s = integral.to_string();
528
2.16M
                if let Some(decimal) = decimal {
529
112k
                    s.push_str(".");
530
112k
                    s.push_str(&decimal);
531
2.05M
                }
532
2.16M
                if let Some(exponent) = exponent_str {
533
8.33k
                    s.push_str("e");
534
8.33k
                    s.push_str(&exponent);
535
2.15M
                }
536
2.16M
                let float = s.parse::<$float>().ok()?;
537
                // looks like the `*.wat` format considers infinite overflow to
538
                // be invalid.
539
2.16M
                if float.is_infinite() {
540
38
                    return None;
541
2.16M
                }
542
2.16M
                return Some(float.to_bits());
543
68.1k
            }
544
68.1k
545
68.1k
            // Parsing hex floats is... hard! I don't really know what most of
546
68.1k
            // this below does. It was copied from Gecko's implementation in
547
68.1k
            // `WasmTextToBinary.cpp`. Would love comments on this if you have
548
68.1k
            // them!
549
68.1k
            let decimal = decimal.as_ref().map(|s| &**s).unwrap_or("");
wast::ast::token::strtod::{closure#0}
Line
Count
Source
549
9.27k
            let decimal = decimal.as_ref().map(|s| &**s).unwrap_or("");
wast::ast::token::strtof::{closure#0}
Line
Count
Source
549
11.1k
            let decimal = decimal.as_ref().map(|s| &**s).unwrap_or("");
550
68.1k
            let negative = integral.starts_with('-');
551
68.1k
            let integral = integral.trim_start_matches('-').trim_start_matches('0');
552
68.1k
553
68.1k
            // Do a bunch of work up front to locate the first non-zero digit
554
68.1k
            // to determine the initial exponent. There's a number of
555
68.1k
            // adjustments depending on where the digit was found, but the
556
68.1k
            // general idea here is that I'm not really sure why things are
557
68.1k
            // calculated the way they are but it should match Gecko.
558
68.1k
            let decimal_no_leading = decimal.trim_start_matches('0');
559
68.1k
            let decimal_iter = if integral.is_empty() {
560
14.6k
                decimal_no_leading.chars()
561
            } else {
562
53.5k
                decimal.chars()
563
            };
564
68.1k
            let mut digits = integral.chars()
565
526k
                .map(|c| (to_hex(c) as $int, false))
wast::ast::token::strtof::{closure#1}
Line
Count
Source
565
81.4k
                .map(|c| (to_hex(c) as $int, false))
wast::ast::token::strtod::{closure#1}
Line
Count
Source
565
444k
                .map(|c| (to_hex(c) as $int, false))
566
428k
                .chain(decimal_iter.map(|c| (to_hex(c) as $int, true)));
wast::ast::token::strtod::{closure#2}
Line
Count
Source
566
279k
                .chain(decimal_iter.map(|c| (to_hex(c) as $int, true)));
wast::ast::token::strtof::{closure#2}
Line
Count
Source
566
148k
                .chain(decimal_iter.map(|c| (to_hex(c) as $int, true)));
567
68.1k
            let lead_nonzero_digit = match digits.next() {
568
62.4k
                Some((c, _)) => c,
569
                // No digits? Must be `+0` or `-0`, being careful to handle the
570
                // sign encoding here.
571
740
                None if negative => return Some(1 << (width - 1)),
572
4.93k
                None => return Some(0),
573
            };
574
62.4k
            let mut significand = 0 as $int;
575
62.4k
            let mut exponent = if !integral.is_empty() {
576
53.5k
                1
577
            } else {
578
8.98k
                -((decimal.len() - decimal_no_leading.len() + 1) as i32) + 1
579
            };
580
62.4k
            let lz = (lead_nonzero_digit as u8).leading_zeros() as i32 - 4;
581
62.4k
            exponent = exponent.checked_mul(4)?.checked_sub(lz + 1)?;
582
62.4k
            let mut significand_pos = (width - (4 - (lz as usize))) as isize;
583
62.4k
            assert!(significand_pos >= 0);
584
62.4k
            significand |= lead_nonzero_digit << significand_pos;
585
62.4k
586
62.4k
            // Now that we've got an anchor in the string we parse the remaining
587
62.4k
            // digits. Again, not entirely sure why everything is the way it is
588
62.4k
            // here! This is copied frmo gecko.
589
62.4k
            let mut discarded_extra_nonzero = false;
590
954k
            for (digit, decimal) in digits {
591
892k
                if !decimal {
592
472k
                    exponent += 4;
593
419k
                }
594
892k
                if significand_pos > -4 {
595
306k
                    significand_pos -= 4;
596
585k
                }
597
598
892k
                if significand_pos >= 0 {
599
281k
                    significand |= digit << significand_pos;
600
610k
                } else if significand_pos > -4 {
601
9.10k
                    significand |= digit >> (4 - significand_pos);
602
9.10k
                    discarded_extra_nonzero = (digit & !((!0) >> (4 - significand_pos))) != 0;
603
601k
                } else if digit != 0 {
604
174k
                    discarded_extra_nonzero = true;
605
427k
                }
606
            }
607
608
62.4k
            exponent = exponent.checked_add(match exponent_str {
609
8.14k
                Some(s) => s.parse::<i32>().ok()?,
610
54.3k
                None => 0,
611
0
            })?;
612
            debug_assert!(significand != 0);
613
614
62.4k
            let (encoded_exponent, encoded_significand, discarded_significand) =
615
62.4k
                if exponent <= -bias {
616
                    // Underflow to subnormal or zero.
617
4.31k
                    let shift = exp_offset as i32 + exponent + bias;
618
4.31k
                    if shift == 0 {
619
415
                        (0, 0, significand)
620
3.90k
                    } else if shift < 0 || shift >= width as i32 {
621
810
                        (0, 0, 0)
622
                    } else {
623
3.09k
                        (
624
3.09k
                            0,
625
3.09k
                            significand >> (width as i32 - shift),
626
3.09k
                            significand << shift,
627
3.09k
                        )
628
                    }
629
58.1k
                } else if exponent <= bias {
630
                    // Normal (non-zero). The significand's leading 1 is encoded
631
                    // implicitly.
632
58.1k
                    (
633
58.1k
                        ((exponent + bias) as $int) << exp_offset,
634
58.1k
                        (significand >> (width - exp_offset - 1)) & signif_mask,
635
58.1k
                        significand << (exp_offset + 1),
636
58.1k
                    )
637
                } else {
638
                    // Overflow to infinity.
639
27
                    (
640
27
                        ((1 << $exp_bits) - 1) << exp_offset,
641
27
                        0,
642
27
                        0,
643
27
                    )
644
                };
645
646
62.4k
            let bits = encoded_exponent | encoded_significand;
647
62.4k
648
62.4k
            // Apply rounding. If this overflows the significand, it carries
649
62.4k
            // into the exponent bit according to the magic of the IEEE 754
650
62.4k
            // encoding.
651
62.4k
            //
652
62.4k
            // Or rather, the comment above is what Gecko says so it's copied
653
62.4k
            // here too.
654
62.4k
            let msb = 1 << (width - 1);
655
62.4k
            let bits = bits
656
62.4k
                + (((discarded_significand & msb != 0)
657
7.35k
                    && ((discarded_significand & !msb != 0) ||
658
366
                         discarded_extra_nonzero ||
659
                         // ties to even
660
306
                         (encoded_significand & 1 != 0))) as $int);
661
662
            // Just before we return the bits be sure to handle the sign bit we
663
            // found at the beginning.
664
62.4k
            let bits = if negative {
665
4.73k
                bits | (1 << (width - 1))
666
            } else {
667
57.7k
                bits
668
            };
669
            // looks like the `*.wat` format considers infinite overflow to
670
            // be invalid.
671
62.4k
            if $float::from_bits(bits).is_infinite() {
672
27
                return None;
673
62.4k
            }
674
62.4k
            Some(bits)
675
2.24M
        }
wast::ast::token::strtof
Line
Count
Source
477
314k
        fn $parse(val: &FloatVal<'_>) -> Option<$int> {
478
            // Compute a few well-known constants about the float representation
479
            // given the parameters to the macro here.
480
314k
            let width = std::mem::size_of::<$int>() * 8;
481
314k
            let neg_offset = width - 1;
482
314k
            let exp_offset = neg_offset - $exp_bits;
483
314k
            let signif_bits = width - 1 - $exp_bits;
484
314k
            let signif_mask = (1 << exp_offset) - 1;
485
314k
            let bias = (1 << ($exp_bits - 1)) - 1;
486
487
314k
            let (hex, integral, decimal, exponent_str) = match val {
488
                // Infinity is when the exponent bits are all set and
489
                // the significand is zero.
490
11
                FloatVal::Inf { negative } => {
491
11
                    let exp_bits = (1 << $exp_bits) - 1;
492
11
                    let neg_bit = *negative as $int;
493
11
                    return Some(
494
11
                        (neg_bit << neg_offset) |
495
11
                        (exp_bits << exp_offset)
496
11
                    );
497
                }
498
499
                // NaN is when the exponent bits are all set and
500
                // the significand is nonzero. The default of NaN is
501
                // when only the highest bit of the significand is set.
502
101
                FloatVal::Nan { negative, val } => {
503
101
                    let exp_bits = (1 << $exp_bits) - 1;
504
101
                    let neg_bit = *negative as $int;
505
101
                    let signif = val.unwrap_or(1 << (signif_bits - 1)) as $int;
506
101
                    // If the significand is zero then this is actually infinity
507
101
                    // so we fail to parse it.
508
101
                    if signif & signif_mask == 0 {
509
2
                        return None;
510
99
                    }
511
99
                    return Some(
512
99
                        (neg_bit << neg_offset) |
513
99
                        (exp_bits << exp_offset) |
514
99
                        (signif & signif_mask)
515
99
                    );
516
                }
517
518
                // This is trickier, handle this below
519
313k
                FloatVal::Val { hex, integral, decimal, exponent } => {
520
313k
                    (hex, integral, decimal, exponent)
521
313k
                }
522
313k
            };
523
313k
524
313k
            // Rely on Rust's standard library to parse base 10 floats
525
313k
            // correctly.
526
313k
            if !*hex {
527
298k
                let mut s = integral.to_string();
528
298k
                if let Some(decimal) = decimal {
529
66.3k
                    s.push_str(".");
530
66.3k
                    s.push_str(&decimal);
531
232k
                }
532
298k
                if let Some(exponent) = exponent_str {
533
3.87k
                    s.push_str("e");
534
3.87k
                    s.push_str(&exponent);
535
294k
                }
536
298k
                let float = s.parse::<$float>().ok()?;
537
                // looks like the `*.wat` format considers infinite overflow to
538
                // be invalid.
539
298k
                if float.is_infinite() {
540
22
                    return None;
541
298k
                }
542
298k
                return Some(float.to_bits());
543
15.4k
            }
544
15.4k
545
15.4k
            // Parsing hex floats is... hard! I don't really know what most of
546
15.4k
            // this below does. It was copied from Gecko's implementation in
547
15.4k
            // `WasmTextToBinary.cpp`. Would love comments on this if you have
548
15.4k
            // them!
549
15.4k
            let decimal = decimal.as_ref().map(|s| &**s).unwrap_or("");
550
15.4k
            let negative = integral.starts_with('-');
551
15.4k
            let integral = integral.trim_start_matches('-').trim_start_matches('0');
552
15.4k
553
15.4k
            // Do a bunch of work up front to locate the first non-zero digit
554
15.4k
            // to determine the initial exponent. There's a number of
555
15.4k
            // adjustments depending on where the digit was found, but the
556
15.4k
            // general idea here is that I'm not really sure why things are
557
15.4k
            // calculated the way they are but it should match Gecko.
558
15.4k
            let decimal_no_leading = decimal.trim_start_matches('0');
559
15.4k
            let decimal_iter = if integral.is_empty() {
560
8.97k
                decimal_no_leading.chars()
561
            } else {
562
6.43k
                decimal.chars()
563
            };
564
15.4k
            let mut digits = integral.chars()
565
15.4k
                .map(|c| (to_hex(c) as $int, false))
566
15.4k
                .chain(decimal_iter.map(|c| (to_hex(c) as $int, true)));
567
15.4k
            let lead_nonzero_digit = match digits.next() {
568
12.7k
                Some((c, _)) => c,
569
                // No digits? Must be `+0` or `-0`, being careful to handle the
570
                // sign encoding here.
571
13
                None if negative => return Some(1 << (width - 1)),
572
2.63k
                None => return Some(0),
573
            };
574
12.7k
            let mut significand = 0 as $int;
575
12.7k
            let mut exponent = if !integral.is_empty() {
576
6.43k
                1
577
            } else {
578
6.33k
                -((decimal.len() - decimal_no_leading.len() + 1) as i32) + 1
579
            };
580
12.7k
            let lz = (lead_nonzero_digit as u8).leading_zeros() as i32 - 4;
581
12.7k
            exponent = exponent.checked_mul(4)?.checked_sub(lz + 1)?;
582
12.7k
            let mut significand_pos = (width - (4 - (lz as usize))) as isize;
583
12.7k
            assert!(significand_pos >= 0);
584
12.7k
            significand |= lead_nonzero_digit << significand_pos;
585
12.7k
586
12.7k
            // Now that we've got an anchor in the string we parse the remaining
587
12.7k
            // digits. Again, not entirely sure why everything is the way it is
588
12.7k
            // here! This is copied frmo gecko.
589
12.7k
            let mut discarded_extra_nonzero = false;
590
230k
            for (digit, decimal) in digits {
591
217k
                if !decimal {
592
75.0k
                    exponent += 4;
593
142k
                }
594
217k
                if significand_pos > -4 {
595
88.3k
                    significand_pos -= 4;
596
128k
                }
597
598
217k
                if significand_pos >= 0 {
599
73.1k
                    significand |= digit << significand_pos;
600
144k
                } else if significand_pos > -4 {
601
7.24k
                    significand |= digit >> (4 - significand_pos);
602
7.24k
                    discarded_extra_nonzero = (digit & !((!0) >> (4 - significand_pos))) != 0;
603
136k
                } else if digit != 0 {
604
56.2k
                    discarded_extra_nonzero = true;
605
80.6k
                }
606
            }
607
608
12.7k
            exponent = exponent.checked_add(match exponent_str {
609
151
                Some(s) => s.parse::<i32>().ok()?,
610
12.6k
                None => 0,
611
0
            })?;
612
            debug_assert!(significand != 0);
613
614
12.7k
            let (encoded_exponent, encoded_significand, discarded_significand) =
615
12.7k
                if exponent <= -bias {
616
                    // Underflow to subnormal or zero.
617
2.84k
                    let shift = exp_offset as i32 + exponent + bias;
618
2.84k
                    if shift == 0 {
619
397
                        (0, 0, significand)
620
2.44k
                    } else if shift < 0 || shift >= width as i32 {
621
716
                        (0, 0, 0)
622
                    } else {
623
1.73k
                        (
624
1.73k
                            0,
625
1.73k
                            significand >> (width as i32 - shift),
626
1.73k
                            significand << shift,
627
1.73k
                        )
628
                    }
629
9.92k
                } else if exponent <= bias {
630
                    // Normal (non-zero). The significand's leading 1 is encoded
631
                    // implicitly.
632
9.90k
                    (
633
9.90k
                        ((exponent + bias) as $int) << exp_offset,
634
9.90k
                        (significand >> (width - exp_offset - 1)) & signif_mask,
635
9.90k
                        significand << (exp_offset + 1),
636
9.90k
                    )
637
                } else {
638
                    // Overflow to infinity.
639
21
                    (
640
21
                        ((1 << $exp_bits) - 1) << exp_offset,
641
21
                        0,
642
21
                        0,
643
21
                    )
644
                };
645
646
12.7k
            let bits = encoded_exponent | encoded_significand;
647
12.7k
648
12.7k
            // Apply rounding. If this overflows the significand, it carries
649
12.7k
            // into the exponent bit according to the magic of the IEEE 754
650
12.7k
            // encoding.
651
12.7k
            //
652
12.7k
            // Or rather, the comment above is what Gecko says so it's copied
653
12.7k
            // here too.
654
12.7k
            let msb = 1 << (width - 1);
655
12.7k
            let bits = bits
656
12.7k
                + (((discarded_significand & msb != 0)
657
2.87k
                    && ((discarded_significand & !msb != 0) ||
658
335
                         discarded_extra_nonzero ||
659
                         // ties to even
660
279
                         (encoded_significand & 1 != 0))) as $int);
661
662
            // Just before we return the bits be sure to handle the sign bit we
663
            // found at the beginning.
664
12.7k
            let bits = if negative {
665
378
                bits | (1 << (width - 1))
666
            } else {
667
12.3k
                bits
668
            };
669
            // looks like the `*.wat` format considers infinite overflow to
670
            // be invalid.
671
12.7k
            if $float::from_bits(bits).is_infinite() {
672
21
                return None;
673
12.7k
            }
674
12.7k
            Some(bits)
675
314k
        }
wast::ast::token::strtod
Line
Count
Source
477
1.92M
        fn $parse(val: &FloatVal<'_>) -> Option<$int> {
478
            // Compute a few well-known constants about the float representation
479
            // given the parameters to the macro here.
480
1.92M
            let width = std::mem::size_of::<$int>() * 8;
481
1.92M
            let neg_offset = width - 1;
482
1.92M
            let exp_offset = neg_offset - $exp_bits;
483
1.92M
            let signif_bits = width - 1 - $exp_bits;
484
1.92M
            let signif_mask = (1 << exp_offset) - 1;
485
1.92M
            let bias = (1 << ($exp_bits - 1)) - 1;
486
487
1.92M
            let (hex, integral, decimal, exponent_str) = match val {
488
                // Infinity is when the exponent bits are all set and
489
                // the significand is zero.
490
1.77k
                FloatVal::Inf { negative } => {
491
1.77k
                    let exp_bits = (1 << $exp_bits) - 1;
492
1.77k
                    let neg_bit = *negative as $int;
493
1.77k
                    return Some(
494
1.77k
                        (neg_bit << neg_offset) |
495
1.77k
                        (exp_bits << exp_offset)
496
1.77k
                    );
497
                }
498
499
                // NaN is when the exponent bits are all set and
500
                // the significand is nonzero. The default of NaN is
501
                // when only the highest bit of the significand is set.
502
3.64k
                FloatVal::Nan { negative, val } => {
503
3.64k
                    let exp_bits = (1 << $exp_bits) - 1;
504
3.64k
                    let neg_bit = *negative as $int;
505
3.64k
                    let signif = val.unwrap_or(1 << (signif_bits - 1)) as $int;
506
3.64k
                    // If the significand is zero then this is actually infinity
507
3.64k
                    // so we fail to parse it.
508
3.64k
                    if signif & signif_mask == 0 {
509
3
                        return None;
510
3.64k
                    }
511
3.64k
                    return Some(
512
3.64k
                        (neg_bit << neg_offset) |
513
3.64k
                        (exp_bits << exp_offset) |
514
3.64k
                        (signif & signif_mask)
515
3.64k
                    );
516
                }
517
518
                // This is trickier, handle this below
519
1.92M
                FloatVal::Val { hex, integral, decimal, exponent } => {
520
1.92M
                    (hex, integral, decimal, exponent)
521
1.92M
                }
522
1.92M
            };
523
1.92M
524
1.92M
            // Rely on Rust's standard library to parse base 10 floats
525
1.92M
            // correctly.
526
1.92M
            if !*hex {
527
1.86M
                let mut s = integral.to_string();
528
1.86M
                if let Some(decimal) = decimal {
529
45.9k
                    s.push_str(".");
530
45.9k
                    s.push_str(&decimal);
531
1.82M
                }
532
1.86M
                if let Some(exponent) = exponent_str {
533
4.45k
                    s.push_str("e");
534
4.45k
                    s.push_str(&exponent);
535
1.86M
                }
536
1.86M
                let float = s.parse::<$float>().ok()?;
537
                // looks like the `*.wat` format considers infinite overflow to
538
                // be invalid.
539
1.86M
                if float.is_infinite() {
540
16
                    return None;
541
1.86M
                }
542
1.86M
                return Some(float.to_bits());
543
52.7k
            }
544
52.7k
545
52.7k
            // Parsing hex floats is... hard! I don't really know what most of
546
52.7k
            // this below does. It was copied from Gecko's implementation in
547
52.7k
            // `WasmTextToBinary.cpp`. Would love comments on this if you have
548
52.7k
            // them!
549
52.7k
            let decimal = decimal.as_ref().map(|s| &**s).unwrap_or("");
550
52.7k
            let negative = integral.starts_with('-');
551
52.7k
            let integral = integral.trim_start_matches('-').trim_start_matches('0');
552
52.7k
553
52.7k
            // Do a bunch of work up front to locate the first non-zero digit
554
52.7k
            // to determine the initial exponent. There's a number of
555
52.7k
            // adjustments depending on where the digit was found, but the
556
52.7k
            // general idea here is that I'm not really sure why things are
557
52.7k
            // calculated the way they are but it should match Gecko.
558
52.7k
            let decimal_no_leading = decimal.trim_start_matches('0');
559
52.7k
            let decimal_iter = if integral.is_empty() {
560
5.68k
                decimal_no_leading.chars()
561
            } else {
562
47.0k
                decimal.chars()
563
            };
564
52.7k
            let mut digits = integral.chars()
565
52.7k
                .map(|c| (to_hex(c) as $int, false))
566
52.7k
                .chain(decimal_iter.map(|c| (to_hex(c) as $int, true)));
567
52.7k
            let lead_nonzero_digit = match digits.next() {
568
49.7k
                Some((c, _)) => c,
569
                // No digits? Must be `+0` or `-0`, being careful to handle the
570
                // sign encoding here.
571
727
                None if negative => return Some(1 << (width - 1)),
572
2.30k
                None => return Some(0),
573
            };
574
49.7k
            let mut significand = 0 as $int;
575
49.7k
            let mut exponent = if !integral.is_empty() {
576
47.0k
                1
577
            } else {
578
2.64k
                -((decimal.len() - decimal_no_leading.len() + 1) as i32) + 1
579
            };
580
49.7k
            let lz = (lead_nonzero_digit as u8).leading_zeros() as i32 - 4;
581
49.7k
            exponent = exponent.checked_mul(4)?.checked_sub(lz + 1)?;
582
49.7k
            let mut significand_pos = (width - (4 - (lz as usize))) as isize;
583
49.7k
            assert!(significand_pos >= 0);
584
49.7k
            significand |= lead_nonzero_digit << significand_pos;
585
49.7k
586
49.7k
            // Now that we've got an anchor in the string we parse the remaining
587
49.7k
            // digits. Again, not entirely sure why everything is the way it is
588
49.7k
            // here! This is copied frmo gecko.
589
49.7k
            let mut discarded_extra_nonzero = false;
590
724k
            for (digit, decimal) in digits {
591
674k
                if !decimal {
592
397k
                    exponent += 4;
593
277k
                }
594
674k
                if significand_pos > -4 {
595
218k
                    significand_pos -= 4;
596
456k
                }
597
598
674k
                if significand_pos >= 0 {
599
208k
                    significand |= digit << significand_pos;
600
466k
                } else if significand_pos > -4 {
601
1.86k
                    significand |= digit >> (4 - significand_pos);
602
1.86k
                    discarded_extra_nonzero = (digit & !((!0) >> (4 - significand_pos))) != 0;
603
464k
                } else if digit != 0 {
604
118k
                    discarded_extra_nonzero = true;
605
346k
                }
606
            }
607
608
49.7k
            exponent = exponent.checked_add(match exponent_str {
609
7.99k
                Some(s) => s.parse::<i32>().ok()?,
610
41.7k
                None => 0,
611
0
            })?;
612
            debug_assert!(significand != 0);
613
614
49.7k
            let (encoded_exponent, encoded_significand, discarded_significand) =
615
49.7k
                if exponent <= -bias {
616
                    // Underflow to subnormal or zero.
617
1.47k
                    let shift = exp_offset as i32 + exponent + bias;
618
1.47k
                    if shift == 0 {
619
18
                        (0, 0, significand)
620
1.45k
                    } else if shift < 0 || shift >= width as i32 {
621
94
                        (0, 0, 0)
622
                    } else {
623
1.36k
                        (
624
1.36k
                            0,
625
1.36k
                            significand >> (width as i32 - shift),
626
1.36k
                            significand << shift,
627
1.36k
                        )
628
                    }
629
48.2k
                } else if exponent <= bias {
630
                    // Normal (non-zero). The significand's leading 1 is encoded
631
                    // implicitly.
632
48.2k
                    (
633
48.2k
                        ((exponent + bias) as $int) << exp_offset,
634
48.2k
                        (significand >> (width - exp_offset - 1)) & signif_mask,
635
48.2k
                        significand << (exp_offset + 1),
636
48.2k
                    )
637
                } else {
638
                    // Overflow to infinity.
639
6
                    (
640
6
                        ((1 << $exp_bits) - 1) << exp_offset,
641
6
                        0,
642
6
                        0,
643
6
                    )
644
                };
645
646
49.7k
            let bits = encoded_exponent | encoded_significand;
647
49.7k
648
49.7k
            // Apply rounding. If this overflows the significand, it carries
649
49.7k
            // into the exponent bit according to the magic of the IEEE 754
650
49.7k
            // encoding.
651
49.7k
            //
652
49.7k
            // Or rather, the comment above is what Gecko says so it's copied
653
49.7k
            // here too.
654
49.7k
            let msb = 1 << (width - 1);
655
49.7k
            let bits = bits
656
49.7k
                + (((discarded_significand & msb != 0)
657
4.47k
                    && ((discarded_significand & !msb != 0) ||
658
31
                         discarded_extra_nonzero ||
659
                         // ties to even
660
27
                         (encoded_significand & 1 != 0))) as $int);
661
662
            // Just before we return the bits be sure to handle the sign bit we
663
            // found at the beginning.
664
49.7k
            let bits = if negative {
665
4.35k
                bits | (1 << (width - 1))
666
            } else {
667
45.3k
                bits
668
            };
669
            // looks like the `*.wat` format considers infinite overflow to
670
            // be invalid.
671
49.7k
            if $float::from_bits(bits).is_infinite() {
672
6
                return None;
673
49.7k
            }
674
49.7k
            Some(bits)
675
1.92M
        }
676
677
    )*)
678
}
679
680
float! {
681
    Float32 => {
682
        bits: u32,
683
        float: f32,
684
        exponent_bits: 8,
685
        name: strtof,
686
    }
687
    Float64 => {
688
        bits: u64,
689
        float: f64,
690
        exponent_bits: 11,
691
        name: strtod,
692
    }
693
}
694
695
954k
fn to_hex(c: char) -> u8 {
696
954k
    match c {
697
160k
        'a'..='f' => c as u8 - b'a' + 10,
698
54.4k
        'A'..='F' => c as u8 - b'A' + 10,
699
740k
        _ => c as u8 - b'0',
700
    }
701
954k
}
702
703
/// A convenience type to use with [`Parser::peek`](crate::parser::Parser::peek)
704
/// to see if the next token is an s-expression.
705
pub struct LParen {
706
    _priv: (),
707
}
708
709
impl Peek for LParen {
710
1.05M
    fn peek(cursor: Cursor<'_>) -> bool {
711
1.05M
        cursor.lparen().is_some()
712
1.05M
    }
713
714
2.82k
    fn display() -> &'static str {
715
2.82k
        "left paren"
716
2.82k
    }
717
}
718
719
#[cfg(test)]
720
mod tests {
721
    #[test]
722
    fn hex_strtof() {
723
        macro_rules! f {
724
            ($a:tt) => (f!(@mk $a, None, None));
725
            ($a:tt p $e:tt) => (f!(@mk $a, None, Some($e.into())));
726
            ($a:tt . $b:tt) => (f!(@mk $a, Some($b.into()), None));
727
            ($a:tt . $b:tt p $e:tt) => (f!(@mk $a, Some($b.into()), Some($e.into())));
728
            (@mk $a:tt, $b:expr, $e:expr) => (crate::lexer::FloatVal::Val {
729
                hex: true,
730
                integral: $a.into(),
731
                decimal: $b,
732
                exponent: $e
733
            });
734
        }
735
        assert_eq!(super::strtof(&f!("0")), Some(0));
736
        assert_eq!(super::strtof(&f!("0" . "0")), Some(0));
737
        assert_eq!(super::strtof(&f!("0" . "0" p "2354")), Some(0));
738
        assert_eq!(super::strtof(&f!("-0")), Some(1 << 31));
739
        assert_eq!(super::strtof(&f!("f32")), Some(0x45732000));
740
        assert_eq!(super::strtof(&f!("0" . "f32")), Some(0x3f732000));
741
        assert_eq!(super::strtof(&f!("1" . "2")), Some(0x3f900000));
742
        assert_eq!(
743
            super::strtof(&f!("0" . "00000100000000000" p "-126")),
744
            Some(0)
745
        );
746
        assert_eq!(
747
            super::strtof(&f!("1" . "fffff4" p "-106")),
748
            Some(0x0afffffa)
749
        );
750
        assert_eq!(super::strtof(&f!("fffff98" p "-133")), Some(0x0afffffa));
751
        assert_eq!(super::strtof(&f!("0" . "081" p "023")), Some(0x48810000));
752
        assert_eq!(
753
            super::strtof(&f!("1" . "00000100000000000" p "-50")),
754
            Some(0x26800000)
755
        );
756
    }
757
}