Coverage Report

Created: 2023-04-25 07:07

/rust/registry/src/index.crates.io-6f17d22bba15001f/wast-56.0.0/src/names.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::token::{Id, Index};
2
use crate::Error;
3
use std::collections::HashMap;
4
5
1.27M
#[derive(Default)]
6
pub struct Namespace<'a> {
7
    names: HashMap<Id<'a>, u32>,
8
    count: u32,
9
}
10
11
impl<'a> Namespace<'a> {
12
728k
    pub fn register(&mut self, name: Option<Id<'a>>, desc: &str) -> Result<u32, Error> {
13
728k
        let index = self.alloc();
14
728k
        if let Some(name) = name {
15
383k
            if let Some(_prev) = self.names.insert(name, index) {
16
                // FIXME: temporarily allow duplicately-named data and element
17
                // segments. This is a sort of dumb hack to get the spec test
18
                // suite working (ironically).
19
                //
20
                // So as background, the text format disallows duplicate
21
                // identifiers, causing a parse error if they're found. There
22
                // are two tests currently upstream, however, data.wast and
23
                // elem.wast, which *look* like they have duplicately named
24
                // element and data segments. These tests, however, are using
25
                // pre-bulk-memory syntax where a bare identifier was the
26
                // table/memory being initialized. In post-bulk-memory this
27
                // identifier is the name of the segment. Since we implement
28
                // post-bulk-memory features that means that we're parsing the
29
                // memory/table-to-initialize as the name of the segment.
30
                //
31
                // This is technically incorrect behavior but no one is
32
                // hopefully relying on this too much. To get the spec tests
33
                // passing we ignore errors for elem/data segments. Once the
34
                // spec tests get updated enough we can remove this condition
35
                // and return errors for them.
36
13.2k
                if desc != "elem" && desc != "data" {
37
404
                    return Err(Error::new(
38
404
                        name.span(),
39
404
                        format!("duplicate {} identifier", desc),
40
404
                    ));
41
12.7k
                }
42
369k
            }
43
345k
        }
44
727k
        Ok(index)
45
728k
    }
46
47
728k
    pub fn alloc(&mut self) -> u32 {
48
728k
        let index = self.count;
49
728k
        self.count += 1;
50
728k
        index
51
728k
    }
52
53
    pub fn register_specific(&mut self, name: Id<'a>, index: u32, desc: &str) -> Result<(), Error> {
54
0
        if let Some(_prev) = self.names.insert(name, index) {
55
0
            return Err(Error::new(
56
0
                name.span(),
57
0
                format!("duplicate identifier for {}", desc),
58
0
            ));
59
0
        }
60
0
        Ok(())
61
0
    }
62
63
1.65M
    pub fn resolve(&self, idx: &mut Index<'a>, desc: &str) -> Result<u32, Error> {
64
1.65M
        let id = match idx {
65
938k
            Index::Num(n, _) => return Ok(*n),
66
717k
            Index::Id(id) => id,
67
        };
68
717k
        if let Some(&n) = self.names.get(id) {
69
717k
            *idx = Index::Num(n, id.span());
70
717k
            return Ok(n);
71
45
        }
72
45
        Err(resolve_error(*id, desc))
73
1.65M
    }
74
}
75
76
96
pub fn resolve_error(id: Id<'_>, ns: &str) -> Error {
77
96
    assert!(
78
96
        !id.is_gensym(),
79
0
        "symbol generated by `wast` itself cannot be resolved {:?}",
80
        id
81
    );
82
96
    Error::new(
83
96
        id.span(),
84
96
        format!("unknown {ns}: failed to find name `${}`", id.name()),
85
96
    )
86
96
}