Coverage Report

Created: 2026-02-14 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/wast-245.0.0/src/token.rs
Line
Count
Source
1
//! Common tokens that implement the [`Parse`] trait which are otherwise not
2
//! associated specifically with the wasm text format per se (useful in other
3
//! contexts too perhaps).
4
5
use crate::annotation;
6
use crate::lexer::Float;
7
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
8
use std::fmt;
9
use std::hash::{Hash, Hasher};
10
use std::str;
11
12
/// A position in the original source stream, used to render errors.
13
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
14
pub struct Span {
15
    pub(crate) offset: usize,
16
}
17
18
impl Span {
19
    /// Construct a `Span` from a byte offset in the source file.
20
0
    pub fn from_offset(offset: usize) -> Self {
21
0
        Span { offset }
22
0
    }
23
24
    /// Returns the line/column information of this span within `text`.
25
    /// Line and column numbers are 0-indexed. User presentation is typically
26
    /// 1-indexed, but 0-indexing is appropriate for internal use with
27
    /// iterators and slices.
28
0
    pub fn linecol_in(&self, text: &str) -> (usize, usize) {
29
0
        let mut cur = 0;
30
        // Use split_terminator instead of lines so that if there is a `\r`,
31
        // it is included in the offset calculation. The `+1` values below
32
        // account for the `\n`.
33
0
        for (i, line) in text.split_terminator('\n').enumerate() {
34
0
            if cur + line.len() + 1 > self.offset {
35
0
                return (i, self.offset - cur);
36
0
            }
37
0
            cur += line.len() + 1;
38
        }
39
0
        (text.lines().count(), 0)
40
0
    }
41
42
    /// Returns the byte offset of this span.
43
0
    pub fn offset(&self) -> usize {
44
0
        self.offset
45
0
    }
46
}
47
48
/// An identifier in a WebAssembly module, prefixed by `$` in the textual
49
/// format.
50
///
51
/// An identifier is used to symbolically refer to items in a a wasm module,
52
/// typically via the [`Index`] type.
53
#[derive(Copy, Clone)]
54
pub struct Id<'a> {
55
    name: &'a str,
56
    generation: u32,
57
    span: Span,
58
}
59
60
impl<'a> Id<'a> {
61
    /// Construct a new identifier from given string.
62
    ///
63
    /// Note that `name` can be any arbitrary string according to the
64
    /// WebAssembly/annotations proposal.
65
0
    pub fn new(name: &'a str, span: Span) -> Id<'a> {
66
0
        Id {
67
0
            name,
68
0
            generation: 0,
69
0
            span,
70
0
        }
71
0
    }
72
73
    #[cfg(feature = "wasm-module")]
74
0
    pub(crate) fn gensym(span: Span, generation: u32) -> Id<'a> {
75
0
        Id {
76
0
            name: "gensym",
77
0
            generation,
78
0
            span,
79
0
        }
80
0
    }
81
82
    /// Returns the underlying name of this identifier.
83
    ///
84
    /// The name returned does not contain the leading `$`.
85
0
    pub fn name(&self) -> &'a str {
86
0
        self.name
87
0
    }
88
89
    /// Returns span of this identifier in the original source
90
0
    pub fn span(&self) -> Span {
91
0
        self.span
92
0
    }
93
94
    #[cfg(feature = "wasm-module")]
95
0
    pub(crate) fn is_gensym(&self) -> bool {
96
0
        self.generation != 0
97
0
    }
98
}
99
100
impl<'a> Hash for Id<'a> {
101
0
    fn hash<H: Hasher>(&self, hasher: &mut H) {
102
0
        self.name.hash(hasher);
103
0
        self.generation.hash(hasher);
104
0
    }
105
}
106
107
impl<'a> PartialEq for Id<'a> {
108
0
    fn eq(&self, other: &Id<'a>) -> bool {
109
0
        self.name == other.name && self.generation == other.generation
110
0
    }
111
}
112
113
impl<'a> Eq for Id<'a> {}
114
115
impl<'a> Parse<'a> for Id<'a> {
116
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
117
0
        parser.step(|c| {
118
0
            if let Some((name, rest)) = c.id()? {
119
0
                return Ok((
120
0
                    Id {
121
0
                        name,
122
0
                        generation: 0,
123
0
                        span: c.cur_span(),
124
0
                    },
125
0
                    rest,
126
0
                ));
127
0
            }
128
0
            Err(c.error("expected an identifier"))
129
0
        })
130
0
    }
131
}
132
133
impl fmt::Debug for Id<'_> {
134
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135
0
        if self.generation != 0 {
136
0
            f.debug_struct("Id")
137
0
                .field("generation", &self.generation)
138
0
                .finish()
139
        } else {
140
0
            self.name.fmt(f)
141
        }
142
0
    }
143
}
144
145
impl Peek for Id<'_> {
146
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
147
0
        cursor.peek_id()
148
0
    }
149
150
0
    fn display() -> &'static str {
151
0
        "an identifier"
152
0
    }
153
}
154
155
/// A reference to another item in a wasm module.
156
///
157
/// This type is used for items referring to other items (such as `call $foo`
158
/// referencing function `$foo`). References can be either an index (u32) or an
159
/// [`Id`] in the textual format.
160
///
161
/// The emission phase of a module will ensure that `Index::Id` is never used
162
/// and switch them all to `Index::Num`.
163
#[derive(Copy, Clone, Debug)]
164
pub enum Index<'a> {
165
    /// A numerical index that this references. The index space this is
166
    /// referencing is implicit based on where this [`Index`] is stored.
167
    Num(u32, Span),
168
    /// A human-readable identifier this references. Like `Num`, the namespace
169
    /// this references is based on where this is stored.
170
    Id(Id<'a>),
171
}
172
173
impl Index<'_> {
174
    /// Returns the source location where this `Index` was defined.
175
0
    pub fn span(&self) -> Span {
176
0
        match self {
177
0
            Index::Num(_, span) => *span,
178
0
            Index::Id(id) => id.span(),
179
        }
180
0
    }
181
182
    #[cfg(feature = "wasm-module")]
183
0
    pub(crate) fn is_resolved(&self) -> bool {
184
0
        matches!(self, Index::Num(..))
185
0
    }
186
}
187
188
impl<'a> Parse<'a> for Index<'a> {
189
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
190
0
        if parser.peek::<Id>()? {
191
0
            Ok(Index::Id(parser.parse()?))
192
0
        } else if parser.peek::<u32>()? {
193
0
            let (val, span) = parser.parse()?;
194
0
            Ok(Index::Num(val, span))
195
        } else {
196
0
            Err(parser.error(format!(
197
0
                "unexpected token, expected an index or an identifier"
198
0
            )))
199
        }
200
0
    }
201
}
202
203
impl Peek for Index<'_> {
204
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
205
0
        Ok(u32::peek(cursor)? || Id::peek(cursor)?)
206
0
    }
207
208
0
    fn display() -> &'static str {
209
0
        "an index"
210
0
    }
211
}
212
213
impl<'a> From<Id<'a>> for Index<'a> {
214
0
    fn from(id: Id<'a>) -> Index<'a> {
215
0
        Index::Id(id)
216
0
    }
217
}
218
219
impl PartialEq for Index<'_> {
220
0
    fn eq(&self, other: &Index<'_>) -> bool {
221
0
        match (self, other) {
222
0
            (Index::Num(a, _), Index::Num(b, _)) => a == b,
223
0
            (Index::Id(a), Index::Id(b)) => a == b,
224
0
            _ => false,
225
        }
226
0
    }
227
}
228
229
impl Eq for Index<'_> {}
230
231
impl Hash for Index<'_> {
232
0
    fn hash<H: Hasher>(&self, hasher: &mut H) {
233
0
        match self {
234
0
            Index::Num(a, _) => {
235
0
                0u8.hash(hasher);
236
0
                a.hash(hasher);
237
0
            }
238
0
            Index::Id(a) => {
239
0
                1u8.hash(hasher);
240
0
                a.hash(hasher);
241
0
            }
242
        }
243
0
    }
244
}
245
246
/// Parses `(func $foo)`
247
#[derive(Clone, Debug)]
248
#[allow(missing_docs)]
249
pub struct ItemRef<'a, K> {
250
    pub kind: K,
251
    pub idx: Index<'a>,
252
}
253
254
impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> {
255
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
256
0
        parser.parens(|parser| {
257
0
            let kind = parser.parse::<K>()?;
258
0
            let idx = parser.parse()?;
259
0
            Ok(ItemRef { kind, idx })
260
0
        })
261
0
    }
262
}
263
264
impl<'a, K: Peek> Peek for ItemRef<'a, K> {
265
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
266
0
        match cursor.lparen()? {
267
0
            Some(remaining) => K::peek(remaining),
268
0
            None => Ok(false),
269
        }
270
0
    }
271
272
0
    fn display() -> &'static str {
273
0
        "an item reference"
274
0
    }
275
}
276
277
/// An `@name` annotation in source, currently of the form `@name "foo"`
278
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
279
pub struct NameAnnotation<'a> {
280
    /// The name specified for the item
281
    pub name: &'a str,
282
}
283
284
impl<'a> Parse<'a> for NameAnnotation<'a> {
285
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
286
0
        parser.parse::<annotation::name>()?;
287
0
        let name = parser.parse()?;
288
0
        Ok(NameAnnotation { name })
289
0
    }
290
}
291
292
impl<'a> Parse<'a> for Option<NameAnnotation<'a>> {
293
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
294
0
        Ok(if parser.peek2::<annotation::name>()? {
295
0
            Some(parser.parens(|p| p.parse())?)
296
        } else {
297
0
            None
298
        })
299
0
    }
300
}
301
302
macro_rules! integers {
303
    ($($i:ident($u:ident))*) => ($(
304
        impl<'a> Parse<'a> for $i {
305
0
            fn parse(parser: Parser<'a>) -> Result<Self> {
306
0
                Ok(parser.parse::<($i, Span)>()?.0)
307
0
            }
Unexecuted instantiation: <i8 as wast::parser::Parse>::parse
Unexecuted instantiation: <i16 as wast::parser::Parse>::parse
Unexecuted instantiation: <i32 as wast::parser::Parse>::parse
Unexecuted instantiation: <i64 as wast::parser::Parse>::parse
Unexecuted instantiation: <u8 as wast::parser::Parse>::parse
Unexecuted instantiation: <u16 as wast::parser::Parse>::parse
Unexecuted instantiation: <u32 as wast::parser::Parse>::parse
Unexecuted instantiation: <u64 as wast::parser::Parse>::parse
308
        }
309
310
        impl<'a> Parse<'a> for ($i, Span) {
311
0
            fn parse(parser: Parser<'a>) -> Result<Self> {
312
0
                parser.step(|c| {
313
0
                    if let Some((i, rest)) = c.integer()? {
314
0
                        let (s, base) = i.val();
315
0
                        let val = $i::from_str_radix(s, base)
316
0
                            .or_else(|_| {
317
0
                                $u::from_str_radix(s, base).map(|i| i as $i)
Unexecuted instantiation: <(i8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(i16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(i32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(i64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(u8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(u16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(u32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
Unexecuted instantiation: <(u64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}::{closure#0}
318
0
                            });
Unexecuted instantiation: <(i8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(i16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(i32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(i64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(u8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(u16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(u32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
Unexecuted instantiation: <(u64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}::{closure#0}
319
0
                        return match val {
320
0
                            Ok(n) => Ok(((n, c.cur_span()), rest)),
321
0
                            Err(_) => Err(c.error(concat!(
322
0
                                "invalid ",
323
0
                                stringify!($i),
324
0
                                " number: constant out of range",
325
0
                            ))),
326
                        };
327
0
                    }
328
0
                    Err(c.error(concat!("expected a ", stringify!($i))))
329
0
                })
Unexecuted instantiation: <(i8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(i16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(i32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(i64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(u8, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(u16, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(u32, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <(u64, wast::token::Span) as wast::parser::Parse>::parse::{closure#0}
330
0
            }
Unexecuted instantiation: <(i8, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(i16, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(i32, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(i64, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(u8, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(u16, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(u32, wast::token::Span) as wast::parser::Parse>::parse
Unexecuted instantiation: <(u64, wast::token::Span) as wast::parser::Parse>::parse
331
        }
332
333
        impl Peek for $i {
334
0
            fn peek(cursor: Cursor<'_>) -> Result<bool> {
335
0
                cursor.peek_integer()
336
0
            }
Unexecuted instantiation: <i8 as wast::parser::Peek>::peek
Unexecuted instantiation: <i16 as wast::parser::Peek>::peek
Unexecuted instantiation: <i32 as wast::parser::Peek>::peek
Unexecuted instantiation: <i64 as wast::parser::Peek>::peek
Unexecuted instantiation: <u8 as wast::parser::Peek>::peek
Unexecuted instantiation: <u16 as wast::parser::Peek>::peek
Unexecuted instantiation: <u32 as wast::parser::Peek>::peek
Unexecuted instantiation: <u64 as wast::parser::Peek>::peek
337
338
0
            fn display() -> &'static str {
339
0
                stringify!($i)
340
0
            }
Unexecuted instantiation: <u32 as wast::parser::Peek>::display
Unexecuted instantiation: <u64 as wast::parser::Peek>::display
Unexecuted instantiation: <i8 as wast::parser::Peek>::display
Unexecuted instantiation: <i16 as wast::parser::Peek>::display
Unexecuted instantiation: <i32 as wast::parser::Peek>::display
Unexecuted instantiation: <i64 as wast::parser::Peek>::display
Unexecuted instantiation: <u8 as wast::parser::Peek>::display
Unexecuted instantiation: <u16 as wast::parser::Peek>::display
341
        }
342
    )*)
343
}
344
345
integers! {
346
    u8(u8) u16(u16) u32(u32) u64(u64)
347
    i8(u8) i16(u16) i32(u32) i64(u64)
348
}
349
350
impl<'a> Parse<'a> for &'a [u8] {
351
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
352
0
        parser.step(|c| {
353
0
            if let Some((i, rest)) = c.string()? {
354
0
                return Ok((i, rest));
355
0
            }
356
0
            Err(c.error("expected a string"))
357
0
        })
358
0
    }
359
}
360
361
impl Peek for &'_ [u8] {
362
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
363
0
        cursor.peek_string()
364
0
    }
365
366
0
    fn display() -> &'static str {
367
0
        "string"
368
0
    }
369
}
370
371
impl<'a> Parse<'a> for &'a str {
372
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
373
0
        str::from_utf8(parser.parse()?)
374
0
            .map_err(|_| parser.error_at(parser.prev_span(), "malformed UTF-8 encoding"))
375
0
    }
376
}
377
378
impl Parse<'_> for String {
379
0
    fn parse(parser: Parser<'_>) -> Result<Self> {
380
0
        Ok(<&str>::parse(parser)?.to_string())
381
0
    }
382
}
383
384
impl Peek for &'_ str {
385
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
386
0
        <&[u8]>::peek(cursor)
387
0
    }
388
389
0
    fn display() -> &'static str {
390
0
        <&[u8]>::display()
391
0
    }
392
}
393
394
macro_rules! float {
395
    ($($name:ident => {
396
        bits: $int:ident,
397
        float: $float:ident,
398
        exponent_bits: $exp_bits:tt,
399
        name: $parse:ident,
400
    })*) => ($(
401
        /// A parsed floating-point type
402
        #[derive(Debug, Copy, Clone)]
403
        pub struct $name {
404
            /// The raw bits that this floating point number represents.
405
            pub bits: $int,
406
        }
407
408
        impl<'a> Parse<'a> for $name {
409
0
            fn parse(parser: Parser<'a>) -> Result<Self> {
410
0
                parser.step(|c| {
411
0
                    let (val, rest) = if let Some((f, rest)) = c.float()? {
412
0
                        ($parse(&f), rest)
413
0
                    } else if let Some((i, rest)) = c.integer()? {
414
0
                        let (s, base) = i.val();
415
0
                        (
416
0
                            $parse(&Float::Val {
417
0
                                hex: base == 16,
418
0
                                integral: s.into(),
419
0
                                fractional: None,
420
0
                                exponent: None,
421
0
                            }),
422
0
                            rest,
423
0
                        )
424
                    } else {
425
0
                        return Err(c.error("expected a float"));
426
                    };
427
0
                    match val {
428
0
                        Some(bits) => Ok(($name { bits }, rest)),
429
0
                        None => Err(c.error("invalid float value: constant out of range")),
430
                    }
431
0
                })
Unexecuted instantiation: <wast::token::F32 as wast::parser::Parse>::parse::{closure#0}
Unexecuted instantiation: <wast::token::F64 as wast::parser::Parse>::parse::{closure#0}
432
0
            }
Unexecuted instantiation: <wast::token::F32 as wast::parser::Parse>::parse
Unexecuted instantiation: <wast::token::F64 as wast::parser::Parse>::parse
433
        }
434
435
0
        fn $parse(val: &Float<'_>) -> Option<$int> {
436
            // Compute a few well-known constants about the float representation
437
            // given the parameters to the macro here.
438
0
            let width = std::mem::size_of::<$int>() * 8;
439
0
            let neg_offset = width - 1;
440
0
            let exp_offset = neg_offset - $exp_bits;
441
0
            let signif_bits = width - 1 - $exp_bits;
442
0
            let signif_mask = (1 << exp_offset) - 1;
443
0
            let bias = (1 << ($exp_bits - 1)) - 1;
444
0
            let msb = 1 << neg_offset;
445
446
0
            let (hex, integral, fractional, exponent_str) = match val {
447
                // Infinity is when the exponent bits are all set and
448
                // the significand is zero.
449
0
                Float::Inf { negative } => {
450
0
                    let exp_bits = (1 << $exp_bits) - 1;
451
0
                    let neg_bit = *negative as $int;
452
0
                    return Some(
453
0
                        (neg_bit << neg_offset) |
454
0
                        (exp_bits << exp_offset)
455
0
                    );
456
                }
457
458
                // NaN is when the exponent bits are all set and
459
                // the significand is nonzero. The default of NaN is
460
                // when only the highest bit of the significand is set.
461
0
                Float::Nan { negative, val } => {
462
0
                    let exp_bits = (1 << $exp_bits) - 1;
463
0
                    let neg_bit = *negative as $int;
464
0
                    let signif = match val {
465
0
                        Some(val) => $int::from_str_radix(val,16).ok()?,
466
0
                        None => 1 << (signif_bits - 1),
467
                    };
468
                    // If the significand is zero then this is actually infinity
469
                    // so we fail to parse it.
470
0
                    if signif & signif_mask == 0 {
471
0
                        return None;
472
0
                    }
473
0
                    return Some(
474
0
                        (neg_bit << neg_offset) |
475
0
                        (exp_bits << exp_offset) |
476
0
                        (signif & signif_mask)
477
0
                    );
478
                }
479
480
                // This is trickier, handle this below
481
0
                Float::Val { hex, integral, fractional, exponent } => {
482
0
                    (hex, integral, fractional, exponent)
483
                }
484
            };
485
486
            // Rely on Rust's standard library to parse base 10 floats
487
            // correctly.
488
0
            if !*hex {
489
0
                let mut s = integral.to_string();
490
0
                if let Some(fractional) = fractional {
491
0
                    s.push_str(".");
492
0
                    s.push_str(&fractional);
493
0
                }
494
0
                if let Some(exponent) = exponent_str {
495
0
                    s.push_str("e");
496
0
                    s.push_str(&exponent);
497
0
                }
498
0
                let float = s.parse::<$float>().ok()?;
499
                // looks like the `*.wat` format considers infinite overflow to
500
                // be invalid.
501
0
                if float.is_infinite() {
502
0
                    return None;
503
0
                }
504
0
                return Some(float.to_bits());
505
0
            }
506
507
            // Parse a hexadecimal floating-point value.
508
            //
509
            // The main loop here is simpler than for parsing decimal floats,
510
            // because we can just parse hexadecimal digits and then shift
511
            // their bits into place in the significand. But in addition to
512
            // that, we also need to handle non-normalized representations,
513
            // where the integral part is not "1", to convert them to
514
            // normalized results, to round, in case we get more digits than
515
            // the target format supports, and to handle overflow and subnormal
516
            // cases.
517
518
            // Get slices of digits for the integral and fractional parts. We
519
            // can trivially skip any leading zeros in the integral part.
520
0
            let is_negative = integral.starts_with('-');
521
0
            let integral = integral.trim_start_matches('-').trim_start_matches('0');
522
0
            let fractional = fractional.as_ref().map(|s| &**s).unwrap_or("");
Unexecuted instantiation: wast::token::strtod::{closure#0}
Unexecuted instantiation: wast::token::strtof::{closure#0}
523
524
            // Locate the first non-zero digit to determine the initial exponent.
525
            //
526
            // If there's no integral part, skip past leading zeros so that
527
            // something like "0x.0000000000000000000002" doesn't cause us to hit
528
            // a shift overflow when we try to shift the value into place. We'll
529
            // adjust the exponent below to account for these skipped zeros.
530
0
            let fractional_no_leading = fractional.trim_start_matches('0');
531
0
            let fractional_iter = if integral.is_empty() {
532
0
                fractional_no_leading.chars()
533
            } else {
534
0
                fractional.chars()
535
            };
536
537
            // Create a unified iterator over the digits of the integral part
538
            // followed by the digits of the fractional part. The boolean value
539
            // indicates which of these parts we're in.
540
0
            let mut digits = integral.chars()
541
0
                .map(|c| (to_hex(c) as $int, false))
Unexecuted instantiation: wast::token::strtod::{closure#1}
Unexecuted instantiation: wast::token::strtof::{closure#1}
542
0
                .chain(fractional_iter.map(|c| (to_hex(c) as $int, true)));
Unexecuted instantiation: wast::token::strtod::{closure#2}
Unexecuted instantiation: wast::token::strtof::{closure#2}
543
544
            // Compute the number of leading zeros in the first non-zero digit,
545
            // since if the first digit is not "1" we'll need to adjust for
546
            // normalization.
547
0
            let lead_nonzero_digit = match digits.next() {
548
0
                Some((c, _)) => c,
549
                // No non-zero digits? Must be `+0` or `-0`, being careful to
550
                // handle the sign encoding here.
551
0
                None if is_negative => return Some(msb),
552
0
                None => return Some(0),
553
            };
554
0
            let lz = (lead_nonzero_digit as u8).leading_zeros() as i32 - 4;
555
556
            // Prepare for the main parsing loop. Calculate the initial values
557
            // of `exponent` and `significand` based on what we've seen so far.
558
0
            let mut exponent = if !integral.is_empty() {
559
0
                1
560
            } else {
561
                // Adjust the exponent digits to account for any leading zeros
562
                // in the fractional part that we skipped above.
563
0
                -((fractional.len() - fractional_no_leading.len() + 1) as i32) + 1
564
            };
565
0
            let mut significand_pos = (width - (4 - (lz as usize))) as isize;
566
0
            let mut significand: $int = lead_nonzero_digit << significand_pos;
567
0
            let mut discarded_extra_nonzero = false;
568
569
0
            assert!(significand_pos >= 0, "$int should be at least 4 bits wide");
570
571
            // Adjust for leading zeros in the first digit.
572
0
            exponent = exponent.checked_mul(4)?.checked_sub(lz + 1)?;
573
574
            // Now that we've got an anchor in the string we parse the remaining
575
            // hexadecimal digits.
576
0
            for (digit, in_fractional) in digits {
577
0
                if !in_fractional {
578
0
                    exponent += 4;
579
0
                }
580
0
                if significand_pos > -4 {
581
0
                    significand_pos -= 4;
582
0
                }
583
584
0
                if significand_pos >= 0 {
585
0
                    significand |= digit << significand_pos;
586
0
                } else if significand_pos > -4 {
587
0
                    significand |= digit >> (4 - significand_pos);
588
0
                    discarded_extra_nonzero = (digit & !((!0) >> (4 - significand_pos))) != 0;
589
0
                } else if digit != 0 {
590
0
                    discarded_extra_nonzero = true;
591
0
                }
592
            }
593
594
0
            debug_assert!(significand != 0, "The case of no non-zero digits should have been handled above");
595
596
            // Parse the exponent string, which despite this being a hexadecimal
597
            // syntax, is a decimal number, and add it the exponent we've
598
            // computed from the potentially non-normalized significand.
599
0
            exponent = exponent.checked_add(match exponent_str {
600
0
                Some(s) => s.parse::<i32>().ok()?,
601
0
                None => 0,
602
0
            })?;
603
604
            // Encode the exponent and significand. Also calculate the bits of
605
            // the significand which are discarded, as we'll use them to
606
            // determine if we need to round up.
607
0
            let (encoded_exponent, encoded_significand, discarded_significand) =
608
0
                if exponent <= -bias {
609
                    // Underflow to subnormal or zero.
610
0
                    let shift = exp_offset as i32 + exponent + bias;
611
0
                    if shift == 0 {
612
0
                        (0, 0, significand)
613
0
                    } else if shift < 0 || shift >= width as i32 {
614
0
                        (0, 0, 0)
615
                    } else {
616
0
                        (
617
0
                            0,
618
0
                            significand >> (width as i32 - shift),
619
0
                            significand << shift,
620
0
                        )
621
                    }
622
0
                } else if exponent <= bias {
623
                    // Normal (non-zero). The significand's leading 1 is encoded
624
                    // implicitly.
625
0
                    (
626
0
                        ((exponent + bias) as $int) << exp_offset,
627
0
                        (significand >> (width - exp_offset - 1)) & signif_mask,
628
0
                        significand << (exp_offset + 1),
629
0
                    )
630
                } else {
631
                    // Overflow to infinity.
632
0
                    (
633
0
                        ((1 << $exp_bits) - 1) << exp_offset,
634
0
                        0,
635
0
                        0,
636
0
                    )
637
                };
638
639
            // Combine the encoded exponent and encoded significand to produce
640
            // the raw result, except for the sign bit, which we'll apply at
641
            // the end.
642
0
            let bits = encoded_exponent | encoded_significand;
643
644
            // Apply rounding. Do an integer add of `0` or `1` on the raw
645
            // result, depending on whether rounding is needed. Rounding can
646
            // lead to a floating-point overflow, but we don't need to
647
            // special-case that here because it turns out that IEEE 754 floats
648
            // are encoded such that when an integer add of `1` carries into
649
            // the bits of the exponent field, it produces the correct encoding
650
            // for infinity.
651
0
            let bits = bits
652
0
                + (((discarded_significand & msb != 0)
653
0
                    && ((discarded_significand & !msb != 0) ||
654
0
                         discarded_extra_nonzero ||
655
                         // ties to even
656
0
                         (encoded_significand & 1 != 0))) as $int);
657
658
            // Just before we return the bits, be sure to handle the sign bit we
659
            // found at the beginning.
660
0
            let bits = if is_negative {
661
0
                bits | msb
662
            } else {
663
0
                bits
664
            };
665
            // looks like the `*.wat` format considers infinite overflow to
666
            // be invalid.
667
0
            if $float::from_bits(bits).is_infinite() {
668
0
                return None;
669
0
            }
670
0
            Some(bits)
671
0
        }
Unexecuted instantiation: wast::token::strtod
Unexecuted instantiation: wast::token::strtof
672
673
    )*)
674
}
675
676
float! {
677
    F32 => {
678
        bits: u32,
679
        float: f32,
680
        exponent_bits: 8,
681
        name: strtof,
682
    }
683
    F64 => {
684
        bits: u64,
685
        float: f64,
686
        exponent_bits: 11,
687
        name: strtod,
688
    }
689
}
690
691
0
fn to_hex(c: char) -> u8 {
692
0
    match c {
693
0
        'a'..='f' => c as u8 - b'a' + 10,
694
0
        'A'..='F' => c as u8 - b'A' + 10,
695
0
        _ => c as u8 - b'0',
696
    }
697
0
}
698
699
/// A convenience type to use with [`Parser::peek`](crate::parser::Parser::peek)
700
/// to see if the next token is an s-expression.
701
pub struct LParen {
702
    _priv: (),
703
}
704
705
impl Peek for LParen {
706
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
707
0
        cursor.peek_lparen()
708
0
    }
709
710
0
    fn display() -> &'static str {
711
0
        "left paren"
712
0
    }
713
}
714
715
/// A convenience type to use with [`Parser::peek`](crate::parser::Parser::peek)
716
/// to see if the next token is the end of an s-expression.
717
pub struct RParen {
718
    _priv: (),
719
}
720
721
impl Peek for RParen {
722
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
723
0
        cursor.peek_rparen()
724
0
    }
725
726
0
    fn display() -> &'static str {
727
0
        "right paren"
728
0
    }
729
}
730
731
#[cfg(test)]
732
mod tests {
733
    #[test]
734
    fn hex_strtof() {
735
        macro_rules! f {
736
            ($a:tt) => (f!(@mk $a, None, None));
737
            ($a:tt p $e:tt) => (f!(@mk $a, None, Some($e.into())));
738
            ($a:tt . $b:tt) => (f!(@mk $a, Some($b.into()), None));
739
            ($a:tt . $b:tt p $e:tt) => (f!(@mk $a, Some($b.into()), Some($e.into())));
740
            (@mk $a:tt, $b:expr, $e:expr) => (crate::lexer::Float::Val {
741
                hex: true,
742
                integral: $a.into(),
743
                fractional: $b,
744
                exponent: $e
745
            });
746
        }
747
        assert_eq!(super::strtof(&f!("0")), Some(0));
748
        assert_eq!(super::strtof(&f!("0" . "0")), Some(0));
749
        assert_eq!(super::strtof(&f!("0" . "0" p "2354")), Some(0));
750
        assert_eq!(super::strtof(&f!("-0")), Some(1 << 31));
751
        assert_eq!(super::strtof(&f!("f32")), Some(0x45732000));
752
        assert_eq!(super::strtof(&f!("0" . "f32")), Some(0x3f732000));
753
        assert_eq!(super::strtof(&f!("1" . "2")), Some(0x3f900000));
754
        assert_eq!(
755
            super::strtof(&f!("0" . "00000100000000000" p "-126")),
756
            Some(0)
757
        );
758
        assert_eq!(
759
            super::strtof(&f!("1" . "fffff4" p "-106")),
760
            Some(0x0afffffa)
761
        );
762
        assert_eq!(super::strtof(&f!("fffff98" p "-133")), Some(0x0afffffa));
763
        assert_eq!(super::strtof(&f!("0" . "081" p "023")), Some(0x48810000));
764
        assert_eq!(
765
            super::strtof(&f!("1" . "00000100000000000" p "-50")),
766
            Some(0x26800000)
767
        );
768
    }
769
}