/src/wasm-tools/crates/wit-parser/src/decoding.rs
Line | Count | Source |
1 | | use crate::*; |
2 | | use alloc::string::{String, ToString}; |
3 | | use alloc::vec; |
4 | | use alloc::vec::Vec; |
5 | | use anyhow::Result; |
6 | | use anyhow::{Context, anyhow, bail}; |
7 | | use core::mem; |
8 | | use std::io::Read; |
9 | | use wasmparser::Chunk; |
10 | | use wasmparser::{ |
11 | | ComponentExternalKind, Parser, Payload, PrimitiveValType, ValidPayload, Validator, |
12 | | WasmFeatures, |
13 | | component_types::{ |
14 | | ComponentAnyTypeId, ComponentDefinedType, ComponentEntityType, ComponentFuncType, |
15 | | ComponentItem, ComponentType, ComponentValType, |
16 | | }, |
17 | | names::{ComponentName, ComponentNameKind}, |
18 | | types, |
19 | | types::Types, |
20 | | }; |
21 | | |
22 | | /// Represents information about a decoded WebAssembly component. |
23 | | struct ComponentInfo { |
24 | | /// Wasmparser-defined type information learned after a component is fully |
25 | | /// validated. |
26 | | types: types::Types, |
27 | | /// List of all imports and exports from this component. |
28 | | externs: Vec<(String, Extern)>, |
29 | | /// Decoded package metadata |
30 | | package_metadata: Option<PackageMetadata>, |
31 | | } |
32 | | |
33 | | enum Extern { |
34 | | Import(ComponentItem), |
35 | | Export(ComponentItem), |
36 | | } |
37 | | |
38 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
39 | | enum WitEncodingVersion { |
40 | | V1, |
41 | | V2, |
42 | | } |
43 | | |
44 | | impl ComponentInfo { |
45 | | /// Creates a new component info by parsing the given WebAssembly component bytes. |
46 | 11.9k | fn from_reader(mut reader: impl Read) -> Result<Self> { |
47 | 11.9k | let mut validator = Validator::new_with_features(WasmFeatures::all()); |
48 | 11.9k | let mut externs = Vec::new(); |
49 | 11.9k | let mut depth = 1; |
50 | 11.9k | let mut types = None; |
51 | 11.9k | let mut _package_metadata = None; |
52 | 11.9k | let mut cur = Parser::new(0); |
53 | 11.9k | let mut eof = false; |
54 | 11.9k | let mut stack = Vec::new(); |
55 | 11.9k | let mut buffer = Vec::new(); |
56 | | |
57 | | loop { |
58 | 1.52M | let chunk = cur.parse(&buffer, eof)?; |
59 | 1.52M | let (payload, consumed) = match chunk { |
60 | 1.11M | Chunk::NeedMoreData(hint) => { |
61 | 1.11M | assert!(!eof); // otherwise an error would be returned |
62 | | |
63 | | // Use the hint to preallocate more space, then read |
64 | | // some more data into our buffer. |
65 | | // |
66 | | // Note that the buffer management here is not ideal, |
67 | | // but it's compact enough to fit in an example! |
68 | 1.11M | let len = buffer.len(); |
69 | 1.11M | buffer.extend((0..hint).map(|_| 0u8)); |
70 | 1.11M | let n = reader.read(&mut buffer[len..])?; |
71 | 1.11M | buffer.truncate(len + n); |
72 | 1.11M | eof = n == 0; |
73 | 1.11M | continue; |
74 | | } |
75 | | |
76 | 417k | Chunk::Parsed { consumed, payload } => (payload, consumed), |
77 | | }; |
78 | 417k | match validator.payload(&payload)? { |
79 | 334k | ValidPayload::Ok => {} |
80 | 19.5k | ValidPayload::Parser(_) => depth += 1, |
81 | 31.4k | ValidPayload::End(t) => { |
82 | 31.4k | depth -= 1; |
83 | 31.4k | if depth == 0 { |
84 | 11.9k | types = Some(t); |
85 | 19.5k | } |
86 | | } |
87 | 32.5k | ValidPayload::Func(..) => {} |
88 | | } |
89 | | |
90 | 10.5k | match payload { |
91 | 10.5k | Payload::ComponentImportSection(s) if depth == 1 => { |
92 | 6.37k | for import in s { |
93 | 6.37k | let import = import?; |
94 | 6.37k | let ty = validator |
95 | 6.37k | .types(0) |
96 | 6.37k | .unwrap() |
97 | 6.37k | .component_item_for_import(import.name.name) |
98 | 6.37k | .unwrap(); |
99 | 6.37k | externs.push((import.name.name.to_string(), Extern::Import(ty.clone()))); |
100 | | } |
101 | | } |
102 | 61.6k | Payload::ComponentExportSection(s) if depth == 1 => { |
103 | 37.0k | for export in s { |
104 | 37.0k | let export = export?; |
105 | 37.0k | let ty = validator |
106 | 37.0k | .types(0) |
107 | 37.0k | .unwrap() |
108 | 37.0k | .component_item_for_export(export.name.name) |
109 | 37.0k | .unwrap(); |
110 | 37.0k | externs.push((export.name.name.to_string(), Extern::Export(ty.clone()))); |
111 | | } |
112 | | } |
113 | | #[cfg(feature = "serde")] |
114 | 33.3k | Payload::CustomSection(s) if s.name() == PackageMetadata::SECTION_NAME => { |
115 | 5.43k | if _package_metadata.is_some() { |
116 | 0 | bail!("multiple {:?} sections", PackageMetadata::SECTION_NAME); |
117 | 5.43k | } |
118 | 5.43k | _package_metadata = Some(PackageMetadata::decode(s.data())?); |
119 | | } |
120 | 15.9k | Payload::ModuleSection { parser, .. } |
121 | 19.5k | | Payload::ComponentSection { parser, .. } => { |
122 | 19.5k | stack.push(cur.clone()); |
123 | 19.5k | cur = parser.clone(); |
124 | 19.5k | } |
125 | | Payload::End(_) => { |
126 | 31.4k | if let Some(parent_parser) = stack.pop() { |
127 | 19.5k | cur = parent_parser.clone(); |
128 | 19.5k | } else { |
129 | 11.9k | break; |
130 | | } |
131 | | } |
132 | 318k | _ => {} |
133 | | } |
134 | | |
135 | | // once we're done processing the payload we can forget the |
136 | | // original. |
137 | 405k | buffer.drain(..consumed); |
138 | | } |
139 | | |
140 | 11.9k | Ok(Self { |
141 | 11.9k | types: types.unwrap(), |
142 | 11.9k | externs, |
143 | 11.9k | package_metadata: _package_metadata, |
144 | 11.9k | }) |
145 | 11.9k | } |
146 | | |
147 | 18.5k | fn is_wit_package(&self) -> Option<WitEncodingVersion> { |
148 | | // all wit package exports must be component types, and there must be at |
149 | | // least one |
150 | 18.5k | if self.externs.is_empty() { |
151 | 6.55k | return None; |
152 | 11.9k | } |
153 | | |
154 | 39.4k | if !self.externs.iter().all(|(_, item)| { |
155 | 39.4k | let export = match item { |
156 | 34.5k | Extern::Export(e) => e, |
157 | 4.92k | _ => return false, |
158 | | }; |
159 | 34.5k | match export.ty { |
160 | 32.9k | ComponentEntityType::Type { created, .. } => { |
161 | 32.9k | matches!(created, ComponentAnyTypeId::Component(_)) |
162 | | } |
163 | 1.59k | _ => false, |
164 | | } |
165 | 39.4k | }) { |
166 | 6.51k | return None; |
167 | 5.43k | } |
168 | | |
169 | | // The distinction between v1 and v2 encoding formats is the structure of the export |
170 | | // strings for each component. The v1 format uses "<namespace>:<package>/wit" as the name |
171 | | // for the top-level exports, while the v2 format uses the unqualified name of the encoded |
172 | | // entity. |
173 | 5.43k | match ComponentName::new(&self.externs[0].0, 0).ok()?.kind() { |
174 | 0 | ComponentNameKind::Interface(name) if name.interface().as_str() == "wit" => { |
175 | 0 | Some(WitEncodingVersion::V1) |
176 | | } |
177 | 5.43k | ComponentNameKind::Label(_) => Some(WitEncodingVersion::V2), |
178 | 0 | _ => None, |
179 | | } |
180 | 18.5k | } |
181 | | |
182 | 0 | fn decode_wit_v1_package(&self) -> Result<(Resolve, PackageId)> { |
183 | 0 | let mut decoder = WitPackageDecoder::new(&self.types); |
184 | | |
185 | 0 | let mut pkg = None; |
186 | 0 | for (name, item) in self.externs.iter() { |
187 | 0 | let export = match item { |
188 | 0 | Extern::Export(e) => e, |
189 | 0 | _ => unreachable!(), |
190 | | }; |
191 | 0 | if pkg.is_some() { |
192 | 0 | bail!("more than one top-level exported component type found"); |
193 | 0 | } |
194 | 0 | let name = ComponentName::new(name, 0).unwrap(); |
195 | 0 | pkg = Some( |
196 | 0 | decoder |
197 | 0 | .decode_v1_package(&name, export) |
198 | 0 | .with_context(|| format!("failed to decode document `{name}`"))?, |
199 | | ); |
200 | | } |
201 | | |
202 | 0 | let pkg = pkg.ok_or_else(|| anyhow!("no exported component type found"))?; |
203 | 0 | let (mut resolve, package) = decoder.finish(pkg); |
204 | 0 | if let Some(package_metadata) = &self.package_metadata { |
205 | 0 | package_metadata.inject(&mut resolve, package)?; |
206 | 0 | } |
207 | 0 | Ok((resolve, package)) |
208 | 0 | } |
209 | | |
210 | 5.43k | fn decode_wit_v2_package(&self) -> Result<(Resolve, PackageId)> { |
211 | 5.43k | let mut decoder = WitPackageDecoder::new(&self.types); |
212 | | |
213 | 5.43k | let mut pkg_name = None; |
214 | | |
215 | 5.43k | let mut interfaces = IndexMap::default(); |
216 | 5.43k | let mut worlds = IndexMap::default(); |
217 | 5.43k | let mut fields = PackageFields { |
218 | 5.43k | interfaces: &mut interfaces, |
219 | 5.43k | worlds: &mut worlds, |
220 | 5.43k | }; |
221 | | |
222 | 32.9k | for (_, item) in self.externs.iter() { |
223 | 32.9k | let export = match item { |
224 | 32.9k | Extern::Export(e) => e, |
225 | 0 | _ => unreachable!(), |
226 | | }; |
227 | 32.9k | let component = match export.ty { |
228 | | ComponentEntityType::Type { |
229 | 32.9k | created: ComponentAnyTypeId::Component(id), |
230 | | .. |
231 | 32.9k | } => &self.types[id], |
232 | 0 | _ => unreachable!(), |
233 | | }; |
234 | | |
235 | | // The single export of this component will determine if it's a world or an interface: |
236 | | // worlds export a component, while interfaces export an instance. |
237 | 32.9k | if component.exports.len() != 1 { |
238 | 0 | bail!( |
239 | | "Expected a single export, but found {} instead", |
240 | 0 | component.exports.len() |
241 | | ); |
242 | 32.9k | } |
243 | | |
244 | 32.9k | let name = component.exports.keys().nth(0).unwrap(); |
245 | | |
246 | 32.9k | let item = &component.exports[name]; |
247 | 32.9k | let name = match item.ty { |
248 | | ComponentEntityType::Component(_) => { |
249 | 7.42k | let package_name = decoder.decode_world(name.as_str(), item, &mut fields)?; |
250 | 7.42k | package_name |
251 | | } |
252 | | ComponentEntityType::Instance(_) => { |
253 | 25.5k | let package_name = decoder.decode_interface( |
254 | 25.5k | name.as_str(), |
255 | 25.5k | &component.imports, |
256 | 25.5k | item, |
257 | 25.5k | &mut fields, |
258 | 0 | )?; |
259 | 25.5k | package_name |
260 | | } |
261 | 0 | _ => unreachable!(), |
262 | | }; |
263 | | |
264 | 32.9k | if let Some(pkg_name) = pkg_name.as_ref() { |
265 | | // TODO: when we have fully switched to the v2 format, we should switch to parsing |
266 | | // multiple wit documents instead of bailing. |
267 | 27.4k | if pkg_name != &name { |
268 | 0 | bail!("item defined with mismatched package name") |
269 | 27.4k | } |
270 | 5.43k | } else { |
271 | 5.43k | pkg_name.replace(name); |
272 | 5.43k | } |
273 | | } |
274 | | |
275 | 5.43k | let pkg = if let Some(name) = pkg_name { |
276 | 5.43k | Package { |
277 | 5.43k | name, |
278 | 5.43k | docs: Docs::default(), |
279 | 5.43k | interfaces, |
280 | 5.43k | worlds, |
281 | 5.43k | } |
282 | | } else { |
283 | 0 | bail!("no exported component type found"); |
284 | | }; |
285 | | |
286 | 5.43k | let (mut resolve, package) = decoder.finish(pkg); |
287 | 5.43k | if let Some(package_metadata) = &self.package_metadata { |
288 | 5.43k | package_metadata.inject(&mut resolve, package)?; |
289 | 0 | } |
290 | 5.43k | Ok((resolve, package)) |
291 | 5.43k | } |
292 | | |
293 | 6.53k | fn decode_component(&self) -> Result<(Resolve, WorldId)> { |
294 | 6.53k | assert!(self.is_wit_package().is_none()); |
295 | 6.53k | let mut decoder = WitPackageDecoder::new(&self.types); |
296 | | // Note that this name is arbitrarily chosen. We may one day perhaps |
297 | | // want to encode this in the component binary format itself, but for |
298 | | // now it shouldn't be an issue to have a defaulted name here. |
299 | 6.53k | let world_name = "root"; |
300 | 6.53k | let world = decoder.resolve.worlds.alloc(World { |
301 | 6.53k | name: world_name.to_string(), |
302 | 6.53k | docs: Default::default(), |
303 | 6.53k | imports: Default::default(), |
304 | 6.53k | exports: Default::default(), |
305 | 6.53k | package: None, |
306 | 6.53k | includes: Default::default(), |
307 | 6.53k | stability: Default::default(), |
308 | 6.53k | span: Default::default(), |
309 | 6.53k | }); |
310 | 6.53k | let mut package = Package { |
311 | 6.53k | // Similar to `world_name` above this is arbitrarily chosen as it's |
312 | 6.53k | // not otherwise encoded in a binary component. This theoretically |
313 | 6.53k | // shouldn't cause issues, however. |
314 | 6.53k | name: PackageName { |
315 | 6.53k | namespace: "root".to_string(), |
316 | 6.53k | version: None, |
317 | 6.53k | name: "component".to_string(), |
318 | 6.53k | }, |
319 | 6.53k | docs: Default::default(), |
320 | 6.53k | worlds: [(world_name.to_string(), world)].into_iter().collect(), |
321 | 6.53k | interfaces: Default::default(), |
322 | 6.53k | }; |
323 | | |
324 | 6.53k | let mut fields = PackageFields { |
325 | 6.53k | worlds: &mut package.worlds, |
326 | 6.53k | interfaces: &mut package.interfaces, |
327 | 6.53k | }; |
328 | | |
329 | 10.5k | for (name, item) in self.externs.iter() { |
330 | 10.5k | match item { |
331 | 6.37k | Extern::Import(i) => { |
332 | 6.37k | decoder.decode_component_import(name, i, world, &mut fields)? |
333 | | } |
334 | 4.13k | Extern::Export(e) => { |
335 | 4.13k | decoder.decode_component_export(name, e, world, &mut fields)? |
336 | | } |
337 | | } |
338 | | } |
339 | | |
340 | 6.53k | let (mut resolve, pkg) = decoder.finish(package); |
341 | 6.53k | if let Some(package_metadata) = &self.package_metadata { |
342 | 0 | package_metadata.inject(&mut resolve, pkg)?; |
343 | 6.53k | } |
344 | 6.53k | Ok((resolve, world)) |
345 | 6.53k | } |
346 | | } |
347 | | |
348 | | /// Result of the [`decode`] function. |
349 | | pub enum DecodedWasm { |
350 | | /// The input to [`decode`] was one or more binary-encoded WIT package(s). |
351 | | /// |
352 | | /// The full resolve graph is here plus the identifier of the packages that |
353 | | /// were encoded. Note that other packages may be within the resolve if any |
354 | | /// of the main packages refer to other, foreign packages. |
355 | | WitPackage(Resolve, PackageId), |
356 | | |
357 | | /// The input to [`decode`] was a component and its interface is specified |
358 | | /// by the world here. |
359 | | Component(Resolve, WorldId), |
360 | | } |
361 | | |
362 | | impl DecodedWasm { |
363 | | /// Returns the [`Resolve`] for WIT types contained. |
364 | 1.02k | pub fn resolve(&self) -> &Resolve { |
365 | 1.02k | match self { |
366 | 1.02k | DecodedWasm::WitPackage(resolve, _) => resolve, |
367 | 0 | DecodedWasm::Component(resolve, _) => resolve, |
368 | | } |
369 | 1.02k | } |
370 | | |
371 | | /// Returns the main packages of what was decoded. |
372 | 0 | pub fn package(&self) -> PackageId { |
373 | 0 | match self { |
374 | 0 | DecodedWasm::WitPackage(_, id) => *id, |
375 | 0 | DecodedWasm::Component(resolve, world) => resolve.worlds[*world].package.unwrap(), |
376 | | } |
377 | 0 | } |
378 | | } |
379 | | |
380 | | /// Decode for incremental reading |
381 | 11.9k | pub fn decode_reader(reader: impl Read) -> Result<DecodedWasm> { |
382 | 11.9k | let info = ComponentInfo::from_reader(reader)?; |
383 | | |
384 | 11.9k | if let Some(version) = info.is_wit_package() { |
385 | 5.43k | match version { |
386 | | WitEncodingVersion::V1 => { |
387 | 0 | log::debug!("decoding a v1 WIT package encoded as wasm"); |
388 | 0 | let (resolve, pkg) = info.decode_wit_v1_package()?; |
389 | 0 | Ok(DecodedWasm::WitPackage(resolve, pkg)) |
390 | | } |
391 | | WitEncodingVersion::V2 => { |
392 | 5.43k | log::debug!("decoding a v2 WIT package encoded as wasm"); |
393 | 5.43k | let (resolve, pkg) = info.decode_wit_v2_package()?; |
394 | 5.43k | Ok(DecodedWasm::WitPackage(resolve, pkg)) |
395 | | } |
396 | | } |
397 | | } else { |
398 | 6.53k | log::debug!("inferring the WIT of a concrete component"); |
399 | 6.53k | let (resolve, world) = info.decode_component()?; |
400 | 6.53k | Ok(DecodedWasm::Component(resolve, world)) |
401 | | } |
402 | 11.9k | } |
403 | | |
404 | | /// Decodes an in-memory WebAssembly binary into a WIT [`Resolve`] and |
405 | | /// associated metadata. |
406 | | /// |
407 | | /// The WebAssembly binary provided here can either be a |
408 | | /// WIT-package-encoded-as-binary or an actual component itself. A [`Resolve`] |
409 | | /// is always created and the return value indicates which was detected. |
410 | 11.9k | pub fn decode(bytes: &[u8]) -> Result<DecodedWasm> { |
411 | 11.9k | decode_reader(bytes) |
412 | 11.9k | } |
413 | | |
414 | | /// Decodes the single component type `world` specified as a WIT world. |
415 | | /// |
416 | | /// The `world` should be an exported component type. The `world` must have been |
417 | | /// previously created via `encode_world` meaning that it is a component that |
418 | | /// itself imports nothing and exports a single component, and the single |
419 | | /// component export represents the world. The name of the export is also the |
420 | | /// name of the package/world/etc. |
421 | 3.26k | pub fn decode_world(wasm: &[u8]) -> Result<(Resolve, WorldId)> { |
422 | 3.26k | let mut validator = Validator::new_with_features(WasmFeatures::all()); |
423 | 3.26k | let mut exports = Vec::new(); |
424 | 3.26k | let mut depth = 1; |
425 | 3.26k | let mut types = None; |
426 | | |
427 | 19.6k | for payload in Parser::new(0).parse_all(wasm) { |
428 | 19.6k | let payload = payload?; |
429 | | |
430 | 19.6k | match validator.payload(&payload)? { |
431 | 16.3k | ValidPayload::Ok => {} |
432 | 0 | ValidPayload::Parser(_) => depth += 1, |
433 | 3.26k | ValidPayload::End(t) => { |
434 | 3.26k | depth -= 1; |
435 | 3.26k | if depth == 0 { |
436 | 3.26k | types = Some(t); |
437 | 3.26k | } |
438 | | } |
439 | 0 | ValidPayload::Func(..) => {} |
440 | | } |
441 | | |
442 | 3.26k | match payload { |
443 | 3.26k | Payload::ComponentExportSection(s) if depth == 1 => { |
444 | 3.26k | for export in s { |
445 | 3.26k | exports.push(export?); |
446 | | } |
447 | | } |
448 | 16.3k | _ => {} |
449 | | } |
450 | | } |
451 | | |
452 | 3.26k | if exports.len() != 1 { |
453 | 0 | bail!("expected one export in component"); |
454 | 3.26k | } |
455 | 3.26k | if exports[0].kind != ComponentExternalKind::Type { |
456 | 0 | bail!("expected an export of a type"); |
457 | 3.26k | } |
458 | 3.26k | if exports[0].ty.is_some() { |
459 | 0 | bail!("expected an un-ascribed exported type"); |
460 | 3.26k | } |
461 | 3.26k | let types = types.as_ref().unwrap(); |
462 | 3.26k | let world = match types.as_ref().component_any_type_at(exports[0].index) { |
463 | 3.26k | ComponentAnyTypeId::Component(c) => c, |
464 | 0 | _ => bail!("expected an exported component type"), |
465 | | }; |
466 | | |
467 | 3.26k | let mut decoder = WitPackageDecoder::new(types); |
468 | 3.26k | let mut interfaces = IndexMap::default(); |
469 | 3.26k | let mut worlds = IndexMap::default(); |
470 | 3.26k | let ty = &types[world]; |
471 | 3.26k | assert_eq!(ty.imports.len(), 0); |
472 | 3.26k | assert_eq!(ty.exports.len(), 1); |
473 | 3.26k | let name = ty.exports.keys().nth(0).unwrap(); |
474 | 3.26k | let name = decoder.decode_world( |
475 | 3.26k | name, |
476 | 3.26k | &ty.exports[0], |
477 | 3.26k | &mut PackageFields { |
478 | 3.26k | interfaces: &mut interfaces, |
479 | 3.26k | worlds: &mut worlds, |
480 | 3.26k | }, |
481 | 0 | )?; |
482 | 3.26k | let (resolve, pkg) = decoder.finish(Package { |
483 | 3.26k | name, |
484 | 3.26k | interfaces, |
485 | 3.26k | worlds, |
486 | 3.26k | docs: Default::default(), |
487 | 3.26k | }); |
488 | | // The package decoded here should only have a single world so extract that |
489 | | // here to return. |
490 | 3.26k | let world = *resolve.packages[pkg].worlds.iter().next().unwrap().1; |
491 | 3.26k | Ok((resolve, world)) |
492 | 3.26k | } |
493 | | |
494 | | struct PackageFields<'a> { |
495 | | interfaces: &'a mut IndexMap<String, InterfaceId>, |
496 | | worlds: &'a mut IndexMap<String, WorldId>, |
497 | | } |
498 | | |
499 | | struct WitPackageDecoder<'a> { |
500 | | resolve: Resolve, |
501 | | types: &'a Types, |
502 | | foreign_packages: IndexMap<String, Package>, |
503 | | iface_to_package_index: HashMap<InterfaceId, usize>, |
504 | | named_interfaces: HashMap<String, InterfaceId>, |
505 | | |
506 | | /// A map which tracks named resources to what their corresponding `TypeId` |
507 | | /// is. This first layer of key in this map is the owner scope of a |
508 | | /// resource, more-or-less the `world` or `interface` that it's defined |
509 | | /// within. The second layer of this map is keyed by name of the resource |
510 | | /// and points to the actual ID of the resource. |
511 | | /// |
512 | | /// This map is populated in `register_type_export`. |
513 | | resources: HashMap<TypeOwner, HashMap<String, TypeId>>, |
514 | | |
515 | | /// A map from a type id to what it's been translated to. |
516 | | type_map: HashMap<ComponentAnyTypeId, TypeId>, |
517 | | } |
518 | | |
519 | | impl WitPackageDecoder<'_> { |
520 | 15.2k | fn new<'a>(types: &'a Types) -> WitPackageDecoder<'a> { |
521 | 15.2k | WitPackageDecoder { |
522 | 15.2k | resolve: Resolve::default(), |
523 | 15.2k | types, |
524 | 15.2k | type_map: HashMap::new(), |
525 | 15.2k | foreign_packages: Default::default(), |
526 | 15.2k | iface_to_package_index: Default::default(), |
527 | 15.2k | named_interfaces: Default::default(), |
528 | 15.2k | resources: Default::default(), |
529 | 15.2k | } |
530 | 15.2k | } |
531 | | |
532 | 0 | fn decode_v1_package(&mut self, name: &ComponentName, item: &ComponentItem) -> Result<Package> { |
533 | 0 | let ty = match item.ty { |
534 | | ComponentEntityType::Type { |
535 | 0 | created: ComponentAnyTypeId::Component(id), |
536 | | .. |
537 | 0 | } => &self.types[id], |
538 | 0 | _ => unreachable!(), |
539 | | }; |
540 | | |
541 | | // Process all imports for this package first, where imports are |
542 | | // importing from remote packages. |
543 | 0 | for (name, item) in ty.imports.iter() { |
544 | 0 | self.register_import(name, item) |
545 | 0 | .with_context(|| format!("failed to process import `{name}`"))?; |
546 | | } |
547 | | |
548 | 0 | let mut package = Package { |
549 | | // The name encoded for packages must be of the form `foo:bar/wit` |
550 | | // where "wit" is just a placeholder for now. The package name in |
551 | | // this case would be `foo:bar`. |
552 | 0 | name: match name.kind() { |
553 | 0 | ComponentNameKind::Interface(name) if name.interface().as_str() == "wit" => { |
554 | 0 | name.to_package_name(item)? |
555 | | } |
556 | 0 | _ => bail!("package name is not a valid id: {name}"), |
557 | | }, |
558 | 0 | docs: Default::default(), |
559 | 0 | interfaces: Default::default(), |
560 | 0 | worlds: Default::default(), |
561 | | }; |
562 | | |
563 | 0 | let mut fields = PackageFields { |
564 | 0 | interfaces: &mut package.interfaces, |
565 | 0 | worlds: &mut package.worlds, |
566 | 0 | }; |
567 | | |
568 | 0 | for (name, ty) in ty.exports.iter() { |
569 | 0 | match ty.ty { |
570 | | ComponentEntityType::Instance(_) => { |
571 | 0 | self.register_interface(name.as_str(), ty, &mut fields) |
572 | 0 | .with_context(|| format!("failed to process export `{name}`"))?; |
573 | | } |
574 | 0 | ComponentEntityType::Component(idx) => { |
575 | 0 | let ty = &self.types[idx]; |
576 | 0 | self.register_world(name.as_str(), ty, &mut fields) |
577 | 0 | .with_context(|| format!("failed to process export `{name}`"))?; |
578 | | } |
579 | 0 | _ => bail!("component export `{name}` is not an instance or component"), |
580 | | } |
581 | | } |
582 | 0 | Ok(package) |
583 | 0 | } |
584 | | |
585 | 25.5k | fn decode_interface<'a>( |
586 | 25.5k | &mut self, |
587 | 25.5k | name: &str, |
588 | 25.5k | imports: &wasmparser::collections::IndexMap<String, ComponentItem>, |
589 | 25.5k | item: &ComponentItem, |
590 | 25.5k | fields: &mut PackageFields<'a>, |
591 | 25.5k | ) -> Result<PackageName> { |
592 | 25.5k | let component_name = self |
593 | 25.5k | .parse_component_name(name) |
594 | 25.5k | .context("expected world name to have an ID form")?; |
595 | | |
596 | 25.5k | let package = match component_name.kind() { |
597 | 25.5k | ComponentNameKind::Interface(name) => name.to_package_name(item)?, |
598 | 0 | _ => bail!("expected world name to be fully qualified"), |
599 | | }; |
600 | | |
601 | 25.5k | for (name, ty) in imports.iter() { |
602 | 4.37k | self.register_import(name, ty) |
603 | 4.37k | .with_context(|| format!("failed to process import `{name}`"))?; |
604 | | } |
605 | | |
606 | 25.5k | let _ = self.register_interface(name, item, fields)?; |
607 | | |
608 | 25.5k | Ok(package) |
609 | 25.5k | } |
610 | | |
611 | 10.6k | fn decode_world<'a>( |
612 | 10.6k | &mut self, |
613 | 10.6k | name: &str, |
614 | 10.6k | item: &ComponentItem, |
615 | 10.6k | fields: &mut PackageFields<'a>, |
616 | 10.6k | ) -> Result<PackageName> { |
617 | 10.6k | let ty = match item.ty { |
618 | 10.6k | ComponentEntityType::Component(ty) => &self.types[ty], |
619 | 0 | _ => unreachable!(), |
620 | | }; |
621 | 10.6k | let kebab_name = self |
622 | 10.6k | .parse_component_name(name) |
623 | 10.6k | .context("expected world name to have an ID form")?; |
624 | | |
625 | 10.6k | let package = match kebab_name.kind() { |
626 | 10.6k | ComponentNameKind::Interface(name) => name.to_package_name(item)?, |
627 | 0 | _ => bail!("expected world name to be fully qualified"), |
628 | | }; |
629 | | |
630 | 10.6k | let _ = self.register_world(name, ty, fields)?; |
631 | | |
632 | 10.6k | Ok(package) |
633 | 10.6k | } |
634 | | |
635 | 6.37k | fn decode_component_import<'a>( |
636 | 6.37k | &mut self, |
637 | 6.37k | name: &str, |
638 | 6.37k | item: &ComponentItem, |
639 | 6.37k | world: WorldId, |
640 | 6.37k | package: &mut PackageFields<'a>, |
641 | 6.37k | ) -> Result<()> { |
642 | 6.37k | log::debug!("decoding component import `{name}`"); |
643 | 6.37k | let owner = TypeOwner::World(world); |
644 | 6.37k | let (name, item) = match item.ty { |
645 | 934 | ComponentEntityType::Instance(_) => self |
646 | 934 | .decode_world_instance(name, item, package) |
647 | 934 | .with_context(|| format!("failed to decode WIT from import `{name}`"))?, |
648 | 1.69k | ComponentEntityType::Func(i) => { |
649 | 1.69k | let ty = &self.types[i]; |
650 | 1.69k | let func = self |
651 | 1.69k | .convert_function(name, ty, owner) |
652 | 1.69k | .with_context(|| format!("failed to decode function from import `{name}`"))?; |
653 | 1.69k | (WorldKey::Name(name.to_string()), WorldItem::Function(func)) |
654 | | } |
655 | | ComponentEntityType::Type { |
656 | 3.75k | referenced, |
657 | 3.75k | created, |
658 | | } => { |
659 | 3.75k | let id = self |
660 | 3.75k | .register_type_export(name, owner, referenced, created) |
661 | 3.75k | .with_context(|| format!("failed to decode type from export `{name}`"))?; |
662 | 3.75k | ( |
663 | 3.75k | WorldKey::Name(name.to_string()), |
664 | 3.75k | WorldItem::Type { |
665 | 3.75k | id, |
666 | 3.75k | span: Default::default(), |
667 | 3.75k | }, |
668 | 3.75k | ) |
669 | | } |
670 | | // All other imports do not form part of the component's world |
671 | 0 | _ => return Ok(()), |
672 | | }; |
673 | 6.37k | self.resolve.worlds[world].imports.insert(name, item); |
674 | 6.37k | Ok(()) |
675 | 6.37k | } |
676 | | |
677 | 4.13k | fn decode_component_export<'a>( |
678 | 4.13k | &mut self, |
679 | 4.13k | name: &str, |
680 | 4.13k | item: &ComponentItem, |
681 | 4.13k | world: WorldId, |
682 | 4.13k | package: &mut PackageFields<'a>, |
683 | 4.13k | ) -> Result<()> { |
684 | 4.13k | log::debug!("decoding component export `{name}`"); |
685 | 4.13k | let (name, item) = match item.ty { |
686 | 604 | ComponentEntityType::Func(i) => { |
687 | 604 | let ty = &self.types[i]; |
688 | 604 | let func = self |
689 | 604 | .convert_function(name, ty, TypeOwner::World(world)) |
690 | 604 | .with_context(|| format!("failed to decode function from export `{name}`"))?; |
691 | | |
692 | 604 | (WorldKey::Name(name.to_string()), WorldItem::Function(func)) |
693 | | } |
694 | 3.52k | ComponentEntityType::Instance(_) => self |
695 | 3.52k | .decode_world_instance(name, item, package) |
696 | 3.52k | .with_context(|| format!("failed to decode WIT from export `{name}`"))?, |
697 | | _ => { |
698 | 0 | bail!("component export `{name}` was not a function or instance") |
699 | | } |
700 | | }; |
701 | 4.13k | self.resolve.worlds[world].exports.insert(name, item); |
702 | 4.13k | Ok(()) |
703 | 4.13k | } |
704 | | |
705 | | /// Decodes a component instance import/export name into a |
706 | | /// `(WorldKey, WorldItem)` pair. |
707 | | /// |
708 | | /// Handles three name forms: |
709 | | /// - `ns:pkg/iface` — qualified interface name, keyed by `InterfaceId` |
710 | | /// - `plain-name` — unqualified name for an inline or local interface |
711 | | /// - `plain-name (implements "...")` - reference to a preexisting interface |
712 | | /// elsewhere |
713 | 11.6k | fn decode_world_instance<'a>( |
714 | 11.6k | &mut self, |
715 | 11.6k | name: &str, |
716 | 11.6k | item: &ComponentItem, |
717 | 11.6k | package: &mut PackageFields<'a>, |
718 | 11.6k | ) -> Result<(WorldKey, WorldItem)> { |
719 | 11.6k | let (key, id) = match &item.implements { |
720 | 8.27k | Some(i) => { |
721 | 8.27k | let id = self.register_import(i, item)?; |
722 | 8.27k | (WorldKey::Name(name.to_string()), id) |
723 | | } |
724 | 3.42k | None => match self.parse_component_name(name)?.kind() { |
725 | 2.00k | ComponentNameKind::Interface(i) => { |
726 | 2.00k | let id = self.register_import(i.as_str(), item)?; |
727 | 2.00k | (WorldKey::Interface(id), id) |
728 | | } |
729 | 1.42k | _ => self.register_interface(name, item, package)?, |
730 | | }, |
731 | | }; |
732 | 11.6k | Ok(( |
733 | 11.6k | key, |
734 | 11.6k | WorldItem::Interface { |
735 | 11.6k | id, |
736 | 11.6k | stability: Default::default(), |
737 | 11.6k | docs: Default::default(), |
738 | 11.6k | span: Default::default(), |
739 | 11.6k | external_id: item.external_id.clone(), |
740 | 11.6k | }, |
741 | 11.6k | )) |
742 | 11.6k | } |
743 | | |
744 | | /// Registers that the `name` provided is either imported interface from a |
745 | | /// foreign package or referencing a previously defined interface in this |
746 | | /// package. |
747 | | /// |
748 | | /// This function will internally ensure that `name` is well-structured and |
749 | | /// will fill in any information as necessary. For example with a foreign |
750 | | /// dependency the foreign package structure, types, etc, all need to be |
751 | | /// created. For a local dependency it's instead ensured that all the types |
752 | | /// line up with the previous definitions. |
753 | 14.6k | fn register_import(&mut self, name: &str, item: &ComponentItem) -> Result<InterfaceId> { |
754 | 14.6k | let ty = match item.ty { |
755 | 14.6k | ComponentEntityType::Instance(idx) => &self.types[idx], |
756 | 0 | _ => bail!("import `{name}` is not an instance"), |
757 | | }; |
758 | 14.6k | let (is_local, interface) = match self.named_interfaces.get(name) { |
759 | 3.31k | Some(id) => (true, *id), |
760 | 11.3k | None => (false, self.extract_dep_interface(name, item)?), |
761 | | }; |
762 | 14.6k | let owner = TypeOwner::Interface(interface); |
763 | 105k | for (name, ty) in ty.exports.iter() { |
764 | 105k | log::debug!("decoding import instance export `{name}`"); |
765 | 105k | match ty.ty { |
766 | | ComponentEntityType::Type { |
767 | 82.7k | referenced, |
768 | 82.7k | created, |
769 | | } => { |
770 | 82.7k | match self.resolve.interfaces[interface] |
771 | 82.7k | .types |
772 | 82.7k | .get(name.as_str()) |
773 | 82.7k | .copied() |
774 | | { |
775 | | // If this name is already defined as a type in the |
776 | | // specified interface then that's ok. For package-local |
777 | | // interfaces that's expected since the interface was |
778 | | // fully defined. For remote interfaces it means we're |
779 | | // using something that was already used elsewhere. In |
780 | | // both cases continue along. |
781 | | // |
782 | | // Notably for the remotely defined case this will also |
783 | | // walk over the structure of the type and register |
784 | | // internal wasmparser ids with wit-parser ids. This is |
785 | | // necessary to ensure that anonymous types like |
786 | | // `list<u8>` defined in original definitions are |
787 | | // unified with anonymous types when duplicated inside |
788 | | // of worlds. Overall this prevents, for example, extra |
789 | | // `list<u8>` types from popping up when decoding. This |
790 | | // is not strictly necessary but assists with |
791 | | // roundtripping assertions during fuzzing. |
792 | 68.3k | Some(id) => { |
793 | 68.3k | log::debug!("type already exist"); |
794 | 68.3k | match referenced { |
795 | 67.0k | ComponentAnyTypeId::Defined(ty) => { |
796 | 67.0k | self.register_defined(id, &self.types[ty])?; |
797 | | } |
798 | 1.34k | ComponentAnyTypeId::Resource(_) => {} |
799 | 0 | _ => unreachable!(), |
800 | | } |
801 | 68.3k | let prev = self.type_map.insert(created, id); |
802 | 68.3k | assert!(prev.is_none()); |
803 | | } |
804 | | |
805 | | // If the name is not defined, however, then there's two |
806 | | // possibilities: |
807 | | // |
808 | | // * For package-local interfaces this is an error |
809 | | // because the package-local interface defined |
810 | | // everything already and this is referencing |
811 | | // something that isn't defined. |
812 | | // |
813 | | // * For remote interfaces they're never fully declared |
814 | | // so it's lazily filled in here. This means that the |
815 | | // view of remote interfaces ends up being the minimal |
816 | | // slice needed for this resolve, which is what's |
817 | | // intended. |
818 | | None => { |
819 | 14.4k | if is_local { |
820 | 0 | bail!("instance type export `{name}` not defined in interface"); |
821 | 14.4k | } |
822 | 14.4k | let id = self.register_type_export( |
823 | 14.4k | name.as_str(), |
824 | 14.4k | owner, |
825 | 14.4k | referenced, |
826 | 14.4k | created, |
827 | 0 | )?; |
828 | 14.4k | let prev = self.resolve.interfaces[interface] |
829 | 14.4k | .types |
830 | 14.4k | .insert(name.to_string(), id); |
831 | 14.4k | assert!(prev.is_none()); |
832 | | } |
833 | | } |
834 | | } |
835 | | |
836 | | // This has similar logic to types above where we lazily fill in |
837 | | // functions for remote dependencies and otherwise assert |
838 | | // they're already defined for local dependencies. |
839 | 22.9k | ComponentEntityType::Func(ty) => { |
840 | 22.9k | let def = &self.types[ty]; |
841 | 22.9k | if self.resolve.interfaces[interface] |
842 | 22.9k | .functions |
843 | 22.9k | .contains_key(name.as_str()) |
844 | | { |
845 | | // TODO: should ideally verify that function signatures |
846 | | // match. |
847 | 16.7k | continue; |
848 | 6.24k | } |
849 | 6.24k | if is_local { |
850 | 0 | bail!("instance function export `{name}` not defined in interface"); |
851 | 6.24k | } |
852 | 6.24k | let func = self.convert_function(name.as_str(), def, owner)?; |
853 | 6.24k | let prev = self.resolve.interfaces[interface] |
854 | 6.24k | .functions |
855 | 6.24k | .insert(name.to_string(), func); |
856 | 6.24k | assert!(prev.is_none()); |
857 | | } |
858 | | |
859 | 0 | _ => bail!("instance type export `{name}` is not a type"), |
860 | | } |
861 | | } |
862 | | |
863 | 14.6k | Ok(interface) |
864 | 14.6k | } |
865 | | |
866 | 37.5k | fn find_alias(&self, id: ComponentAnyTypeId) -> Option<TypeId> { |
867 | | // Consult `type_map` for `referenced` or anything in its |
868 | | // chain of aliases to determine what it maps to. This may |
869 | | // bottom out in `None` in the case that this type is |
870 | | // just now being defined, but this should otherwise follow |
871 | | // chains of aliases to determine what exactly this was a |
872 | | // `use` of if it exists. |
873 | 37.5k | let mut prev = None; |
874 | 37.5k | let mut cur = id; |
875 | 48.9k | while prev.is_none() { |
876 | 37.5k | prev = self.type_map.get(&cur).copied(); |
877 | 37.5k | cur = match self.types.as_ref().peel_alias(cur) { |
878 | 11.4k | Some(next) => next, |
879 | 26.0k | None => break, |
880 | | }; |
881 | | } |
882 | 37.5k | prev |
883 | 37.5k | } |
884 | | |
885 | | /// This will parse the `name_string` as a component model ID string and |
886 | | /// ensure that there's an `InterfaceId` corresponding to its components. |
887 | 11.3k | fn extract_dep_interface( |
888 | 11.3k | &mut self, |
889 | 11.3k | name_string: &str, |
890 | 11.3k | item: &ComponentItem, |
891 | 11.3k | ) -> Result<InterfaceId> { |
892 | 11.3k | let name = ComponentName::new(name_string, 0).unwrap(); |
893 | 11.3k | let name = match name.kind() { |
894 | 11.3k | ComponentNameKind::Interface(name) => name, |
895 | 0 | _ => bail!("package name is not a valid id: {name_string}"), |
896 | | }; |
897 | 11.3k | let package_name = name.to_package_name(item)?; |
898 | | // Lazily create a `Package` as necessary, along with the interface. |
899 | 11.3k | let package = self |
900 | 11.3k | .foreign_packages |
901 | 11.3k | .entry(package_name.to_string()) |
902 | 11.3k | .or_insert_with(|| Package { |
903 | 3.02k | name: package_name.clone(), |
904 | 3.02k | docs: Default::default(), |
905 | 3.02k | interfaces: Default::default(), |
906 | 3.02k | worlds: Default::default(), |
907 | 3.02k | }); |
908 | 11.3k | let interface = *package |
909 | 11.3k | .interfaces |
910 | 11.3k | .entry(name.interface().to_string()) |
911 | 11.3k | .or_insert_with(|| { |
912 | 3.58k | self.resolve.interfaces.alloc(Interface { |
913 | 3.58k | name: Some(name.interface().to_string()), |
914 | 3.58k | docs: Default::default(), |
915 | 3.58k | types: IndexMap::default(), |
916 | 3.58k | functions: IndexMap::default(), |
917 | 3.58k | package: None, |
918 | 3.58k | stability: Default::default(), |
919 | 3.58k | span: Default::default(), |
920 | 3.58k | clone_of: None, |
921 | 3.58k | }) |
922 | 3.58k | }); |
923 | | |
924 | | // Record a mapping of which foreign package this interface belongs to |
925 | 11.3k | self.iface_to_package_index.insert( |
926 | 11.3k | interface, |
927 | 11.3k | self.foreign_packages |
928 | 11.3k | .get_full(&package_name.to_string()) |
929 | 11.3k | .unwrap() |
930 | 11.3k | .0, |
931 | | ); |
932 | 11.3k | Ok(interface) |
933 | 11.3k | } |
934 | | |
935 | | /// A general-purpose helper function to translate a component instance |
936 | | /// into a WIT interface. |
937 | | /// |
938 | | /// This is one of the main workhorses of this module. This handles |
939 | | /// interfaces both at the type level, for concrete components, and |
940 | | /// internally within worlds as well. |
941 | | /// |
942 | | /// The `name` provided is the contextual ID or name of the interface. This |
943 | | /// could be a kebab-name in the case of a world import or export or it can |
944 | | /// also be an ID. This is used to guide insertion into various maps. |
945 | | /// |
946 | | /// The `ty` provided is the actual component type being decoded. |
947 | | /// |
948 | | /// The `package` is where to insert the final interface if `name` is an ID |
949 | | /// meaning it's registered as a named standalone item within the package. |
950 | 26.9k | fn register_interface<'a>( |
951 | 26.9k | &mut self, |
952 | 26.9k | name: &str, |
953 | 26.9k | item: &ComponentItem, |
954 | 26.9k | package: &mut PackageFields<'a>, |
955 | 26.9k | ) -> Result<(WorldKey, InterfaceId)> { |
956 | 26.9k | let ty = match item.ty { |
957 | 26.9k | ComponentEntityType::Instance(i) => &self.types[i], |
958 | 0 | _ => unreachable!(), |
959 | | }; |
960 | | // If this interface's name is already known then that means this is an |
961 | | // interface that's both imported and exported. Use `register_import` |
962 | | // to draw connections between types and this interface's types. |
963 | 26.9k | if self.named_interfaces.contains_key(name) { |
964 | 0 | let id = self.register_import(name, item)?; |
965 | 0 | return Ok((WorldKey::Interface(id), id)); |
966 | 26.9k | } |
967 | | |
968 | | // If this is a bare kebab-name for an interface then the interface's |
969 | | // listed name is `None` and the name goes out through the key. |
970 | | // Otherwise this name is extracted from `name` interpreted as an ID. |
971 | 26.9k | let interface_name = self.extract_interface_name_from_component_name(name)?; |
972 | | |
973 | 26.9k | let mut interface = Interface { |
974 | 26.9k | name: interface_name.clone(), |
975 | 26.9k | docs: Default::default(), |
976 | 26.9k | types: IndexMap::default(), |
977 | 26.9k | functions: IndexMap::default(), |
978 | 26.9k | package: None, |
979 | 26.9k | stability: Default::default(), |
980 | 26.9k | span: Default::default(), |
981 | 26.9k | clone_of: None, |
982 | 26.9k | }; |
983 | | |
984 | 26.9k | let owner = TypeOwner::Interface(self.resolve.interfaces.next_id()); |
985 | 26.9k | for (name, ty) in ty.exports.iter() { |
986 | 23.7k | match ty.ty { |
987 | | ComponentEntityType::Type { |
988 | 13.5k | referenced, |
989 | 13.5k | created, |
990 | | } => { |
991 | 13.5k | let ty = self |
992 | 13.5k | .register_type_export(name.as_str(), owner, referenced, created) |
993 | 13.5k | .with_context(|| format!("failed to register type export '{name}'"))?; |
994 | 13.5k | let prev = interface.types.insert(name.to_string(), ty); |
995 | 13.5k | assert!(prev.is_none()); |
996 | | } |
997 | | |
998 | 10.2k | ComponentEntityType::Func(ty) => { |
999 | 10.2k | let ty = &self.types[ty]; |
1000 | 10.2k | let func = self |
1001 | 10.2k | .convert_function(name.as_str(), ty, owner) |
1002 | 10.2k | .with_context(|| format!("failed to convert function '{name}'"))?; |
1003 | 10.2k | let prev = interface.functions.insert(name.to_string(), func); |
1004 | 10.2k | assert!(prev.is_none()); |
1005 | | } |
1006 | 0 | _ => bail!("instance type export `{name}` is not a type or function"), |
1007 | | }; |
1008 | | } |
1009 | 26.9k | let id = self.resolve.interfaces.alloc(interface); |
1010 | 26.9k | let key = match interface_name { |
1011 | | // If this interface is named then it's part of the package, so |
1012 | | // insert it. Additionally register it in `named_interfaces` so |
1013 | | // further use comes back to this original definition. |
1014 | 25.5k | Some(interface_name) => { |
1015 | 25.5k | let prev = package.interfaces.insert(interface_name, id); |
1016 | 25.5k | assert!(prev.is_none(), "duplicate interface added for {name:?}"); |
1017 | 25.5k | let prev = self.named_interfaces.insert(name.to_string(), id); |
1018 | 25.5k | assert!(prev.is_none()); |
1019 | 25.5k | WorldKey::Interface(id) |
1020 | | } |
1021 | | |
1022 | | // If this interface isn't named then its key is always a |
1023 | | // kebab-name. |
1024 | 1.42k | None => WorldKey::Name(name.to_string()), |
1025 | | }; |
1026 | 26.9k | Ok((key, id)) |
1027 | 26.9k | } |
1028 | | |
1029 | 77.2k | fn parse_component_name(&self, name: &str) -> Result<ComponentName> { |
1030 | 77.2k | ComponentName::new(name, 0) |
1031 | 77.2k | .with_context(|| format!("cannot extract item name from: {name}")) |
1032 | 77.2k | } |
1033 | | |
1034 | 37.6k | fn extract_interface_name_from_component_name(&self, name: &str) -> Result<Option<String>> { |
1035 | 37.6k | let component_name = self.parse_component_name(name)?; |
1036 | 37.6k | match component_name.kind() { |
1037 | 36.2k | ComponentNameKind::Interface(name) => Ok(Some(name.interface().to_string())), |
1038 | 1.42k | ComponentNameKind::Label(_name) => Ok(None), |
1039 | 0 | _ => bail!("cannot extract item name from: {name}"), |
1040 | | } |
1041 | 37.6k | } |
1042 | | |
1043 | 37.5k | fn register_type_export( |
1044 | 37.5k | &mut self, |
1045 | 37.5k | name: &str, |
1046 | 37.5k | owner: TypeOwner, |
1047 | 37.5k | referenced: ComponentAnyTypeId, |
1048 | 37.5k | created: ComponentAnyTypeId, |
1049 | 37.5k | ) -> Result<TypeId> { |
1050 | 37.5k | let kind = match self.find_alias(referenced) { |
1051 | | // If this `TypeId` points to a type which has |
1052 | | // previously been defined, meaning we're aliasing a |
1053 | | // prior definition. |
1054 | 12.1k | Some(prev) => { |
1055 | 12.1k | log::debug!("type export for `{name}` is an alias"); |
1056 | 12.1k | TypeDefKind::Type(Type::Id(prev)) |
1057 | | } |
1058 | | |
1059 | | // ... or this `TypeId`'s source definition has never |
1060 | | // been seen before, so declare the full type. |
1061 | | None => { |
1062 | 25.4k | log::debug!("type export for `{name}` is a new type"); |
1063 | 25.4k | match referenced { |
1064 | 23.3k | ComponentAnyTypeId::Defined(ty) => self |
1065 | 23.3k | .convert_defined(&self.types[ty]) |
1066 | 23.3k | .context("failed to convert unaliased type")?, |
1067 | 2.06k | ComponentAnyTypeId::Resource(_) => TypeDefKind::Resource, |
1068 | 0 | _ => unreachable!(), |
1069 | | } |
1070 | | } |
1071 | | }; |
1072 | 37.5k | let ty = self.resolve.types.alloc(TypeDef { |
1073 | 37.5k | name: Some(name.to_string()), |
1074 | 37.5k | kind, |
1075 | 37.5k | docs: Default::default(), |
1076 | 37.5k | stability: Default::default(), |
1077 | 37.5k | owner, |
1078 | 37.5k | span: Default::default(), |
1079 | 37.5k | }); |
1080 | | |
1081 | | // If this is a resource then doubly-register it in `self.resources` so |
1082 | | // the ID allocated here can be looked up via name later on during |
1083 | | // `convert_function`. |
1084 | 37.5k | if let TypeDefKind::Resource = self.resolve.types[ty].kind { |
1085 | 2.06k | let prev = self |
1086 | 2.06k | .resources |
1087 | 2.06k | .entry(owner) |
1088 | 2.06k | .or_insert(HashMap::new()) |
1089 | 2.06k | .insert(name.to_string(), ty); |
1090 | 2.06k | assert!(prev.is_none()); |
1091 | 35.4k | } |
1092 | | |
1093 | | // A duplicate mapping here comes from a valid component that WIT cannot |
1094 | | // represent (for example an imported resource re-exported under a new |
1095 | | // name), not an internal invariant, so report it instead of asserting. |
1096 | 37.5k | let prev = self.type_map.insert(created, ty); |
1097 | 37.5k | if prev.is_some() { |
1098 | 0 | bail!( |
1099 | | "cannot represent this component in WIT: the type `{name}` appears \ |
1100 | | more than once (for example, when an imported instance is \ |
1101 | | re-exported under a new name)" |
1102 | | ); |
1103 | 37.5k | } |
1104 | 37.5k | Ok(ty) |
1105 | 37.5k | } |
1106 | | |
1107 | 10.6k | fn register_world<'a>( |
1108 | 10.6k | &mut self, |
1109 | 10.6k | name: &str, |
1110 | 10.6k | ty: &ComponentType, |
1111 | 10.6k | package: &mut PackageFields<'a>, |
1112 | 10.6k | ) -> Result<WorldId> { |
1113 | 10.6k | let name = self |
1114 | 10.6k | .extract_interface_name_from_component_name(name)? |
1115 | 10.6k | .context("expected world name to have an ID form")?; |
1116 | 10.6k | let mut world = World { |
1117 | 10.6k | name: name.clone(), |
1118 | 10.6k | docs: Default::default(), |
1119 | 10.6k | imports: Default::default(), |
1120 | 10.6k | exports: Default::default(), |
1121 | 10.6k | includes: Default::default(), |
1122 | 10.6k | package: None, |
1123 | 10.6k | stability: Default::default(), |
1124 | 10.6k | span: Default::default(), |
1125 | 10.6k | }; |
1126 | | |
1127 | 10.6k | let owner = TypeOwner::World(self.resolve.worlds.next_id()); |
1128 | 10.6k | for (name, ty) in ty.imports.iter() { |
1129 | 10.4k | let (name, item) = match ty.ty { |
1130 | | ComponentEntityType::Instance(_) => { |
1131 | 1.93k | self.decode_world_instance(name, ty, package)? |
1132 | | } |
1133 | | ComponentEntityType::Type { |
1134 | 5.80k | created, |
1135 | 5.80k | referenced, |
1136 | | } => { |
1137 | 5.80k | let ty = |
1138 | 5.80k | self.register_type_export(name.as_str(), owner, referenced, created)?; |
1139 | 5.80k | ( |
1140 | 5.80k | WorldKey::Name(name.to_string()), |
1141 | 5.80k | WorldItem::Type { |
1142 | 5.80k | id: ty, |
1143 | 5.80k | span: Default::default(), |
1144 | 5.80k | }, |
1145 | 5.80k | ) |
1146 | | } |
1147 | 2.66k | ComponentEntityType::Func(idx) => { |
1148 | 2.66k | let ty = &self.types[idx]; |
1149 | 2.66k | let func = self.convert_function(name.as_str(), ty, owner)?; |
1150 | 2.66k | (WorldKey::Name(name.to_string()), WorldItem::Function(func)) |
1151 | | } |
1152 | 0 | _ => bail!("component import `{name}` is not an instance, func, or type"), |
1153 | | }; |
1154 | 10.4k | world.imports.insert(name, item); |
1155 | | } |
1156 | | |
1157 | 10.6k | for (name, item) in ty.exports.iter() { |
1158 | 6.22k | let (name, item) = match item.ty { |
1159 | | ComponentEntityType::Instance(_) => { |
1160 | 5.29k | self.decode_world_instance(name, item, package)? |
1161 | | } |
1162 | | |
1163 | 929 | ComponentEntityType::Func(idx) => { |
1164 | 929 | let ty = &self.types[idx]; |
1165 | 929 | let func = self.convert_function(name.as_str(), ty, owner)?; |
1166 | 929 | (WorldKey::Name(name.to_string()), WorldItem::Function(func)) |
1167 | | } |
1168 | | |
1169 | 0 | _ => bail!("component export `{name}` is not an instance or function"), |
1170 | | }; |
1171 | 6.22k | world.exports.insert(name, item); |
1172 | | } |
1173 | 10.6k | let id = self.resolve.worlds.alloc(world); |
1174 | 10.6k | let prev = package.worlds.insert(name, id); |
1175 | 10.6k | assert!(prev.is_none()); |
1176 | 10.6k | Ok(id) |
1177 | 10.6k | } |
1178 | | |
1179 | 22.3k | fn convert_function( |
1180 | 22.3k | &mut self, |
1181 | 22.3k | name: &str, |
1182 | 22.3k | ty: &ComponentFuncType, |
1183 | 22.3k | owner: TypeOwner, |
1184 | 22.3k | ) -> Result<Function> { |
1185 | 22.3k | let name = ComponentName::new(name, 0).unwrap(); |
1186 | 22.3k | let params = ty |
1187 | 22.3k | .params |
1188 | 22.3k | .iter() |
1189 | 49.6k | .map(|(name, ty)| { |
1190 | | Ok(Param { |
1191 | 49.6k | name: name.to_string(), |
1192 | 49.6k | ty: self.convert_valtype(ty)?, |
1193 | 49.6k | span: Default::default(), |
1194 | | }) |
1195 | 49.6k | }) |
1196 | 22.3k | .collect::<Result<Vec<_>>>() |
1197 | 22.3k | .context("failed to convert params")?; |
1198 | 22.3k | let result = match &ty.result { |
1199 | 17.0k | Some(ty) => Some( |
1200 | 17.0k | self.convert_valtype(ty) |
1201 | 17.0k | .context("failed to convert anonymous result type")?, |
1202 | | ), |
1203 | 5.32k | None => None, |
1204 | | }; |
1205 | | Ok(Function { |
1206 | 22.3k | docs: Default::default(), |
1207 | 22.3k | stability: Default::default(), |
1208 | 22.3k | kind: match name.kind() { |
1209 | | ComponentNameKind::Label(_) => { |
1210 | 18.3k | if ty.async_ { |
1211 | 10.2k | FunctionKind::AsyncFreestanding |
1212 | | } else { |
1213 | 8.10k | FunctionKind::Freestanding |
1214 | | } |
1215 | | } |
1216 | 492 | ComponentNameKind::Constructor(resource) => { |
1217 | 492 | FunctionKind::Constructor(self.resources[&owner][resource.as_str()]) |
1218 | | } |
1219 | 2.09k | ComponentNameKind::Method(name) => { |
1220 | 2.09k | if ty.async_ { |
1221 | 1.53k | FunctionKind::AsyncMethod(self.resources[&owner][name.resource().as_str()]) |
1222 | | } else { |
1223 | 555 | FunctionKind::Method(self.resources[&owner][name.resource().as_str()]) |
1224 | | } |
1225 | | } |
1226 | 1.38k | ComponentNameKind::Static(name) => { |
1227 | 1.38k | if ty.async_ { |
1228 | 989 | FunctionKind::AsyncStatic(self.resources[&owner][name.resource().as_str()]) |
1229 | | } else { |
1230 | 398 | FunctionKind::Static(self.resources[&owner][name.resource().as_str()]) |
1231 | | } |
1232 | | } |
1233 | | |
1234 | | // Functions shouldn't have ID-based names at this time. |
1235 | | ComponentNameKind::Interface(_) |
1236 | | | ComponentNameKind::Url(_) |
1237 | | | ComponentNameKind::Hash(_) |
1238 | 0 | | ComponentNameKind::Dependency(_) => unreachable!(), |
1239 | | }, |
1240 | | |
1241 | | // Note that this name includes "name mangling" such as |
1242 | | // `[method]foo.bar` which is intentional. The `FunctionKind` |
1243 | | // discriminant calculated above indicates how to interpret this |
1244 | | // name. |
1245 | 22.3k | name: name.to_string(), |
1246 | 22.3k | params, |
1247 | 22.3k | result, |
1248 | 22.3k | span: Default::default(), |
1249 | | }) |
1250 | 22.3k | } |
1251 | | |
1252 | 260k | fn convert_valtype(&mut self, ty: &ComponentValType) -> Result<Type> { |
1253 | 260k | let id = match ty { |
1254 | 151k | ComponentValType::Primitive(ty) => return Ok(self.convert_primitive(*ty)), |
1255 | 108k | ComponentValType::Type(id) => *id, |
1256 | | }; |
1257 | | |
1258 | | // Don't create duplicate types for anything previously created. |
1259 | 108k | let key: ComponentAnyTypeId = id.into(); |
1260 | 108k | if let Some(ret) = self.type_map.get(&key) { |
1261 | 12.8k | return Ok(Type::Id(*ret)); |
1262 | 95.3k | } |
1263 | | |
1264 | | // Otherwise create a new `TypeDef` without a name since this is an |
1265 | | // anonymous valtype. Note that this is invalid for some types so return |
1266 | | // errors on those types, but eventually the `bail!` here is |
1267 | | // more-or-less unreachable due to expected validation to be added to |
1268 | | // the component model binary format itself. |
1269 | 95.3k | let def = &self.types[id]; |
1270 | 95.3k | let kind = self.convert_defined(def)?; |
1271 | 95.3k | match &kind { |
1272 | | TypeDefKind::Type(_) |
1273 | | | TypeDefKind::List(_) |
1274 | | | TypeDefKind::Map(_, _) |
1275 | | | TypeDefKind::FixedLengthList(..) |
1276 | | | TypeDefKind::Tuple(_) |
1277 | | | TypeDefKind::Option(_) |
1278 | | | TypeDefKind::Result(_) |
1279 | | | TypeDefKind::Handle(_) |
1280 | | | TypeDefKind::Future(_) |
1281 | 95.3k | | TypeDefKind::Stream(_) => {} |
1282 | | |
1283 | | TypeDefKind::Resource |
1284 | | | TypeDefKind::Record(_) |
1285 | | | TypeDefKind::Enum(_) |
1286 | | | TypeDefKind::Variant(_) |
1287 | | | TypeDefKind::Flags(_) => { |
1288 | 0 | bail!("unexpected unnamed type of kind '{}'", kind.as_str()); |
1289 | | } |
1290 | 0 | TypeDefKind::Unknown => unreachable!(), |
1291 | | } |
1292 | 95.3k | let ty = self.resolve.types.alloc(TypeDef { |
1293 | 95.3k | name: None, |
1294 | 95.3k | docs: Default::default(), |
1295 | 95.3k | stability: Default::default(), |
1296 | 95.3k | owner: TypeOwner::None, |
1297 | 95.3k | kind, |
1298 | 95.3k | span: Default::default(), |
1299 | 95.3k | }); |
1300 | 95.3k | let prev = self.type_map.insert(id.into(), ty); |
1301 | 95.3k | assert!(prev.is_none()); |
1302 | 95.3k | Ok(Type::Id(ty)) |
1303 | 260k | } |
1304 | | |
1305 | | /// Converts a wasmparser `ComponentDefinedType`, the definition of a type |
1306 | | /// in the component model, to a WIT `TypeDefKind` to get inserted into the |
1307 | | /// types arena by the caller. |
1308 | 118k | fn convert_defined(&mut self, ty: &ComponentDefinedType) -> Result<TypeDefKind> { |
1309 | 118k | match ty { |
1310 | 1.51k | ComponentDefinedType::Primitive(t) => Ok(TypeDefKind::Type(self.convert_primitive(*t))), |
1311 | | |
1312 | 4.43k | ComponentDefinedType::List(t) => { |
1313 | 4.43k | let t = self.convert_valtype(t)?; |
1314 | 4.43k | Ok(TypeDefKind::List(t)) |
1315 | | } |
1316 | | |
1317 | 0 | ComponentDefinedType::Map(k, v) => { |
1318 | 0 | let k = self.convert_valtype(k)?; |
1319 | 0 | let v = self.convert_valtype(v)?; |
1320 | 0 | Ok(TypeDefKind::Map(k, v)) |
1321 | | } |
1322 | | |
1323 | 2.57k | ComponentDefinedType::FixedLengthList(t, size) => { |
1324 | 2.57k | let t = self.convert_valtype(t)?; |
1325 | 2.57k | Ok(TypeDefKind::FixedLengthList(t, *size)) |
1326 | | } |
1327 | | |
1328 | 24.1k | ComponentDefinedType::Tuple(t) => { |
1329 | 24.1k | let types = t |
1330 | 24.1k | .types |
1331 | 24.1k | .iter() |
1332 | 81.0k | .map(|t| self.convert_valtype(t)) |
1333 | 24.1k | .collect::<Result<_>>()?; |
1334 | 24.1k | Ok(TypeDefKind::Tuple(Tuple { types })) |
1335 | | } |
1336 | | |
1337 | 18.9k | ComponentDefinedType::Option(t) => { |
1338 | 18.9k | let t = self.convert_valtype(t)?; |
1339 | 18.9k | Ok(TypeDefKind::Option(t)) |
1340 | | } |
1341 | | |
1342 | 33.8k | ComponentDefinedType::Result { ok, err } => { |
1343 | 33.8k | let ok = match ok { |
1344 | 30.8k | Some(t) => Some(self.convert_valtype(t)?), |
1345 | 2.92k | None => None, |
1346 | | }; |
1347 | 33.8k | let err = match err { |
1348 | 29.3k | Some(t) => Some(self.convert_valtype(t)?), |
1349 | 4.47k | None => None, |
1350 | | }; |
1351 | 33.8k | Ok(TypeDefKind::Result(Result_ { ok, err })) |
1352 | | } |
1353 | | |
1354 | 2.41k | ComponentDefinedType::Record(r) => { |
1355 | 2.41k | let fields = r |
1356 | 2.41k | .fields |
1357 | 2.41k | .iter() |
1358 | 6.56k | .map(|(name, ty)| { |
1359 | | Ok(Field { |
1360 | 6.56k | name: name.to_string(), |
1361 | 6.56k | ty: self.convert_valtype(ty).with_context(|| { |
1362 | 0 | format!("failed to convert record field '{name}'") |
1363 | 0 | })?, |
1364 | 6.56k | docs: Default::default(), |
1365 | 6.56k | span: Default::default(), |
1366 | | }) |
1367 | 6.56k | }) |
1368 | 2.41k | .collect::<Result<_>>()?; |
1369 | 2.41k | Ok(TypeDefKind::Record(Record { fields })) |
1370 | | } |
1371 | | |
1372 | 3.05k | ComponentDefinedType::Variant(v) => { |
1373 | 3.05k | let cases = v |
1374 | 3.05k | .cases |
1375 | 3.05k | .iter() |
1376 | 10.5k | .map(|(name, case)| { |
1377 | | Ok(Case { |
1378 | 10.5k | name: name.to_string(), |
1379 | 10.5k | ty: match &case.ty { |
1380 | 8.57k | Some(ty) => Some(self.convert_valtype(ty)?), |
1381 | 1.98k | None => None, |
1382 | | }, |
1383 | 10.5k | docs: Default::default(), |
1384 | 10.5k | span: Default::default(), |
1385 | | }) |
1386 | 10.5k | }) |
1387 | 3.05k | .collect::<Result<_>>()?; |
1388 | 3.05k | Ok(TypeDefKind::Variant(Variant { cases })) |
1389 | | } |
1390 | | |
1391 | 1.02k | ComponentDefinedType::Flags(f) => { |
1392 | 1.02k | let flags = f |
1393 | 1.02k | .iter() |
1394 | 1.02k | .map(|name| Flag { |
1395 | 2.75k | name: name.to_string(), |
1396 | 2.75k | docs: Default::default(), |
1397 | 2.75k | span: Default::default(), |
1398 | 2.75k | }) |
1399 | 1.02k | .collect(); |
1400 | 1.02k | Ok(TypeDefKind::Flags(Flags { flags })) |
1401 | | } |
1402 | | |
1403 | 13.9k | ComponentDefinedType::Enum(e) => { |
1404 | 13.9k | let cases = e |
1405 | 13.9k | .iter() |
1406 | 13.9k | .cloned() |
1407 | 13.9k | .map(|name| EnumCase { |
1408 | 85.6k | name: name.into(), |
1409 | 85.6k | docs: Default::default(), |
1410 | 85.6k | span: Default::default(), |
1411 | 85.6k | }) |
1412 | 13.9k | .collect(); |
1413 | 13.9k | Ok(TypeDefKind::Enum(Enum { cases })) |
1414 | | } |
1415 | | |
1416 | 584 | ComponentDefinedType::Own(id) => { |
1417 | 584 | let key: ComponentAnyTypeId = (*id).into(); |
1418 | 584 | let id = self.type_map[&key]; |
1419 | 584 | Ok(TypeDefKind::Handle(Handle::Own(id))) |
1420 | | } |
1421 | | |
1422 | 861 | ComponentDefinedType::Borrow(id) => { |
1423 | 861 | let key: ComponentAnyTypeId = (*id).into(); |
1424 | 861 | let id = self.type_map[&key]; |
1425 | 861 | Ok(TypeDefKind::Handle(Handle::Borrow(id))) |
1426 | | } |
1427 | | |
1428 | 4.93k | ComponentDefinedType::Future(ty) => Ok(TypeDefKind::Future( |
1429 | 4.93k | ty.as_ref().map(|ty| self.convert_valtype(ty)).transpose()?, |
1430 | | )), |
1431 | | |
1432 | 6.54k | ComponentDefinedType::Stream(ty) => Ok(TypeDefKind::Stream( |
1433 | 6.54k | ty.as_ref().map(|ty| self.convert_valtype(ty)).transpose()?, |
1434 | | )), |
1435 | | } |
1436 | 118k | } |
1437 | | |
1438 | 153k | fn convert_primitive(&self, ty: PrimitiveValType) -> Type { |
1439 | 153k | match ty { |
1440 | 4.64k | PrimitiveValType::U8 => Type::U8, |
1441 | 2.04k | PrimitiveValType::S8 => Type::S8, |
1442 | 1.71k | PrimitiveValType::U16 => Type::U16, |
1443 | 1.74k | PrimitiveValType::S16 => Type::S16, |
1444 | 2.54k | PrimitiveValType::U32 => Type::U32, |
1445 | 1.81k | PrimitiveValType::S32 => Type::S32, |
1446 | 1.62k | PrimitiveValType::U64 => Type::U64, |
1447 | 4.60k | PrimitiveValType::S64 => Type::S64, |
1448 | 88.2k | PrimitiveValType::Bool => Type::Bool, |
1449 | 12.2k | PrimitiveValType::Char => Type::Char, |
1450 | 2.36k | PrimitiveValType::String => Type::String, |
1451 | 4.35k | PrimitiveValType::F32 => Type::F32, |
1452 | 5.87k | PrimitiveValType::F64 => Type::F64, |
1453 | 19.4k | PrimitiveValType::ErrorContext => Type::ErrorContext, |
1454 | | } |
1455 | 153k | } |
1456 | | |
1457 | 67.0k | fn register_defined(&mut self, id: TypeId, def: &ComponentDefinedType) -> Result<()> { |
1458 | 67.0k | Registrar { |
1459 | 67.0k | types: &self.types, |
1460 | 67.0k | type_map: &mut self.type_map, |
1461 | 67.0k | resolve: &self.resolve, |
1462 | 67.0k | } |
1463 | 67.0k | .defined(id, def) |
1464 | 67.0k | } |
1465 | | |
1466 | | /// Completes the decoding of this resolve by finalizing all packages into |
1467 | | /// their topological ordering within the returned `Resolve`. |
1468 | | /// |
1469 | | /// Takes the root package as an argument to insert. |
1470 | 15.2k | fn finish(mut self, package: Package) -> (Resolve, PackageId) { |
1471 | | // Build a topological ordering is then calculated by visiting all the |
1472 | | // transitive dependencies of packages. |
1473 | 15.2k | let mut order = IndexSet::default(); |
1474 | 15.2k | for i in 0..self.foreign_packages.len() { |
1475 | 3.02k | self.visit_package(i, &mut order); |
1476 | 3.02k | } |
1477 | | |
1478 | | // Using the topological ordering create a temporary map from |
1479 | | // index-in-`foreign_packages` to index-in-`order` |
1480 | 15.2k | let mut idx_to_pos = vec![0; self.foreign_packages.len()]; |
1481 | 15.2k | for (pos, idx) in order.iter().enumerate() { |
1482 | 3.02k | idx_to_pos[*idx] = pos; |
1483 | 3.02k | } |
1484 | | // .. and then using `idx_to_pos` sort the `foreign_packages` array based |
1485 | | // on the position it's at in the topological ordering |
1486 | 15.2k | let mut deps = mem::take(&mut self.foreign_packages) |
1487 | 15.2k | .into_iter() |
1488 | 15.2k | .enumerate() |
1489 | 15.2k | .collect::<Vec<_>>(); |
1490 | 15.2k | deps.sort_by_key(|(idx, _)| idx_to_pos[*idx]); |
1491 | | |
1492 | | // .. and finally insert the packages, in their final topological |
1493 | | // ordering, into the returned array. |
1494 | 15.2k | for (_idx, (_url, pkg)) in deps { |
1495 | 3.02k | self.insert_package(pkg); |
1496 | 3.02k | } |
1497 | | |
1498 | 15.2k | let id = self.insert_package(package); |
1499 | 17.2k | assert!(self.resolve.worlds.iter().all(|(_, w)| w.package.is_some())); |
1500 | 15.2k | assert!( |
1501 | 15.2k | self.resolve |
1502 | 15.2k | .interfaces |
1503 | 15.2k | .iter() |
1504 | 30.5k | .all(|(_, i)| i.package.is_some()) |
1505 | | ); |
1506 | 15.2k | (self.resolve, id) |
1507 | 15.2k | } |
1508 | | |
1509 | 18.2k | fn insert_package(&mut self, package: Package) -> PackageId { |
1510 | | let Package { |
1511 | 18.2k | name, |
1512 | 18.2k | interfaces, |
1513 | 18.2k | worlds, |
1514 | 18.2k | docs, |
1515 | 18.2k | } = package; |
1516 | | |
1517 | | // Most of the time the `package` being inserted is not already present |
1518 | | // in `self.resolve`, but in the case of the top-level `decode_world` |
1519 | | // function this isn't the case. This shouldn't in general be a problem |
1520 | | // so union-up the packages here while asserting that nothing gets |
1521 | | // replaced by accident which would indicate a bug. |
1522 | 18.2k | let pkg = self |
1523 | 18.2k | .resolve |
1524 | 18.2k | .package_names |
1525 | 18.2k | .get(&name) |
1526 | 18.2k | .copied() |
1527 | 18.2k | .unwrap_or_else(|| { |
1528 | 17.8k | let id = self.resolve.packages.alloc(Package { |
1529 | 17.8k | name: name.clone(), |
1530 | 17.8k | interfaces: Default::default(), |
1531 | 17.8k | worlds: Default::default(), |
1532 | 17.8k | docs, |
1533 | 17.8k | }); |
1534 | 17.8k | let prev = self.resolve.package_names.insert(name, id); |
1535 | 17.8k | assert!(prev.is_none()); |
1536 | 17.8k | id |
1537 | 17.8k | }); |
1538 | | |
1539 | 29.0k | for (name, id) in interfaces { |
1540 | 29.0k | let prev = self.resolve.packages[pkg].interfaces.insert(name, id); |
1541 | 29.0k | assert!(prev.is_none()); |
1542 | 29.0k | self.resolve.interfaces[id].package = Some(pkg); |
1543 | | } |
1544 | | |
1545 | 18.2k | for (name, id) in worlds { |
1546 | 17.2k | let prev = self.resolve.packages[pkg].worlds.insert(name, id); |
1547 | 17.2k | assert!(prev.is_none()); |
1548 | 17.2k | let world = &mut self.resolve.worlds[id]; |
1549 | 17.2k | world.package = Some(pkg); |
1550 | 27.1k | for (name, item) in world.imports.iter().chain(world.exports.iter()) { |
1551 | 27.1k | if let WorldKey::Name(_) = name { |
1552 | 25.1k | if let WorldItem::Interface { id, .. } = item { |
1553 | 9.69k | let iface = &mut self.resolve.interfaces[*id]; |
1554 | 9.69k | if iface.name.is_none() { |
1555 | 1.42k | iface.package = Some(pkg); |
1556 | 8.27k | } |
1557 | 15.4k | } |
1558 | 2.00k | } |
1559 | | } |
1560 | | } |
1561 | | |
1562 | 18.2k | pkg |
1563 | 18.2k | } |
1564 | | |
1565 | 5.80k | fn visit_package(&self, idx: usize, order: &mut IndexSet<usize>) { |
1566 | 5.80k | if order.contains(&idx) { |
1567 | 2.77k | return; |
1568 | 3.02k | } |
1569 | | |
1570 | 3.02k | let (_name, pkg) = self.foreign_packages.get_index(idx).unwrap(); |
1571 | 3.02k | let interfaces = pkg.interfaces.values().copied().chain( |
1572 | 3.02k | pkg.worlds |
1573 | 3.02k | .values() |
1574 | 3.02k | .flat_map(|w| { |
1575 | 0 | let world = &self.resolve.worlds[*w]; |
1576 | 0 | world.imports.values().chain(world.exports.values()) |
1577 | 0 | }) |
1578 | 3.02k | .filter_map(|item| match item { |
1579 | 0 | WorldItem::Interface { id, .. } => Some(*id), |
1580 | 0 | WorldItem::Function(_) | WorldItem::Type { .. } => None, |
1581 | 0 | }), |
1582 | | ); |
1583 | 3.58k | for iface in interfaces { |
1584 | 4.46k | for dep in self.resolve.interface_direct_deps(iface) { |
1585 | 4.46k | let dep_idx = self.iface_to_package_index[&dep]; |
1586 | 4.46k | if dep_idx != idx { |
1587 | 2.77k | self.visit_package(dep_idx, order); |
1588 | 2.77k | } |
1589 | | } |
1590 | | } |
1591 | | |
1592 | 3.02k | assert!(order.insert(idx)); |
1593 | 5.80k | } |
1594 | | } |
1595 | | |
1596 | | /// Helper type to register the structure of a wasm-defined type against a |
1597 | | /// wit-defined type. |
1598 | | struct Registrar<'a> { |
1599 | | types: &'a Types, |
1600 | | type_map: &'a mut HashMap<ComponentAnyTypeId, TypeId>, |
1601 | | resolve: &'a Resolve, |
1602 | | } |
1603 | | |
1604 | | impl Registrar<'_> { |
1605 | | /// Verifies that the wasm structure of `def` matches the wit structure of |
1606 | | /// `id` and recursively registers types. |
1607 | 73.1k | fn defined(&mut self, id: TypeId, def: &ComponentDefinedType) -> Result<()> { |
1608 | 73.1k | match def { |
1609 | 893 | ComponentDefinedType::Primitive(_) => Ok(()), |
1610 | | |
1611 | 320 | ComponentDefinedType::List(t) => { |
1612 | 320 | let ty = match &self.resolve.types[id].kind { |
1613 | 309 | TypeDefKind::List(r) => r, |
1614 | | // Note that all cases below have this match and the general |
1615 | | // idea is that once a type is named or otherwise identified |
1616 | | // here there's no need to recurse. The purpose of this |
1617 | | // registrar is to build connections for anonymous types |
1618 | | // that don't otherwise have a name to ensure that they're |
1619 | | // decoded to reuse the same constructs consistently. For |
1620 | | // that reason once something is named we can bail out. |
1621 | 11 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1622 | 0 | _ => bail!("expected a list"), |
1623 | | }; |
1624 | 309 | self.valtype(t, ty) |
1625 | | } |
1626 | | |
1627 | 0 | ComponentDefinedType::Map(k, v) => { |
1628 | 0 | let (key_ty, value_ty) = match &self.resolve.types[id].kind { |
1629 | 0 | TypeDefKind::Map(k, v) => (k, v), |
1630 | 0 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1631 | 0 | _ => bail!("expected a map"), |
1632 | | }; |
1633 | 0 | self.valtype(k, key_ty)?; |
1634 | 0 | self.valtype(v, value_ty) |
1635 | | } |
1636 | | |
1637 | 34 | ComponentDefinedType::FixedLengthList(t, elements) => { |
1638 | 34 | let ty = match &self.resolve.types[id].kind { |
1639 | 34 | TypeDefKind::FixedLengthList(r, elements2) if elements2 == elements => r, |
1640 | 0 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1641 | 0 | _ => bail!("expected a fixed-length {elements} list"), |
1642 | | }; |
1643 | 34 | self.valtype(t, ty) |
1644 | | } |
1645 | | |
1646 | 2.19k | ComponentDefinedType::Tuple(t) => { |
1647 | 2.19k | let ty = match &self.resolve.types[id].kind { |
1648 | 2.18k | TypeDefKind::Tuple(r) => r, |
1649 | 18 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1650 | 0 | _ => bail!("expected a tuple"), |
1651 | | }; |
1652 | 2.18k | if ty.types.len() != t.types.len() { |
1653 | 0 | bail!("mismatched number of tuple fields"); |
1654 | 2.18k | } |
1655 | 7.38k | for (a, b) in t.types.iter().zip(ty.types.iter()) { |
1656 | 7.38k | self.valtype(a, b)?; |
1657 | | } |
1658 | 2.18k | Ok(()) |
1659 | | } |
1660 | | |
1661 | 801 | ComponentDefinedType::Option(t) => { |
1662 | 801 | let ty = match &self.resolve.types[id].kind { |
1663 | 781 | TypeDefKind::Option(r) => r, |
1664 | 20 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1665 | 0 | _ => bail!("expected an option"), |
1666 | | }; |
1667 | 781 | self.valtype(t, ty) |
1668 | | } |
1669 | | |
1670 | 2.88k | ComponentDefinedType::Result { ok, err } => { |
1671 | 2.88k | let ty = match &self.resolve.types[id].kind { |
1672 | 2.87k | TypeDefKind::Result(r) => r, |
1673 | 9 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1674 | 0 | _ => bail!("expected a result"), |
1675 | | }; |
1676 | 2.87k | match (ok, &ty.ok) { |
1677 | 2.71k | (Some(a), Some(b)) => self.valtype(a, b)?, |
1678 | 165 | (None, None) => {} |
1679 | 0 | _ => bail!("disagreement on result structure"), |
1680 | | } |
1681 | 2.87k | match (err, &ty.err) { |
1682 | 2.53k | (Some(a), Some(b)) => self.valtype(a, b)?, |
1683 | 340 | (None, None) => {} |
1684 | 0 | _ => bail!("disagreement on result structure"), |
1685 | | } |
1686 | 2.87k | Ok(()) |
1687 | | } |
1688 | | |
1689 | 3.57k | ComponentDefinedType::Record(def) => { |
1690 | 3.57k | let ty = match &self.resolve.types[id].kind { |
1691 | 1.01k | TypeDefKind::Record(r) => r, |
1692 | 2.55k | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1693 | 0 | _ => bail!("expected a record"), |
1694 | | }; |
1695 | 1.01k | if def.fields.len() != ty.fields.len() { |
1696 | 0 | bail!("mismatched number of record fields"); |
1697 | 1.01k | } |
1698 | 4.92k | for ((name, ty), field) in def.fields.iter().zip(&ty.fields) { |
1699 | 4.92k | if name.as_str() != field.name { |
1700 | 0 | bail!("mismatched field order"); |
1701 | 4.92k | } |
1702 | 4.92k | self.valtype(ty, &field.ty)?; |
1703 | | } |
1704 | 1.01k | Ok(()) |
1705 | | } |
1706 | | |
1707 | 15.2k | ComponentDefinedType::Variant(def) => { |
1708 | 15.2k | let ty = match &self.resolve.types[id].kind { |
1709 | 2.62k | TypeDefKind::Variant(r) => r, |
1710 | 12.6k | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1711 | 0 | _ => bail!("expected a variant"), |
1712 | | }; |
1713 | 2.62k | if def.cases.len() != ty.cases.len() { |
1714 | 0 | bail!("mismatched number of variant cases"); |
1715 | 2.62k | } |
1716 | 9.16k | for ((name, ty), case) in def.cases.iter().zip(&ty.cases) { |
1717 | 9.16k | if name.as_str() != case.name { |
1718 | 0 | bail!("mismatched case order"); |
1719 | 9.16k | } |
1720 | 9.16k | match (&ty.ty, &case.ty) { |
1721 | 7.52k | (Some(a), Some(b)) => self.valtype(a, b)?, |
1722 | 1.63k | (None, None) => {} |
1723 | 0 | _ => bail!("disagreement on case type"), |
1724 | | } |
1725 | | } |
1726 | 2.62k | Ok(()) |
1727 | | } |
1728 | | |
1729 | 90 | ComponentDefinedType::Future(payload) => { |
1730 | 90 | let ty = match &self.resolve.types[id].kind { |
1731 | 90 | TypeDefKind::Future(p) => p, |
1732 | 0 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1733 | 0 | _ => bail!("expected a future"), |
1734 | | }; |
1735 | 90 | match (payload, ty) { |
1736 | 47 | (Some(a), Some(b)) => self.valtype(a, b), |
1737 | 43 | (None, None) => Ok(()), |
1738 | 0 | _ => bail!("disagreement on future payload"), |
1739 | | } |
1740 | | } |
1741 | | |
1742 | 45 | ComponentDefinedType::Stream(payload) => { |
1743 | 45 | let ty = match &self.resolve.types[id].kind { |
1744 | 45 | TypeDefKind::Stream(p) => p, |
1745 | 0 | TypeDefKind::Type(Type::Id(_)) => return Ok(()), |
1746 | 0 | _ => bail!("expected a stream"), |
1747 | | }; |
1748 | 45 | match (payload, ty) { |
1749 | 45 | (Some(a), Some(b)) => self.valtype(a, b), |
1750 | 0 | (None, None) => Ok(()), |
1751 | 0 | _ => bail!("disagreement on stream payload"), |
1752 | | } |
1753 | | } |
1754 | | |
1755 | | // These have no recursive structure so they can bail out. |
1756 | | ComponentDefinedType::Flags(_) |
1757 | | | ComponentDefinedType::Enum(_) |
1758 | | | ComponentDefinedType::Own(_) |
1759 | 46.9k | | ComponentDefinedType::Borrow(_) => Ok(()), |
1760 | | } |
1761 | 73.1k | } |
1762 | | |
1763 | 26.2k | fn valtype(&mut self, wasm: &ComponentValType, wit: &Type) -> Result<()> { |
1764 | 26.2k | let wasm = match wasm { |
1765 | 6.99k | ComponentValType::Type(wasm) => *wasm, |
1766 | 19.3k | ComponentValType::Primitive(_wasm) => { |
1767 | 19.3k | assert!(!matches!(wit, Type::Id(_))); |
1768 | 19.3k | return Ok(()); |
1769 | | } |
1770 | | }; |
1771 | 6.99k | let wit = match wit { |
1772 | 6.99k | Type::Id(id) => *id, |
1773 | 0 | _ => bail!("expected id-based type"), |
1774 | | }; |
1775 | 6.99k | let prev = match self.type_map.insert(wasm.into(), wit) { |
1776 | 917 | Some(prev) => prev, |
1777 | | None => { |
1778 | 6.07k | let wasm = &self.types[wasm]; |
1779 | 6.07k | return self.defined(wit, wasm); |
1780 | | } |
1781 | | }; |
1782 | | // If `wit` matches `prev` then we've just rediscovered what we already |
1783 | | // knew which is that the `wasm` id maps to the `wit` id. |
1784 | | // |
1785 | | // If, however, `wit` is not equal to `prev` then that's more |
1786 | | // interesting. Consider a component such as: |
1787 | | // |
1788 | | // ```wasm |
1789 | | // (component |
1790 | | // (import (interface "a:b/name") (instance |
1791 | | // (type $l (list string)) |
1792 | | // (type $foo (variant (case "l" $l))) |
1793 | | // (export "foo" (type (eq $foo))) |
1794 | | // )) |
1795 | | // (component $c |
1796 | | // (type $l (list string)) |
1797 | | // (type $bar (variant (case "n" u16) (case "l" $l))) |
1798 | | // (export "bar" (type $bar)) |
1799 | | // (type $foo (variant (case "l" $l))) |
1800 | | // (export "foo" (type $foo)) |
1801 | | // ) |
1802 | | // (instance $i (instantiate $c)) |
1803 | | // (export (interface "a:b/name") (instance $i)) |
1804 | | // ) |
1805 | | // ``` |
1806 | | // |
1807 | | // This roughly corresponds to: |
1808 | | // |
1809 | | // ```wit |
1810 | | // package a:b |
1811 | | // |
1812 | | // interface name { |
1813 | | // variant bar { |
1814 | | // n(u16), |
1815 | | // l(list<string>), |
1816 | | // } |
1817 | | // |
1818 | | // variant foo { |
1819 | | // l(list<string>), |
1820 | | // } |
1821 | | // } |
1822 | | // |
1823 | | // world module { |
1824 | | // import name |
1825 | | // export name |
1826 | | // } |
1827 | | // ``` |
1828 | | // |
1829 | | // In this situation first we'll see the `import` which records type |
1830 | | // information for the `foo` type in `interface name`. Later on the full |
1831 | | // picture of `interface name` becomes apparent with the export of a |
1832 | | // component which has full type information. When walking over this |
1833 | | // first `bar` is seen and its recursive structure. |
1834 | | // |
1835 | | // The problem arises when walking over the `foo` type. In this |
1836 | | // situation the code path we're currently on will be hit because |
1837 | | // there's a preexisting definition of `foo` from the import and it's |
1838 | | // now going to be unified with what we've seen in the export. When |
1839 | | // visiting the `list<string>` case of the `foo` variant this ends up |
1840 | | // being different than the `list<string>` used by the `bar` variant. The |
1841 | | // reason for this is that when visiting `bar` the wasm-defined `(list |
1842 | | // string)` hasn't been seen before so a new type is allocated. Later |
1843 | | // though this same wasm type is unified with the first `(list string)` |
1844 | | // type in the `import`. |
1845 | | // |
1846 | | // All-in-all this ends up meaning that it's possible for `prev` to not |
1847 | | // match `wit`. In this situation it means the decoded WIT interface |
1848 | | // will have duplicate definitions of `list<string>`. This is, |
1849 | | // theoretically, not that big of a problem because the same underlying |
1850 | | // definition is still there and the meaning of the type is the same. |
1851 | | // This can, however, perhaps be a problem for consumers where it's |
1852 | | // assumed that all `list<string>` are equal and there's only one. For |
1853 | | // example a bindings generator for C may assume that `list<string>` |
1854 | | // will only appear once and generate a single name for it, but with two |
1855 | | // different types in play here it may generate two types of the same |
1856 | | // name (or something like that). |
1857 | | // |
1858 | | // For now though this is left for a future refactoring. Fixing this |
1859 | | // issue would require tracking anonymous types during type translation |
1860 | | // so the decoding process for the `bar` export would reuse the |
1861 | | // `list<string>` type created from decoding the `foo` import. That's |
1862 | | // somewhat nontrivial at this time, so it's left for a future |
1863 | | // refactoring. |
1864 | 917 | let _ = prev; |
1865 | 917 | Ok(()) |
1866 | 26.2k | } |
1867 | | } |
1868 | | |
1869 | | pub(crate) trait InterfaceNameExt { |
1870 | | fn to_package_name(&self, item: &ComponentItem) -> Result<PackageName>; |
1871 | | } |
1872 | | |
1873 | | impl InterfaceNameExt for wasmparser::names::InterfaceName<'_> { |
1874 | 47.5k | fn to_package_name(&self, item: &ComponentItem) -> Result<PackageName> { |
1875 | | Ok(PackageName { |
1876 | 47.5k | namespace: self.namespace().to_string(), |
1877 | 47.5k | name: self.package().to_string(), |
1878 | 47.5k | version: self.version(item.version_suffix.as_deref())?, |
1879 | | }) |
1880 | 47.5k | } |
1881 | | } |