/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 | | } |