Skip to main content

wit_parser/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "std")]
6extern crate std;
7
8use crate::abi::AbiVariant;
9use alloc::format;
10use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12use id_arena::{Arena, Id};
13use semver::Version;
14
15#[cfg(feature = "std")]
16pub type IndexMap<K, V> = indexmap::IndexMap<K, V, std::hash::RandomState>;
17#[cfg(feature = "std")]
18pub type IndexSet<T> = indexmap::IndexSet<T, std::hash::RandomState>;
19#[cfg(not(feature = "std"))]
20pub type IndexMap<K, V> = indexmap::IndexMap<K, V, hashbrown::DefaultHashBuilder>;
21#[cfg(not(feature = "std"))]
22pub type IndexSet<T> = indexmap::IndexSet<T, hashbrown::DefaultHashBuilder>;
23
24#[cfg(feature = "std")]
25pub(crate) use std::collections::{HashMap, HashSet};
26
27#[cfg(not(feature = "std"))]
28pub(crate) use hashbrown::{HashMap, HashSet};
29
30use alloc::borrow::Cow;
31use core::fmt;
32use core::hash::{Hash, Hasher};
33#[cfg(feature = "std")]
34use std::path::Path;
35
36#[cfg(feature = "decoding")]
37pub mod decoding;
38#[cfg(feature = "decoding")]
39mod metadata;
40#[cfg(feature = "decoding")]
41pub use metadata::PackageMetadata;
42
43pub mod abi;
44mod ast;
45pub use ast::error::*;
46pub use ast::lex::Span;
47pub use ast::{ItemName, SourceMap, SpanLocation};
48pub use ast::{ParsedUsePath, parse_use_path};
49mod sizealign;
50pub use sizealign::*;
51mod resolve;
52pub use resolve::error::*;
53pub use resolve::*;
54mod live;
55pub use live::{LiveTypes, TypeIdVisitor};
56
57#[cfg(feature = "serde")]
58use serde_derive::Serialize;
59#[cfg(feature = "serde")]
60mod serde_;
61#[cfg(feature = "serde")]
62use serde_::*;
63
64/// Checks if the given string is a legal identifier in wit.
65pub fn validate_id(s: &str) -> anyhow::Result<()> {
66    ast::validate_id(0, s)?;
67    Ok(())
68}
69
70/// Parses a component model name. [wasmparser::names::ComponentName::new]
71/// cannot be used on its own because any name-related features that are not
72/// yet default would be rejected.
73pub(crate) fn parse_component_name(
74    name: &str,
75) -> wasmparser::Result<wasmparser::names::ComponentName> {
76    wasmparser::names::ComponentName::new_with_features(name, 0, wasmparser::WasmFeatures::all())
77}
78
79/// Renders an [`anyhow::Error`] chain produced by this crate, substituting
80/// snippet-bearing output for any [`ResolveError`] or [`ParseError`] layers.
81///
82/// For each layer in the chain, this calls [`ResolveError::render`] or
83/// [`ParseError::render`] to format typed errors with file/line/column and
84/// a source snippet. Other layers are formatted via their [`fmt::Display`]
85/// impl. Layers are joined with `": "`, matching `format!("{err:#}")`.
86///
87/// `source_map` must be the [`SourceMap`] in which every typed error's spans
88/// are valid; combining typed errors from different source maps in one chain
89/// is unsupported. For errors from [`Resolve`] methods, prefer
90/// [`Resolve::render_error`].
91#[cfg(feature = "std")]
92pub fn render_anyhow_error(err: &anyhow::Error, source_map: &SourceMap) -> String {
93    err.chain()
94        .map(|layer| {
95            if let Some(re) = layer.downcast_ref::<ResolveError>() {
96                re.render(source_map)
97            } else if let Some(pe) = layer.downcast_ref::<ParseError>() {
98                pe.render(source_map)
99            } else {
100                layer.to_string()
101            }
102        })
103        .collect::<Vec<_>>()
104        .join(": ")
105}
106
107pub type WorldId = Id<World>;
108pub type InterfaceId = Id<Interface>;
109pub type TypeId = Id<TypeDef>;
110
111/// Representation of a parsed WIT package which has not resolved external
112/// dependencies yet.
113///
114/// This representation has performed internal resolution of the WIT package
115/// itself, ensuring that all references internally are valid and the WIT was
116/// syntactically valid and such.
117///
118/// The fields of this structure represent a flat list of arrays unioned from
119/// all documents within the WIT package. This means, for example, that all
120/// types from all documents are located in `self.types`. The fields of each
121/// item can help splitting back out into packages/interfaces/etc as necessary.
122///
123/// Note that an `UnresolvedPackage` cannot be queried in general about
124/// information such as size or alignment as that would require resolution of
125/// foreign dependencies. Translations such as to-binary additionally are not
126/// supported on an `UnresolvedPackage` due to the lack of knowledge about the
127/// foreign types. This is intended to be an intermediate state which can be
128/// inspected by embedders, if necessary, before quickly transforming to a
129/// [`Resolve`] to fully work with a WIT package.
130///
131/// After an [`UnresolvedPackage`] is parsed it can be fully resolved with
132/// [`Resolve::push`]. During this operation a dependency map is specified which
133/// will connect the `foreign_deps` field of this structure to packages
134/// previously inserted within the [`Resolve`]. Embedders are responsible for
135/// performing this resolution themselves.
136#[derive(Clone, Debug, PartialEq, Eq)]
137pub struct UnresolvedPackage {
138    /// The namespace, name, and version information for this package.
139    pub name: PackageName,
140
141    /// All worlds from all documents within this package.
142    ///
143    /// Each world lists the document that it is from.
144    pub worlds: Arena<World>,
145
146    /// All interfaces from all documents within this package.
147    ///
148    /// Each interface lists the document that it is from. Interfaces are listed
149    /// in topological order as well so iteration through this arena will only
150    /// reference prior elements already visited when working with recursive
151    /// references.
152    pub interfaces: Arena<Interface>,
153
154    /// All types from all documents within this package.
155    ///
156    /// Each type lists the interface or world that defined it, or nothing if
157    /// it's an anonymous type. Types are listed in this arena in topological
158    /// order to ensure that iteration through this arena will only reference
159    /// other types transitively that are already iterated over.
160    pub types: Arena<TypeDef>,
161
162    /// All foreign dependencies that this package depends on.
163    ///
164    /// These foreign dependencies must be resolved to convert this unresolved
165    /// package into a `Resolve`. The map here is keyed by the name of the
166    /// foreign package that this depends on, and the sub-map is keyed by an
167    /// interface name followed by the identifier within `self.interfaces`. The
168    /// fields of `self.interfaces` describes the required types that are from
169    /// each foreign interface.
170    pub foreign_deps: IndexMap<PackageName, IndexMap<String, (AstItem, Vec<Stability>)>>,
171
172    /// Doc comments for this package.
173    pub docs: Docs,
174
175    #[cfg_attr(not(feature = "std"), allow(dead_code))]
176    package_name_span: Span,
177    unknown_type_spans: Vec<Span>,
178    foreign_dep_spans: Vec<Span>,
179    required_resource_types: Vec<(TypeId, Span)>,
180}
181
182impl UnresolvedPackage {
183    /// Adjusts all spans in this package by adding the given byte offset.
184    ///
185    /// This is used when merging source maps to update spans to point to the
186    /// correct location in the combined source map.
187    pub(crate) fn adjust_spans(&mut self, offset: u32) {
188        // Adjust parallel vec spans
189        self.package_name_span.adjust(offset);
190        for span in &mut self.unknown_type_spans {
191            span.adjust(offset);
192        }
193        for span in &mut self.foreign_dep_spans {
194            span.adjust(offset);
195        }
196        for (_, span) in &mut self.required_resource_types {
197            span.adjust(offset);
198        }
199
200        // Adjust spans on arena items
201        for (_, world) in self.worlds.iter_mut() {
202            world.adjust_spans(offset);
203        }
204        for (_, iface) in self.interfaces.iter_mut() {
205            iface.adjust_spans(offset);
206        }
207        for (_, ty) in self.types.iter_mut() {
208            ty.adjust_spans(offset);
209        }
210    }
211}
212
213/// Tracks a set of packages, all pulled from the same group of WIT source files.
214#[derive(Clone, Debug, PartialEq, Eq)]
215pub struct UnresolvedPackageGroup {
216    /// The "main" package in this package group which was found at the root of
217    /// the WIT files.
218    ///
219    /// Note that this is required to be present in all WIT files.
220    pub main: UnresolvedPackage,
221
222    /// Nested packages found while parsing `main`, if any.
223    pub nested: Vec<UnresolvedPackage>,
224
225    /// A set of processed source files from which these packages have been parsed.
226    pub source_map: SourceMap,
227}
228
229#[derive(Debug, Copy, Clone, PartialEq, Eq)]
230#[cfg_attr(feature = "serde", derive(Serialize))]
231#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
232pub enum AstItem {
233    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
234    Interface(InterfaceId),
235    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
236    World(WorldId),
237}
238
239/// A structure used to keep track of the name of a package, containing optional
240/// information such as a namespace and version information.
241///
242/// This is directly encoded as an "ID" in the binary component representation
243/// with an interfaced tacked on as well.
244#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
245#[cfg_attr(feature = "serde", derive(Serialize))]
246#[cfg_attr(feature = "serde", serde(into = "String"))]
247pub struct PackageName {
248    /// A namespace such as `wasi` in `wasi:foo/bar`
249    pub namespace: String,
250    /// The kebab-name of this package, which is always specified.
251    pub name: String,
252    /// Optional major/minor version information.
253    pub version: Option<Version>,
254}
255
256impl From<PackageName> for String {
257    fn from(name: PackageName) -> String {
258        name.to_string()
259    }
260}
261
262impl PackageName {
263    /// Returns the ID that this package name would assign the `interface` name
264    /// specified.
265    pub fn interface_id(&self, interface: &str) -> String {
266        let mut s = String::new();
267        s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
268        if let Some(version) = &self.version {
269            s.push_str(&format!("@{version}"));
270        }
271        s
272    }
273
274    /// Determines the "semver compatible track" for the given version,
275    /// and its version suffix.
276    ///
277    /// This method implements the logic from the component model where semver
278    /// versions can be compatible with one another. For example versions 1.2.0
279    /// and 1.2.1 would be considered both compatible with one another because
280    /// they're on the same semver compatible track.
281    ///
282    /// This predicate is used during
283    /// [`Resolve::merge_world_imports_based_on_semver`] for example to
284    /// determine whether two imports can be merged together. This is
285    /// additionally used when creating components to match up imports in
286    /// core wasm to imports in worlds.
287    pub fn version_compat_track(version: &Version) -> (Version, Option<String>) {
288        let (_, suffix) = Self::version_compat_track_string(version);
289        let mut version = version.clone();
290        version.build = semver::BuildMetadata::EMPTY;
291        if version.pre.is_empty() {
292            if version.major != 0 {
293                version.minor = 0;
294                version.patch = 0;
295            } else if version.minor != 0 {
296                version.patch = 0;
297            }
298        }
299        (version, suffix)
300    }
301
302    /// Returns the string corresponding to
303    /// [`PackageName::version_compat_track`]. This is done to match the
304    /// component model's expected naming scheme of imports and exports.
305    ///
306    /// See [`wasmparser::names::split_canonical_version`] for more
307    /// information.
308    pub fn version_compat_track_string(version: &Version) -> (String, Option<String>) {
309        let version = version.to_string();
310        let (track, suffix) = wasmparser::names::split_canonical_version(&version)
311            .expect("a `Version` should always display as a valid version");
312        (track.to_string(), suffix.map(|s| s.to_string()))
313    }
314}
315
316impl fmt::Display for PackageName {
317    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
318        write!(f, "{}:{}", self.namespace, self.name)?;
319        if let Some(version) = &self.version {
320            write!(f, "@{version}")?;
321        }
322        Ok(())
323    }
324}
325
326impl UnresolvedPackageGroup {
327    /// Parses the given string as a wit document.
328    ///
329    /// The `path` argument is used for error reporting. The `contents` provided
330    /// are considered to be the contents of `path`. This function does not read
331    /// the filesystem.
332    ///
333    /// On failure the constructed [`SourceMap`] is returned alongside the
334    /// typed [`ParseError`] so the caller can render a snippet via
335    /// [`ParseError::render`] or merge the source map elsewhere.
336    #[cfg(feature = "std")]
337    pub fn parse(
338        path: impl AsRef<Path>,
339        contents: &str,
340    ) -> Result<UnresolvedPackageGroup, (SourceMap, ParseError)> {
341        let mut map = SourceMap::default();
342        map.push(path.as_ref(), contents);
343        map.parse()
344    }
345
346    /// Parses a WIT package from the directory provided.
347    ///
348    /// This method will look at all files under the `path` specified. All
349    /// `*.wit` files are parsed and assumed to be part of the same package
350    /// grouping. This is useful when a WIT package is split across multiple
351    /// files.
352    #[cfg(feature = "std")]
353    pub fn parse_dir(path: impl AsRef<Path>) -> anyhow::Result<UnresolvedPackageGroup> {
354        let mut map = SourceMap::default();
355        map.push_dir(path.as_ref())?;
356        map.parse().map_err(|(map, e)| {
357            let rendered = e.render(&map);
358            anyhow::Error::from(e).context(rendered)
359        })
360    }
361}
362
363#[derive(Debug, Clone, PartialEq, Eq)]
364#[cfg_attr(feature = "serde", derive(Serialize))]
365pub struct World {
366    /// The WIT identifier name of this world.
367    pub name: String,
368
369    /// All imported items into this interface, both worlds and functions.
370    pub imports: IndexMap<WorldKey, WorldItem>,
371
372    /// All exported items from this interface, both worlds and functions.
373    pub exports: IndexMap<WorldKey, WorldItem>,
374
375    /// The package that owns this world.
376    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
377    pub package: Option<PackageId>,
378
379    /// Documentation associated with this world declaration.
380    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
381    pub docs: Docs,
382
383    /// Stability annotation for this world itself.
384    #[cfg_attr(
385        feature = "serde",
386        serde(skip_serializing_if = "Stability::is_unknown")
387    )]
388    pub stability: Stability,
389
390    /// All the included worlds from this world. Empty if this is fully resolved.
391    #[cfg_attr(feature = "serde", serde(skip))]
392    pub includes: Vec<WorldInclude>,
393
394    /// Source span for this world.
395    #[cfg_attr(feature = "serde", serde(skip))]
396    pub span: Span,
397}
398
399impl World {
400    /// Adjusts all spans in this world by adding the given byte offset.
401    pub(crate) fn adjust_spans(&mut self, offset: u32) {
402        self.span.adjust(offset);
403        for item in self.imports.values_mut().chain(self.exports.values_mut()) {
404            item.adjust_spans(offset);
405        }
406        for include in &mut self.includes {
407            include.span.adjust(offset);
408        }
409    }
410}
411
412#[derive(Debug, Clone, PartialEq, Eq)]
413pub struct IncludeName {
414    /// The name of the item
415    pub name: String,
416
417    /// The name to be replaced with
418    pub as_: String,
419}
420
421/// An entry in the `includes` list of a world, representing an `include`
422/// statement in WIT.
423#[derive(Debug, Clone, PartialEq, Eq)]
424pub struct WorldInclude {
425    /// The stability annotation on this include.
426    pub stability: Stability,
427
428    /// The world being included.
429    pub id: WorldId,
430
431    /// Names being renamed as part of this include.
432    pub names: Vec<IncludeName>,
433
434    /// Source span for this include statement.
435    pub span: Span,
436}
437
438/// The key to the import/export maps of a world. Either a kebab-name or a
439/// unique interface.
440#[derive(Debug, Clone, Eq)]
441#[cfg_attr(feature = "serde", derive(Serialize))]
442#[cfg_attr(feature = "serde", serde(into = "String"))]
443pub enum WorldKey {
444    /// A kebab-name.
445    Name(String),
446    /// An interface which is assigned no kebab-name.
447    Interface(InterfaceId),
448}
449
450impl Hash for WorldKey {
451    fn hash<H: Hasher>(&self, hasher: &mut H) {
452        match self {
453            WorldKey::Name(s) => {
454                0u8.hash(hasher);
455                s.as_str().hash(hasher);
456            }
457            WorldKey::Interface(i) => {
458                1u8.hash(hasher);
459                i.hash(hasher);
460            }
461        }
462    }
463}
464
465impl PartialEq for WorldKey {
466    fn eq(&self, other: &WorldKey) -> bool {
467        match (self, other) {
468            (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
469            (WorldKey::Name(_), _) => false,
470            (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
471            (WorldKey::Interface(_), _) => false,
472        }
473    }
474}
475
476impl From<WorldKey> for String {
477    fn from(key: WorldKey) -> String {
478        match key {
479            WorldKey::Name(name) => name,
480            WorldKey::Interface(id) => format!("interface-{}", id.index()),
481        }
482    }
483}
484
485impl WorldKey {
486    /// Asserts that this is `WorldKey::Name` and returns the name.
487    #[track_caller]
488    pub fn unwrap_name(self) -> String {
489        match self {
490            WorldKey::Name(name) => name,
491            WorldKey::Interface(_) => panic!("expected a name, found interface"),
492        }
493    }
494}
495
496#[derive(Debug, Clone, PartialEq, Eq)]
497#[cfg_attr(feature = "serde", derive(Serialize))]
498#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
499pub enum WorldItem {
500    /// An interface is being imported or exported from a world, indicating that
501    /// it's a namespace of functions.
502    Interface {
503        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
504        id: InterfaceId,
505        #[cfg_attr(
506            feature = "serde",
507            serde(skip_serializing_if = "Stability::is_unknown")
508        )]
509        stability: Stability,
510        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
511        external_id: Option<String>,
512        /// Documentation attached to the `import`/`export` statement.
513        #[cfg_attr(
514            feature = "serde",
515            serde(default, skip_serializing_if = "Docs::is_empty")
516        )]
517        docs: Docs,
518        #[cfg_attr(feature = "serde", serde(skip))]
519        span: Span,
520    },
521
522    /// A function is being directly imported or exported from this world.
523    Function(Function),
524
525    /// A type is being exported from this world.
526    ///
527    /// Note that types are never imported into worlds at this time.
528    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_ignore_span"))]
529    Type { id: TypeId, span: Span },
530}
531
532impl WorldItem {
533    pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
534        match self {
535            WorldItem::Interface { stability, .. } => stability,
536            WorldItem::Function(f) => &f.stability,
537            WorldItem::Type { id, .. } => &resolve.types[*id].stability,
538        }
539    }
540
541    pub fn span(&self) -> Span {
542        match self {
543            WorldItem::Interface { span, .. } => *span,
544            WorldItem::Function(f) => f.span,
545            WorldItem::Type { span, .. } => *span,
546        }
547    }
548
549    pub(crate) fn adjust_spans(&mut self, offset: u32) {
550        match self {
551            WorldItem::Function(f) => f.adjust_spans(offset),
552            WorldItem::Interface { span, .. } => span.adjust(offset),
553            WorldItem::Type { span, .. } => span.adjust(offset),
554        }
555    }
556}
557
558#[derive(Debug, Clone, PartialEq, Eq)]
559#[cfg_attr(feature = "serde", derive(Serialize))]
560pub struct Interface {
561    /// Optionally listed name of this interface.
562    ///
563    /// This is `None` for inline interfaces in worlds.
564    pub name: Option<String>,
565
566    /// Exported types from this interface.
567    ///
568    /// Export names are listed within the types themselves. Note that the
569    /// export name here matches the name listed in the `TypeDef`.
570    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
571    pub types: IndexMap<String, TypeId>,
572
573    /// Exported functions from this interface.
574    pub functions: IndexMap<String, Function>,
575
576    /// Documentation associated with this interface.
577    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
578    pub docs: Docs,
579
580    /// Stability attribute for this interface.
581    #[cfg_attr(
582        feature = "serde",
583        serde(skip_serializing_if = "Stability::is_unknown")
584    )]
585    pub stability: Stability,
586
587    /// The package that owns this interface.
588    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
589    pub package: Option<PackageId>,
590
591    /// Source span for this interface.
592    #[cfg_attr(feature = "serde", serde(skip))]
593    pub span: Span,
594
595    /// The interface that this one was cloned from, if any.
596    ///
597    /// Applicable for [`Resolve::generate_nominal_type_ids`].
598    #[cfg_attr(
599        feature = "serde",
600        serde(
601            skip_serializing_if = "Option::is_none",
602            serialize_with = "serialize_optional_id",
603        )
604    )]
605    pub clone_of: Option<InterfaceId>,
606}
607
608impl Interface {
609    /// Adjusts all spans in this interface by adding the given byte offset.
610    pub(crate) fn adjust_spans(&mut self, offset: u32) {
611        self.span.adjust(offset);
612        for func in self.functions.values_mut() {
613            func.adjust_spans(offset);
614        }
615    }
616}
617
618#[derive(Debug, Clone, PartialEq, Eq)]
619#[cfg_attr(feature = "serde", derive(Serialize))]
620pub struct TypeDef {
621    pub name: Option<String>,
622    pub kind: TypeDefKind,
623    pub owner: TypeOwner,
624    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
625    pub docs: Docs,
626    /// Stability attribute for this type.
627    #[cfg_attr(
628        feature = "serde",
629        serde(skip_serializing_if = "Stability::is_unknown")
630    )]
631    pub stability: Stability,
632    /// Source span for this type.
633    #[cfg_attr(feature = "serde", serde(skip))]
634    pub span: Span,
635    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
636    pub external_id: Option<String>,
637}
638
639impl TypeDef {
640    /// Adjusts all spans in this type definition by adding the given byte offset.
641    ///
642    /// This is used when merging source maps to update spans to point to the
643    /// correct location in the combined source map.
644    pub(crate) fn adjust_spans(&mut self, offset: u32) {
645        self.span.adjust(offset);
646        match &mut self.kind {
647            TypeDefKind::Record(r) => {
648                for field in &mut r.fields {
649                    field.span.adjust(offset);
650                }
651            }
652            TypeDefKind::Variant(v) => {
653                for case in &mut v.cases {
654                    case.span.adjust(offset);
655                }
656            }
657            TypeDefKind::Enum(e) => {
658                for case in &mut e.cases {
659                    case.span.adjust(offset);
660                }
661            }
662            TypeDefKind::Flags(f) => {
663                for flag in &mut f.flags {
664                    flag.span.adjust(offset);
665                }
666            }
667            _ => {}
668        }
669    }
670}
671
672#[derive(Debug, Clone, PartialEq, Hash, Eq)]
673#[cfg_attr(feature = "serde", derive(Serialize))]
674#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
675pub enum TypeDefKind {
676    Record(Record),
677    Resource,
678    Handle(Handle),
679    Flags(Flags),
680    Tuple(Tuple),
681    Variant(Variant),
682    Enum(Enum),
683    Option(Type),
684    Result(Result_),
685    List(Type),
686    Map(Type, Type),
687    FixedLengthList(Type, u32),
688    Future(Option<Type>),
689    Stream(Option<Type>),
690    Type(Type),
691
692    /// This represents a type of unknown structure imported from a foreign
693    /// interface.
694    ///
695    /// This variant is only used during the creation of `UnresolvedPackage` but
696    /// by the time a `Resolve` is created then this will not exist.
697    Unknown,
698}
699
700impl TypeDefKind {
701    pub fn as_str(&self) -> &'static str {
702        match self {
703            TypeDefKind::Record(_) => "record",
704            TypeDefKind::Resource => "resource",
705            TypeDefKind::Handle(handle) => match handle {
706                Handle::Own(_) => "own",
707                Handle::Borrow(_) => "borrow",
708            },
709            TypeDefKind::Flags(_) => "flags",
710            TypeDefKind::Tuple(_) => "tuple",
711            TypeDefKind::Variant(_) => "variant",
712            TypeDefKind::Enum(_) => "enum",
713            TypeDefKind::Option(_) => "option",
714            TypeDefKind::Result(_) => "result",
715            TypeDefKind::List(_) => "list",
716            TypeDefKind::Map(_, _) => "map",
717            TypeDefKind::FixedLengthList(..) => "fixed-length list",
718            TypeDefKind::Future(_) => "future",
719            TypeDefKind::Stream(_) => "stream",
720            TypeDefKind::Type(_) => "type",
721            TypeDefKind::Unknown => "unknown",
722        }
723    }
724}
725
726#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
727#[cfg_attr(feature = "serde", derive(Serialize))]
728#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
729pub enum TypeOwner {
730    /// This type was defined within a `world` block.
731    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
732    World(WorldId),
733    /// This type was defined within an `interface` block.
734    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
735    Interface(InterfaceId),
736    /// This type wasn't inherently defined anywhere, such as a `list<T>`, which
737    /// doesn't need an owner.
738    #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
739    None,
740}
741
742#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
743#[cfg_attr(feature = "serde", derive(Serialize))]
744#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
745pub enum Handle {
746    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
747    Own(TypeId),
748    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
749    Borrow(TypeId),
750}
751
752#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone)]
753pub enum Type {
754    Bool,
755    U8,
756    U16,
757    U32,
758    U64,
759    S8,
760    S16,
761    S32,
762    S64,
763    F32,
764    F64,
765    Char,
766    String,
767    ErrorContext,
768    Id(TypeId),
769}
770
771#[derive(Debug, Copy, Clone, Eq, PartialEq)]
772pub enum Int {
773    U8,
774    U16,
775    U32,
776    U64,
777}
778
779#[derive(Debug, Clone, PartialEq, Hash, Eq)]
780#[cfg_attr(feature = "serde", derive(Serialize))]
781pub struct Record {
782    pub fields: Vec<Field>,
783}
784
785#[derive(Debug, Clone, PartialEq, Hash, Eq)]
786#[cfg_attr(feature = "serde", derive(Serialize))]
787pub struct Field {
788    pub name: String,
789    #[cfg_attr(feature = "serde", serde(rename = "type"))]
790    pub ty: Type,
791    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
792    pub docs: Docs,
793    /// Source span for this field.
794    #[cfg_attr(feature = "serde", serde(skip))]
795    pub span: Span,
796}
797
798#[derive(Debug, Clone, PartialEq, Hash, Eq)]
799#[cfg_attr(feature = "serde", derive(Serialize))]
800pub struct Flags {
801    pub flags: Vec<Flag>,
802}
803
804#[derive(Debug, Clone, PartialEq, Hash, Eq)]
805#[cfg_attr(feature = "serde", derive(Serialize))]
806pub struct Flag {
807    pub name: String,
808    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
809    pub docs: Docs,
810    /// Source span for this flag.
811    #[cfg_attr(feature = "serde", serde(skip))]
812    pub span: Span,
813}
814
815#[derive(Debug, Clone, PartialEq)]
816pub enum FlagsRepr {
817    U8,
818    U16,
819    U32(usize),
820}
821
822impl Flags {
823    pub fn repr(&self) -> FlagsRepr {
824        match self.flags.len() {
825            0 => FlagsRepr::U32(0),
826            n if n <= 8 => FlagsRepr::U8,
827            n if n <= 16 => FlagsRepr::U16,
828            n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
829        }
830    }
831}
832
833impl FlagsRepr {
834    pub fn count(&self) -> usize {
835        match self {
836            FlagsRepr::U8 => 1,
837            FlagsRepr::U16 => 1,
838            FlagsRepr::U32(n) => *n,
839        }
840    }
841}
842
843#[derive(Debug, Clone, PartialEq, Hash, Eq)]
844#[cfg_attr(feature = "serde", derive(Serialize))]
845pub struct Tuple {
846    pub types: Vec<Type>,
847}
848
849#[derive(Debug, Clone, PartialEq, Hash, Eq)]
850#[cfg_attr(feature = "serde", derive(Serialize))]
851pub struct Variant {
852    pub cases: Vec<Case>,
853}
854
855#[derive(Debug, Clone, PartialEq, Hash, Eq)]
856#[cfg_attr(feature = "serde", derive(Serialize))]
857pub struct Case {
858    pub name: String,
859    #[cfg_attr(feature = "serde", serde(rename = "type"))]
860    pub ty: Option<Type>,
861    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
862    pub docs: Docs,
863    /// Source span for this variant case.
864    #[cfg_attr(feature = "serde", serde(skip))]
865    pub span: Span,
866}
867
868impl Variant {
869    pub fn tag(&self) -> Int {
870        discriminant_type(self.cases.len())
871    }
872}
873
874#[derive(Debug, Clone, PartialEq, Hash, Eq)]
875#[cfg_attr(feature = "serde", derive(Serialize))]
876pub struct Enum {
877    pub cases: Vec<EnumCase>,
878}
879
880#[derive(Debug, Clone, PartialEq, Hash, Eq)]
881#[cfg_attr(feature = "serde", derive(Serialize))]
882pub struct EnumCase {
883    pub name: String,
884    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
885    pub docs: Docs,
886    /// Source span for this enum case.
887    #[cfg_attr(feature = "serde", serde(skip))]
888    pub span: Span,
889}
890
891impl Enum {
892    pub fn tag(&self) -> Int {
893        discriminant_type(self.cases.len())
894    }
895}
896
897/// This corresponds to the `discriminant_type` function in the Canonical ABI.
898fn discriminant_type(num_cases: usize) -> Int {
899    match num_cases.checked_sub(1) {
900        None => Int::U8,
901        Some(n) if n <= u8::MAX as usize => Int::U8,
902        Some(n) if n <= u16::MAX as usize => Int::U16,
903        Some(n) if n <= u32::MAX as usize => Int::U32,
904        _ => panic!("too many cases to fit in a repr"),
905    }
906}
907
908#[derive(Debug, Clone, PartialEq, Hash, Eq)]
909#[cfg_attr(feature = "serde", derive(Serialize))]
910pub struct Result_ {
911    pub ok: Option<Type>,
912    pub err: Option<Type>,
913}
914
915#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
916#[cfg_attr(feature = "serde", derive(Serialize))]
917pub struct Docs {
918    pub contents: Option<String>,
919}
920
921impl Docs {
922    pub fn is_empty(&self) -> bool {
923        self.contents.is_none()
924    }
925}
926
927#[derive(Debug, Clone, PartialEq, Eq)]
928#[cfg_attr(feature = "serde", derive(Serialize))]
929pub struct Param {
930    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
931    pub name: String,
932    #[cfg_attr(feature = "serde", serde(rename = "type"))]
933    pub ty: Type,
934    #[cfg_attr(feature = "serde", serde(skip))]
935    pub span: Span,
936}
937
938#[derive(Debug, Clone, PartialEq, Eq)]
939#[cfg_attr(feature = "serde", derive(Serialize))]
940pub struct Function {
941    pub name: String,
942    pub kind: FunctionKind,
943    pub params: Vec<Param>,
944    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
945    pub result: Option<Type>,
946    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
947    pub docs: Docs,
948    /// Stability attribute for this function.
949    #[cfg_attr(
950        feature = "serde",
951        serde(skip_serializing_if = "Stability::is_unknown")
952    )]
953    pub stability: Stability,
954
955    /// Source span for this function.
956    #[cfg_attr(feature = "serde", serde(skip))]
957    pub span: Span,
958    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
959    pub external_id: Option<String>,
960}
961
962#[derive(Debug, Clone, PartialEq, Eq)]
963#[cfg_attr(feature = "serde", derive(Serialize))]
964#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
965pub enum FunctionKind {
966    /// A freestanding function.
967    ///
968    /// ```wit
969    /// interface foo {
970    ///     the-func: func();
971    /// }
972    /// ```
973    Freestanding,
974
975    /// An async freestanding function.
976    ///
977    /// ```wit
978    /// interface foo {
979    ///     the-func: async func();
980    /// }
981    /// ```
982    AsyncFreestanding,
983
984    /// A getter function, which takes no parameters and returns a value.
985    ///
986    /// ```wit
987    /// interface foo {
988    ///     the-prop: get() -> u32;
989    /// }
990    /// ```
991    Getter,
992
993    /// A setter function, which takes one parameter and returns either nothing
994    /// or `result<_, error?>`.
995    ///
996    /// ```wit
997    /// interface foo {
998    ///     the-prop: set(value: u32);
999    /// }
1000    /// ```
1001    Setter,
1002
1003    /// A resource method where the first parameter is implicitly
1004    /// `borrow<T>`.
1005    ///
1006    /// ```wit
1007    /// interface foo {
1008    ///     resource r {
1009    ///         the-func: func();
1010    ///     }
1011    /// }
1012    /// ```
1013    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1014    Method(TypeId),
1015
1016    /// An async resource method where the first parameter is implicitly
1017    /// `borrow<T>`.
1018    ///
1019    /// ```wit
1020    /// interface foo {
1021    ///     resource r {
1022    ///         the-func: async func();
1023    ///     }
1024    /// }
1025    /// ```
1026    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1027    AsyncMethod(TypeId),
1028
1029    /// A resource getter where the first parameter is implicitly `borrow<T>`.
1030    ///
1031    /// ```wit
1032    /// interface foo {
1033    ///     resource r {
1034    ///         the-prop: get() -> u32;
1035    ///     }
1036    /// }
1037    /// ```
1038    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1039    MethodGetter(TypeId),
1040
1041    /// A resource setter where the first parameter is implicitly `borrow<T>`.
1042    ///
1043    /// ```wit
1044    /// interface foo {
1045    ///     resource r {
1046    ///         the-prop: set(value: u32);
1047    ///     }
1048    /// }
1049    /// ```
1050    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1051    MethodSetter(TypeId),
1052
1053    /// A static resource method.
1054    ///
1055    /// ```wit
1056    /// interface foo {
1057    ///     resource r {
1058    ///         the-func: static func();
1059    ///     }
1060    /// }
1061    /// ```
1062    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1063    Static(TypeId),
1064
1065    /// An async static resource method.
1066    ///
1067    /// ```wit
1068    /// interface foo {
1069    ///     resource r {
1070    ///         the-func: static async func();
1071    ///     }
1072    /// }
1073    /// ```
1074    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1075    AsyncStatic(TypeId),
1076
1077    /// A static resource getter.
1078    ///
1079    /// ```wit
1080    /// interface foo {
1081    ///     resource r {
1082    ///         the-prop: static get() -> u32;
1083    ///     }
1084    /// }
1085    /// ```
1086    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1087    StaticGetter(TypeId),
1088
1089    /// A static resource setter.
1090    ///
1091    /// ```wit
1092    /// interface foo {
1093    ///     resource r {
1094    ///         the-prop: static set(value: u32);
1095    ///     }
1096    /// }
1097    /// ```
1098    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1099    StaticSetter(TypeId),
1100
1101    /// A resource constructor where the return value is implicitly `own<T>`.
1102    ///
1103    /// ```wit
1104    /// interface foo {
1105    ///     resource r {
1106    ///         constructor();
1107    ///     }
1108    /// }
1109    /// ```
1110    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
1111    Constructor(TypeId),
1112}
1113
1114impl FunctionKind {
1115    /// Returns whether this is an async function or not.
1116    pub fn is_async(&self) -> bool {
1117        match self {
1118            FunctionKind::Freestanding
1119            | FunctionKind::Method(_)
1120            | FunctionKind::Static(_)
1121            | FunctionKind::Constructor(_)
1122            | FunctionKind::Getter
1123            | FunctionKind::Setter
1124            | FunctionKind::MethodGetter(_)
1125            | FunctionKind::MethodSetter(_)
1126            | FunctionKind::StaticGetter(_)
1127            | FunctionKind::StaticSetter(_) => false,
1128            FunctionKind::AsyncFreestanding
1129            | FunctionKind::AsyncMethod(_)
1130            | FunctionKind::AsyncStatic(_) => true,
1131        }
1132    }
1133
1134    /// Returns whether this function is a getter or a setter.
1135    pub fn accessor(&self) -> Option<AccessorKind> {
1136        match self {
1137            FunctionKind::Getter
1138            | FunctionKind::MethodGetter(_)
1139            | FunctionKind::StaticGetter(_) => Some(AccessorKind::Getter),
1140            FunctionKind::Setter
1141            | FunctionKind::MethodSetter(_)
1142            | FunctionKind::StaticSetter(_) => Some(AccessorKind::Setter),
1143            FunctionKind::Freestanding
1144            | FunctionKind::AsyncFreestanding
1145            | FunctionKind::Method(_)
1146            | FunctionKind::AsyncMethod(_)
1147            | FunctionKind::Static(_)
1148            | FunctionKind::AsyncStatic(_)
1149            | FunctionKind::Constructor(_) => None,
1150        }
1151    }
1152
1153    /// Returns the resource, if present, that this function kind refers to.
1154    pub fn resource(&self) -> Option<TypeId> {
1155        match self {
1156            FunctionKind::Freestanding
1157            | FunctionKind::AsyncFreestanding
1158            | FunctionKind::Getter
1159            | FunctionKind::Setter => None,
1160            FunctionKind::Method(id)
1161            | FunctionKind::Static(id)
1162            | FunctionKind::Constructor(id)
1163            | FunctionKind::AsyncMethod(id)
1164            | FunctionKind::AsyncStatic(id)
1165            | FunctionKind::MethodGetter(id)
1166            | FunctionKind::MethodSetter(id)
1167            | FunctionKind::StaticGetter(id)
1168            | FunctionKind::StaticSetter(id) => Some(*id),
1169        }
1170    }
1171
1172    /// Returns the resource, if present, that this function kind refers to.
1173    pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
1174        match self {
1175            FunctionKind::Freestanding
1176            | FunctionKind::AsyncFreestanding
1177            | FunctionKind::Getter
1178            | FunctionKind::Setter => None,
1179            FunctionKind::Method(id)
1180            | FunctionKind::Static(id)
1181            | FunctionKind::Constructor(id)
1182            | FunctionKind::AsyncMethod(id)
1183            | FunctionKind::AsyncStatic(id)
1184            | FunctionKind::MethodGetter(id)
1185            | FunctionKind::MethodSetter(id)
1186            | FunctionKind::StaticGetter(id)
1187            | FunctionKind::StaticSetter(id) => Some(id),
1188        }
1189    }
1190}
1191
1192/// Whether an accessor function is a getter or a setter.
1193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1194#[cfg_attr(feature = "serde", derive(Serialize))]
1195#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1196pub enum AccessorKind {
1197    /// A `get` function, encoded with a `[get]` name.
1198    Getter,
1199    /// A `set` function, encoded with a `[set]` name.
1200    Setter,
1201}
1202
1203/// Reorders `items` so that every setter immediately follows its getter. (WIT
1204/// allows functions to be declared in any order, but the component binary
1205/// format requires getters to precede setters.)
1206pub(crate) fn place_setters_after_getters<K, V>(
1207    items: &mut IndexMap<K, V>,
1208    func: impl Fn(&V) -> Option<&Function>,
1209) {
1210    // This function basically does a very limited linear "sort" by moving
1211    // setters forward if we haven't seen their getter yet. When we do this, we
1212    // simply don't bump the loop index and then continue iterating from
1213    // whatever item slid back into the setter's place. We will eventually see
1214    // that same setter again but that's fine.
1215
1216    let mut getters_seen = HashSet::new();
1217    let mut i = 0;
1218    while let Some((_, item)) = items.get_index(i) {
1219        match func(item) {
1220            Some(f) => match f.kind.accessor() {
1221                Some(AccessorKind::Getter) => {
1222                    getters_seen.insert(f.name.clone());
1223                }
1224                Some(AccessorKind::Setter) => {
1225                    let getter_name = f.name.replacen("[set]", "[get]", 1);
1226                    if !getters_seen.contains(&getter_name) {
1227                        // The getter, if present, is somewhere after `i`.
1228                        let getter_index = (i + 1..items.len())
1229                            .find(|&j| func(&items[j]).is_some_and(|g| g.name == getter_name));
1230                        if let Some(g) = getter_index {
1231                            // Moving the setter to follow the getter will move
1232                            // the intermediate items back, so we continue here
1233                            // without incrementing i.
1234                            items.move_index(i, g);
1235                            continue;
1236                        }
1237                    }
1238                }
1239                None => {}
1240            },
1241            None => {}
1242        }
1243        i += 1;
1244    }
1245}
1246
1247/// Helper for [`place_setters_after_getters`] over a world's imports/exports.
1248pub(crate) fn world_item_func(item: &WorldItem) -> Option<&Function> {
1249    match item {
1250        WorldItem::Function(f) => Some(f),
1251        _ => None,
1252    }
1253}
1254
1255/// Possible forms of name mangling that are supported by this crate.
1256#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1257pub enum Mangling {
1258    /// The "standard" component model mangling format for 32-bit linear
1259    /// memories. This is specified in WebAssembly/component-model#378
1260    Standard32,
1261
1262    /// The "legacy" name mangling supported in versions 218-and-prior for this
1263    /// crate. This is the original support for how components were created from
1264    /// core wasm modules and this does not correspond to any standard. This is
1265    /// preserved for now while tools transition to the new scheme.
1266    Legacy,
1267}
1268
1269impl core::str::FromStr for Mangling {
1270    type Err = anyhow::Error;
1271
1272    fn from_str(s: &str) -> anyhow::Result<Mangling> {
1273        match s {
1274            "legacy" => Ok(Mangling::Legacy),
1275            "standard32" => Ok(Mangling::Standard32),
1276            _ => {
1277                anyhow::bail!(
1278                    "unknown name mangling `{s}`, \
1279                     supported values are `legacy` or `standard32`"
1280                )
1281            }
1282        }
1283    }
1284}
1285
1286/// Possible lift/lower ABI choices supported when mangling names.
1287#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1288pub enum LiftLowerAbi {
1289    /// Both imports and exports will use the synchronous ABI.
1290    Sync,
1291
1292    /// Both imports and exports will use the async ABI (with a callback for
1293    /// each export).
1294    AsyncCallback,
1295
1296    /// Both imports and exports will use the async ABI (with no callbacks for
1297    /// exports).
1298    AsyncStackful,
1299}
1300
1301impl LiftLowerAbi {
1302    fn import_prefix(self) -> &'static str {
1303        match self {
1304            Self::Sync => "",
1305            Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1306        }
1307    }
1308
1309    /// Get the import [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1310    pub fn import_variant(self) -> AbiVariant {
1311        match self {
1312            Self::Sync => AbiVariant::GuestImport,
1313            Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1314        }
1315    }
1316
1317    fn export_prefix(self) -> &'static str {
1318        match self {
1319            Self::Sync => "",
1320            Self::AsyncCallback => "[async-lift]",
1321            Self::AsyncStackful => "[async-lift-stackful]",
1322        }
1323    }
1324
1325    /// Get the export [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1326    pub fn export_variant(self) -> AbiVariant {
1327        match self {
1328            Self::Sync => AbiVariant::GuestExport,
1329            Self::AsyncCallback => AbiVariant::GuestExportAsync,
1330            Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1331        }
1332    }
1333}
1334
1335/// Combination of [`Mangling`] and [`LiftLowerAbi`].
1336#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1337pub enum ManglingAndAbi {
1338    /// See [`Mangling::Standard32`].
1339    ///
1340    /// As of this writing, the standard name mangling only supports the
1341    /// synchronous ABI.
1342    Standard32,
1343
1344    /// See [`Mangling::Legacy`] and [`LiftLowerAbi`].
1345    Legacy(LiftLowerAbi),
1346}
1347
1348impl ManglingAndAbi {
1349    /// Get the import [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1350    pub fn import_variant(self) -> AbiVariant {
1351        match self {
1352            Self::Standard32 => AbiVariant::GuestImport,
1353            Self::Legacy(abi) => abi.import_variant(),
1354        }
1355    }
1356
1357    /// Get the export [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1358    pub fn export_variant(self) -> AbiVariant {
1359        match self {
1360            Self::Standard32 => AbiVariant::GuestExport,
1361            Self::Legacy(abi) => abi.export_variant(),
1362        }
1363    }
1364
1365    /// Switch the ABI to be sync if it's async.
1366    pub fn sync(self) -> Self {
1367        match self {
1368            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1369            Self::Legacy(LiftLowerAbi::AsyncCallback)
1370            | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1371        }
1372    }
1373
1374    /// Returns whether this is an async ABI
1375    pub fn is_async(&self) -> bool {
1376        match self {
1377            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1378            Self::Legacy(LiftLowerAbi::AsyncCallback)
1379            | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1380        }
1381    }
1382
1383    pub fn mangling(&self) -> Mangling {
1384        match self {
1385            Self::Standard32 => Mangling::Standard32,
1386            Self::Legacy(_) => Mangling::Legacy,
1387        }
1388    }
1389
1390    /// Returns a suitable [`ManglingAndAbi`], based on `self`, to use for
1391    /// `func`.
1392    ///
1393    /// This handles the case where `func` is a synchronous function which means
1394    /// that it's forced to use the sync ABI no matter what.
1395    pub fn for_func(&self, func: &Function) -> Self {
1396        match self {
1397            Self::Standard32 => *self,
1398            Self::Legacy(abi) => {
1399                if !func.kind.is_async() {
1400                    Self::Legacy(LiftLowerAbi::Sync)
1401                } else {
1402                    Self::Legacy(*abi)
1403                }
1404            }
1405        }
1406    }
1407}
1408
1409impl Function {
1410    /// Adjusts all spans in this function by adding the given byte offset.
1411    pub(crate) fn adjust_spans(&mut self, offset: u32) {
1412        self.span.adjust(offset);
1413        for param in &mut self.params {
1414            param.span.adjust(offset);
1415        }
1416    }
1417
1418    pub fn item_name(&self) -> &str {
1419        match &self.kind {
1420            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1421            FunctionKind::Method(_)
1422            | FunctionKind::Static(_)
1423            | FunctionKind::AsyncMethod(_)
1424            | FunctionKind::AsyncStatic(_)
1425            | FunctionKind::MethodGetter(_)
1426            | FunctionKind::MethodSetter(_)
1427            | FunctionKind::StaticGetter(_)
1428            | FunctionKind::StaticSetter(_) => &self.name[self.name.find('.').unwrap() + 1..],
1429            FunctionKind::Getter | FunctionKind::Setter => {
1430                &self.name[self.name.find(']').unwrap() + 1..]
1431            }
1432            FunctionKind::Constructor(_) => "constructor",
1433        }
1434    }
1435
1436    /// Returns an iterator over the types used in parameters and results.
1437    ///
1438    /// Note that this iterator is not transitive, it only iterates over the
1439    /// direct references to types that this function has.
1440    pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1441        self.params.iter().map(|p| p.ty).chain(self.result)
1442    }
1443
1444    /// Gets the core export name for this function.
1445    pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1446        self.core_export_name(interface, Mangling::Standard32)
1447    }
1448
1449    pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1450        self.core_export_name(interface, Mangling::Legacy)
1451    }
1452    /// Gets the core export name for this function.
1453    pub fn core_export_name<'a>(
1454        &'a self,
1455        interface: Option<&str>,
1456        mangling: Mangling,
1457    ) -> Cow<'a, str> {
1458        match interface {
1459            Some(interface) => match mangling {
1460                Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1461                Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1462            },
1463            None => match mangling {
1464                Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1465                Mangling::Legacy => Cow::Borrowed(&self.name),
1466            },
1467        }
1468    }
1469    /// Collect any future and stream types appearing in the signature of this
1470    /// function by doing a depth-first search over the parameter types and then
1471    /// the result types.
1472    ///
1473    /// For example, given the WIT function `foo: func(x: future<future<u32>>,
1474    /// y: u32) -> stream<u8>`, we would return `[future<u32>,
1475    /// future<future<u32>>, stream<u8>]`.
1476    ///
1477    /// This may be used by binding generators to refer to specific `future` and
1478    /// `stream` types when importing canonical built-ins such as `stream.new`,
1479    /// `future.read`, etc.  Using the example above, the import
1480    /// `[future-new-0]foo` would indicate a call to `future.new` for the type
1481    /// `future<u32>`.  Likewise, `[future-new-1]foo` would indicate a call to
1482    /// `future.new` for `future<future<u32>>`, and `[stream-new-2]foo` would
1483    /// indicate a call to `stream.new` for `stream<u8>`.
1484    pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1485        let mut results = Vec::new();
1486        for param in self.params.iter() {
1487            find_futures_and_streams(resolve, param.ty, &mut results);
1488        }
1489        if let Some(ty) = self.result {
1490            find_futures_and_streams(resolve, ty, &mut results);
1491        }
1492        results
1493    }
1494
1495    /// Check if this function is a resource constructor in shorthand form.
1496    /// I.e. without an explicit return type annotation.
1497    pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1498        let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1499            return false;
1500        };
1501
1502        let Some(Type::Id(id)) = &self.result else {
1503            return false;
1504        };
1505
1506        let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1507            return false;
1508        };
1509
1510        return containing_resource_id == returned_resource_id;
1511    }
1512
1513    /// Returns the `module`, `name`, and signature to use when importing this
1514    /// function's `task.return` intrinsic using the `mangling` specified.
1515    pub fn task_return_import(
1516        &self,
1517        resolve: &Resolve,
1518        interface: Option<&WorldKey>,
1519        mangling: Mangling,
1520    ) -> (String, String, abi::WasmSignature) {
1521        match mangling {
1522            Mangling::Standard32 => todo!(),
1523            Mangling::Legacy => {}
1524        }
1525        // For exported async functions, generate a `task.return` intrinsic.
1526        let module = match interface {
1527            Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1528            None => "[export]$root".to_string(),
1529        };
1530        let name = format!("[task-return]{}", self.name);
1531
1532        let mut func_tmp = self.clone();
1533        func_tmp.params = Vec::new();
1534        func_tmp.result = None;
1535        if let Some(ty) = self.result {
1536            func_tmp.params.push(Param {
1537                name: "x".to_string(),
1538                ty,
1539                span: Default::default(),
1540            });
1541        }
1542        let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1543        (module, name, sig)
1544    }
1545
1546    // push_imported_future_and_stream_intrinsics(wat, resolve, "[export]", interface, func);
1547}
1548
1549fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1550    let Type::Id(id) = ty else {
1551        return;
1552    };
1553
1554    match &resolve.types[id].kind {
1555        TypeDefKind::Resource
1556        | TypeDefKind::Handle(_)
1557        | TypeDefKind::Flags(_)
1558        | TypeDefKind::Enum(_) => {}
1559        TypeDefKind::Record(r) => {
1560            for Field { ty, .. } in &r.fields {
1561                find_futures_and_streams(resolve, *ty, results);
1562            }
1563        }
1564        TypeDefKind::Tuple(t) => {
1565            for ty in &t.types {
1566                find_futures_and_streams(resolve, *ty, results);
1567            }
1568        }
1569        TypeDefKind::Variant(v) => {
1570            for Case { ty, .. } in &v.cases {
1571                if let Some(ty) = ty {
1572                    find_futures_and_streams(resolve, *ty, results);
1573                }
1574            }
1575        }
1576        TypeDefKind::Option(ty)
1577        | TypeDefKind::List(ty)
1578        | TypeDefKind::FixedLengthList(ty, ..)
1579        | TypeDefKind::Type(ty) => {
1580            find_futures_and_streams(resolve, *ty, results);
1581        }
1582        TypeDefKind::Map(k, v) => {
1583            find_futures_and_streams(resolve, *k, results);
1584            find_futures_and_streams(resolve, *v, results);
1585        }
1586        TypeDefKind::Result(r) => {
1587            if let Some(ty) = r.ok {
1588                find_futures_and_streams(resolve, ty, results);
1589            }
1590            if let Some(ty) = r.err {
1591                find_futures_and_streams(resolve, ty, results);
1592            }
1593        }
1594        TypeDefKind::Future(ty) => {
1595            if let Some(ty) = ty {
1596                find_futures_and_streams(resolve, *ty, results);
1597            }
1598            results.push(id);
1599        }
1600        TypeDefKind::Stream(ty) => {
1601            if let Some(ty) = ty {
1602                find_futures_and_streams(resolve, *ty, results);
1603            }
1604            results.push(id);
1605        }
1606        TypeDefKind::Unknown => unreachable!(),
1607    }
1608}
1609
1610/// Representation of the stability attributes associated with a world,
1611/// interface, function, or type.
1612///
1613/// This is added for WebAssembly/component-model#332 where @since and @unstable
1614/// annotations were added to WIT.
1615///
1616/// The order of the of enum values is significant since it is used with Ord and PartialOrd
1617#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1618#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1619#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1620pub enum Stability {
1621    /// This item does not have either `@since` or `@unstable`.
1622    Unknown,
1623
1624    /// `@unstable(feature = foo)`
1625    ///
1626    /// This item is explicitly tagged `@unstable`. A feature name is listed and
1627    /// this item is excluded by default in `Resolve` unless explicitly enabled.
1628    Unstable {
1629        feature: String,
1630        #[cfg_attr(
1631            feature = "serde",
1632            serde(
1633                skip_serializing_if = "Option::is_none",
1634                default,
1635                serialize_with = "serialize_optional_version",
1636                deserialize_with = "deserialize_optional_version"
1637            )
1638        )]
1639        deprecated: Option<Version>,
1640    },
1641
1642    /// `@since(version = 1.2.3)`
1643    ///
1644    /// This item is explicitly tagged with `@since` as stable since the
1645    /// specified version.  This may optionally have a feature listed as well.
1646    Stable {
1647        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1648        #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1649        since: Version,
1650        #[cfg_attr(
1651            feature = "serde",
1652            serde(
1653                skip_serializing_if = "Option::is_none",
1654                default,
1655                serialize_with = "serialize_optional_version",
1656                deserialize_with = "deserialize_optional_version"
1657            )
1658        )]
1659        deprecated: Option<Version>,
1660    },
1661}
1662
1663impl Stability {
1664    /// Returns whether this is `Stability::Unknown`.
1665    pub fn is_unknown(&self) -> bool {
1666        matches!(self, Stability::Unknown)
1667    }
1668
1669    pub fn is_stable(&self) -> bool {
1670        matches!(self, Stability::Stable { .. })
1671    }
1672}
1673
1674impl Default for Stability {
1675    fn default() -> Stability {
1676        Stability::Unknown
1677    }
1678}
1679
1680#[cfg(test)]
1681mod test {
1682    use super::*;
1683    use alloc::vec;
1684
1685    #[test]
1686    fn test_discriminant_type() {
1687        assert_eq!(discriminant_type(1), Int::U8);
1688        assert_eq!(discriminant_type(0x100), Int::U8);
1689        assert_eq!(discriminant_type(0x101), Int::U16);
1690        assert_eq!(discriminant_type(0x10000), Int::U16);
1691        assert_eq!(discriminant_type(0x10001), Int::U32);
1692        if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1693            assert_eq!(discriminant_type(num_cases), Int::U32);
1694        }
1695    }
1696
1697    #[test]
1698    fn test_find_futures_and_streams() {
1699        let mut resolve = Resolve::default();
1700        let t0 = resolve.types.alloc(TypeDef {
1701            name: None,
1702            kind: TypeDefKind::Future(Some(Type::U32)),
1703            owner: TypeOwner::None,
1704            docs: Docs::default(),
1705            stability: Stability::Unknown,
1706            span: Default::default(),
1707            external_id: Default::default(),
1708        });
1709        let t1 = resolve.types.alloc(TypeDef {
1710            name: None,
1711            kind: TypeDefKind::Future(Some(Type::Id(t0))),
1712            owner: TypeOwner::None,
1713            docs: Docs::default(),
1714            stability: Stability::Unknown,
1715            span: Default::default(),
1716            external_id: Default::default(),
1717        });
1718        let t2 = resolve.types.alloc(TypeDef {
1719            name: None,
1720            kind: TypeDefKind::Stream(Some(Type::U32)),
1721            owner: TypeOwner::None,
1722            docs: Docs::default(),
1723            stability: Stability::Unknown,
1724            span: Default::default(),
1725            external_id: Default::default(),
1726        });
1727        let found = Function {
1728            name: "foo".into(),
1729            kind: FunctionKind::Freestanding,
1730            params: vec![
1731                Param {
1732                    name: "p1".into(),
1733                    ty: Type::Id(t1),
1734                    span: Default::default(),
1735                },
1736                Param {
1737                    name: "p2".into(),
1738                    ty: Type::U32,
1739                    span: Default::default(),
1740                },
1741            ],
1742            result: Some(Type::Id(t2)),
1743            docs: Docs::default(),
1744            stability: Stability::Unknown,
1745            span: Default::default(),
1746            external_id: Default::default(),
1747        }
1748        .find_futures_and_streams(&resolve);
1749        assert_eq!(3, found.len());
1750        assert_eq!(t0, found[0]);
1751        assert_eq!(t1, found[1]);
1752        assert_eq!(t2, found[2]);
1753    }
1754
1755    #[test]
1756    fn test_canon_version_split() {
1757        use semver::Version;
1758
1759        let v = Version::parse("1.2.3").unwrap();
1760        assert_eq!(
1761            PackageName::version_compat_track_string(&v),
1762            ("1".to_string(), Some(".2.3".to_string()))
1763        );
1764
1765        let v = Version::parse("101.201.301").unwrap();
1766        assert_eq!(
1767            PackageName::version_compat_track_string(&v),
1768            ("101".to_string(), Some(".201.301".to_string()))
1769        );
1770
1771        let v = Version::parse("0.2.6-rc.1").unwrap();
1772        assert_eq!(
1773            PackageName::version_compat_track_string(&v),
1774            ("0.2.6-rc.1".to_string(), None)
1775        );
1776
1777        let v = Version::parse("0.10.0+build.1").unwrap();
1778        assert_eq!(
1779            PackageName::version_compat_track_string(&v),
1780            ("0.10".to_string(), Some(".0+build.1".to_string()))
1781        );
1782
1783        let v = Version::parse("0.0.1-alpha+build.1").unwrap();
1784        assert_eq!(
1785            PackageName::version_compat_track_string(&v),
1786            ("0.0.1-alpha".to_string(), Some("+build.1".to_string()))
1787        );
1788
1789        let v = Version::parse("0.0.0").unwrap();
1790        assert_eq!(
1791            PackageName::version_compat_track_string(&v),
1792            ("0.0.0".to_string(), None)
1793        );
1794
1795        let v = Version::parse("1.0.0-beta.1").unwrap();
1796        assert_eq!(
1797            PackageName::version_compat_track_string(&v),
1798            ("1.0.0-beta.1".to_string(), None)
1799        );
1800
1801        let v = Version::parse("0.0.100+build.1").unwrap();
1802        assert_eq!(
1803            PackageName::version_compat_track_string(&v),
1804            ("0.0.100".to_string(), Some("+build.1".to_string()))
1805        );
1806    }
1807}