Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/wast-64.0.0/src/component/import.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::component::*;
2
use crate::kw;
3
use crate::parser::{Cursor, Parse, Parser, Peek, Result};
4
use crate::token::{Id, Index, LParen, NameAnnotation, Span};
5
6
/// An `import` statement and entry in a WebAssembly component.
7
#[derive(Debug)]
8
pub struct ComponentImport<'a> {
9
    /// Where this `import` was defined
10
    pub span: Span,
11
    /// The name of the item being imported.
12
    pub name: ComponentExternName<'a>,
13
    /// The item that's being imported.
14
    pub item: ItemSig<'a>,
15
}
16
17
impl<'a> Parse<'a> for ComponentImport<'a> {
18
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
19
0
        let span = parser.parse::<kw::import>()?.0;
20
0
        let name = parser.parse()?;
21
0
        let item = parser.parens(|p| p.parse())?;
22
0
        Ok(ComponentImport { span, name, item })
23
0
    }
24
}
25
26
/// The different ways an import can be named.
27
#[derive(Debug, Copy, Clone)]
28
pub enum ComponentExternName<'a> {
29
    /// This is a kebab-named import where a top-level name is assigned.
30
    Kebab(&'a str),
31
    /// This is an interface import where the string is an ID.
32
    Interface(&'a str),
33
}
34
35
impl<'a> Parse<'a> for ComponentExternName<'a> {
36
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
37
0
        if parser.peek::<LParen>()? {
38
0
            Ok(ComponentExternName::Interface(parser.parens(|p| {
39
0
                p.parse::<kw::interface>()?;
40
0
                p.parse()
41
0
            })?))
42
        } else {
43
0
            Ok(ComponentExternName::Kebab(parser.parse()?))
44
        }
45
0
    }
46
}
47
48
/// An item signature for imported items.
49
#[derive(Debug)]
50
pub struct ItemSig<'a> {
51
    /// Where this item is defined in the source.
52
    pub span: Span,
53
    /// An optional identifier used during name resolution to refer to this item
54
    /// from the rest of the component.
55
    pub id: Option<Id<'a>>,
56
    /// An optional name which, for functions, will be stored in the
57
    /// custom `name` section.
58
    pub name: Option<NameAnnotation<'a>>,
59
    /// What kind of item this is.
60
    pub kind: ItemSigKind<'a>,
61
}
62
63
impl<'a> Parse<'a> for ItemSig<'a> {
64
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
65
0
        parse_item_sig(parser, true)
66
0
    }
67
}
68
69
/// An item signature for imported items.
70
#[derive(Debug)]
71
pub struct ItemSigNoName<'a>(pub ItemSig<'a>);
72
73
impl<'a> Parse<'a> for ItemSigNoName<'a> {
74
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
75
0
        Ok(ItemSigNoName(parse_item_sig(parser, false)?))
76
0
    }
77
}
78
79
0
fn parse_item_sig<'a>(parser: Parser<'a>, name: bool) -> Result<ItemSig<'a>> {
80
0
    let mut l = parser.lookahead1();
81
0
    let (span, parse_kind): (_, fn(Parser<'a>) -> Result<ItemSigKind>) = if l.peek::<kw::core>()? {
82
0
        let span = parser.parse::<kw::core>()?.0;
83
0
        parser.parse::<kw::module>()?;
84
0
        (span, |parser| Ok(ItemSigKind::CoreModule(parser.parse()?)))
85
0
    } else if l.peek::<kw::func>()? {
86
0
        let span = parser.parse::<kw::func>()?.0;
87
0
        (span, |parser| Ok(ItemSigKind::Func(parser.parse()?)))
88
0
    } else if l.peek::<kw::component>()? {
89
0
        let span = parser.parse::<kw::component>()?.0;
90
0
        (span, |parser| Ok(ItemSigKind::Component(parser.parse()?)))
91
0
    } else if l.peek::<kw::instance>()? {
92
0
        let span = parser.parse::<kw::instance>()?.0;
93
0
        (span, |parser| Ok(ItemSigKind::Instance(parser.parse()?)))
94
0
    } else if l.peek::<kw::value>()? {
95
0
        let span = parser.parse::<kw::value>()?.0;
96
0
        (span, |parser| Ok(ItemSigKind::Value(parser.parse()?)))
97
0
    } else if l.peek::<kw::r#type>()? {
98
0
        let span = parser.parse::<kw::r#type>()?.0;
99
0
        (span, |parser| {
100
0
            Ok(ItemSigKind::Type(parser.parens(|parser| parser.parse())?))
101
0
        })
102
    } else {
103
0
        return Err(l.error());
104
    };
105
    Ok(ItemSig {
106
0
        span,
107
0
        id: if name { parser.parse()? } else { None },
108
0
        name: if name { parser.parse()? } else { None },
109
0
        kind: parse_kind(parser)?,
110
    })
111
0
}
112
113
/// The kind of signatures for imported items.
114
#[derive(Debug)]
115
pub enum ItemSigKind<'a> {
116
    /// The item signature is for a core module.
117
    CoreModule(CoreTypeUse<'a, ModuleType<'a>>),
118
    /// The item signature is for a function.
119
    Func(ComponentTypeUse<'a, ComponentFunctionType<'a>>),
120
    /// The item signature is for a component.
121
    Component(ComponentTypeUse<'a, ComponentType<'a>>),
122
    /// The item signature is for an instance.
123
    Instance(ComponentTypeUse<'a, InstanceType<'a>>),
124
    /// The item signature is for a value.
125
    Value(ComponentValTypeUse<'a>),
126
    /// The item signature is for a type.
127
    Type(TypeBounds<'a>),
128
}
129
130
/// Represents the bounds applied to types being imported.
131
#[derive(Debug)]
132
pub enum TypeBounds<'a> {
133
    /// The equality type bounds.
134
    Eq(Index<'a>),
135
    /// A resource type is imported/exported,
136
    SubResource,
137
}
138
139
impl<'a> Parse<'a> for TypeBounds<'a> {
140
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
141
0
        let mut l = parser.lookahead1();
142
0
        if l.peek::<kw::eq>()? {
143
0
            parser.parse::<kw::eq>()?;
144
0
            Ok(Self::Eq(parser.parse()?))
145
0
        } else if l.peek::<kw::sub>()? {
146
0
            parser.parse::<kw::sub>()?;
147
0
            parser.parse::<kw::resource>()?;
148
0
            Ok(Self::SubResource)
149
        } else {
150
0
            Err(l.error())
151
        }
152
0
    }
153
}
154
155
/// A listing of a inline `(import "foo")` statement.
156
///
157
/// This is the same as `core::InlineImport` except only one string import is
158
/// required.
159
#[derive(Debug, Clone)]
160
pub struct InlineImport<'a> {
161
    /// The name of the item being imported.
162
    pub name: ComponentExternName<'a>,
163
}
164
165
impl<'a> Parse<'a> for InlineImport<'a> {
166
0
    fn parse(parser: Parser<'a>) -> Result<Self> {
167
0
        parser.parens(|p| {
168
0
            p.parse::<kw::import>()?;
169
0
            Ok(InlineImport { name: p.parse()? })
170
0
        })
171
0
    }
172
}
173
174
impl Peek for InlineImport<'_> {
175
0
    fn peek(cursor: Cursor<'_>) -> Result<bool> {
176
0
        let cursor = match cursor.lparen()? {
177
0
            Some(cursor) => cursor,
178
0
            None => return Ok(false),
179
        };
180
0
        let cursor = match cursor.keyword()? {
181
0
            Some(("import", cursor)) => cursor,
182
0
            _ => return Ok(false),
183
        };
184
185
        // (import "foo")
186
0
        if let Some((_, cursor)) = cursor.string()? {
187
0
            return Ok(cursor.rparen()?.is_some());
188
0
        }
189
190
        // (import (interface "foo"))
191
0
        let cursor = match cursor.lparen()? {
192
0
            Some(cursor) => cursor,
193
0
            None => return Ok(false),
194
        };
195
0
        let cursor = match cursor.keyword()? {
196
0
            Some(("interface", cursor)) => cursor,
197
0
            _ => return Ok(false),
198
        };
199
0
        let cursor = match cursor.string()? {
200
0
            Some((_, cursor)) => cursor,
201
0
            _ => return Ok(false),
202
        };
203
0
        let cursor = match cursor.rparen()? {
204
0
            Some(cursor) => cursor,
205
0
            _ => return Ok(false),
206
        };
207
0
        Ok(cursor.rparen()?.is_some())
208
0
    }
209
210
0
    fn display() -> &'static str {
211
0
        "inline import"
212
0
    }
213
}