wit_parser/
lib.rs

1use crate::abi::AbiVariant;
2use anyhow::{Context, Result, bail};
3use id_arena::{Arena, Id};
4use indexmap::IndexMap;
5use semver::Version;
6use std::borrow::Cow;
7use std::fmt;
8use std::hash::{Hash, Hasher};
9use std::path::Path;
10
11#[cfg(feature = "decoding")]
12pub mod decoding;
13#[cfg(feature = "decoding")]
14mod metadata;
15#[cfg(feature = "decoding")]
16pub use metadata::PackageMetadata;
17
18pub mod abi;
19mod ast;
20pub use ast::SourceMap;
21use ast::lex::Span;
22pub use ast::{ParsedUsePath, parse_use_path};
23mod sizealign;
24pub use sizealign::*;
25mod resolve;
26pub use resolve::*;
27mod live;
28pub use live::{LiveTypes, TypeIdVisitor};
29
30#[cfg(feature = "serde")]
31use serde_derive::Serialize;
32#[cfg(feature = "serde")]
33mod serde_;
34#[cfg(feature = "serde")]
35use serde_::*;
36
37/// Checks if the given string is a legal identifier in wit.
38pub fn validate_id(s: &str) -> Result<()> {
39    ast::validate_id(0, s)?;
40    Ok(())
41}
42
43pub type WorldId = Id<World>;
44pub type InterfaceId = Id<Interface>;
45pub type TypeId = Id<TypeDef>;
46
47/// Representation of a parsed WIT package which has not resolved external
48/// dependencies yet.
49///
50/// This representation has performed internal resolution of the WIT package
51/// itself, ensuring that all references internally are valid and the WIT was
52/// syntactically valid and such.
53///
54/// The fields of this structure represent a flat list of arrays unioned from
55/// all documents within the WIT package. This means, for example, that all
56/// types from all documents are located in `self.types`. The fields of each
57/// item can help splitting back out into packages/interfaces/etc as necessary.
58///
59/// Note that an `UnresolvedPackage` cannot be queried in general about
60/// information such as size or alignment as that would require resolution of
61/// foreign dependencies. Translations such as to-binary additionally are not
62/// supported on an `UnresolvedPackage` due to the lack of knowledge about the
63/// foreign types. This is intended to be an intermediate state which can be
64/// inspected by embedders, if necessary, before quickly transforming to a
65/// [`Resolve`] to fully work with a WIT package.
66///
67/// After an [`UnresolvedPackage`] is parsed it can be fully resolved with
68/// [`Resolve::push`]. During this operation a dependency map is specified which
69/// will connect the `foreign_deps` field of this structure to packages
70/// previously inserted within the [`Resolve`]. Embedders are responsible for
71/// performing this resolution themselves.
72#[derive(Clone)]
73pub struct UnresolvedPackage {
74    /// The namespace, name, and version information for this package.
75    pub name: PackageName,
76
77    /// All worlds from all documents within this package.
78    ///
79    /// Each world lists the document that it is from.
80    pub worlds: Arena<World>,
81
82    /// All interfaces from all documents within this package.
83    ///
84    /// Each interface lists the document that it is from. Interfaces are listed
85    /// in topological order as well so iteration through this arena will only
86    /// reference prior elements already visited when working with recursive
87    /// references.
88    pub interfaces: Arena<Interface>,
89
90    /// All types from all documents within this package.
91    ///
92    /// Each type lists the interface or world that defined it, or nothing if
93    /// it's an anonymous type. Types are listed in this arena in topological
94    /// order to ensure that iteration through this arena will only reference
95    /// other types transitively that are already iterated over.
96    pub types: Arena<TypeDef>,
97
98    /// All foreign dependencies that this package depends on.
99    ///
100    /// These foreign dependencies must be resolved to convert this unresolved
101    /// package into a `Resolve`. The map here is keyed by the name of the
102    /// foreign package that this depends on, and the sub-map is keyed by an
103    /// interface name followed by the identifier within `self.interfaces`. The
104    /// fields of `self.interfaces` describes the required types that are from
105    /// each foreign interface.
106    pub foreign_deps: IndexMap<PackageName, IndexMap<String, AstItem>>,
107
108    /// Doc comments for this package.
109    pub docs: Docs,
110
111    package_name_span: Span,
112    unknown_type_spans: Vec<Span>,
113    interface_spans: Vec<InterfaceSpan>,
114    world_spans: Vec<WorldSpan>,
115    type_spans: Vec<Span>,
116    foreign_dep_spans: Vec<Span>,
117    required_resource_types: Vec<(TypeId, Span)>,
118}
119
120/// Tracks a set of packages, all pulled from the same group of WIT source files.
121#[derive(Clone)]
122pub struct UnresolvedPackageGroup {
123    /// The "main" package in this package group which was found at the root of
124    /// the WIT files.
125    ///
126    /// Note that this is required to be present in all WIT files.
127    pub main: UnresolvedPackage,
128
129    /// Nested packages found while parsing `main`, if any.
130    pub nested: Vec<UnresolvedPackage>,
131
132    /// A set of processed source files from which these packages have been parsed.
133    pub source_map: SourceMap,
134}
135
136#[derive(Clone)]
137struct WorldSpan {
138    span: Span,
139    imports: Vec<Span>,
140    exports: Vec<Span>,
141    includes: Vec<Span>,
142}
143
144#[derive(Clone)]
145struct InterfaceSpan {
146    span: Span,
147    funcs: Vec<Span>,
148}
149
150#[derive(Debug, Copy, Clone)]
151#[cfg_attr(feature = "serde", derive(Serialize))]
152#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
153pub enum AstItem {
154    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
155    Interface(InterfaceId),
156    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
157    World(WorldId),
158}
159
160/// A structure used to keep track of the name of a package, containing optional
161/// information such as a namespace and version information.
162///
163/// This is directly encoded as an "ID" in the binary component representation
164/// with an interfaced tacked on as well.
165#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
166#[cfg_attr(feature = "serde", derive(Serialize))]
167#[cfg_attr(feature = "serde", serde(into = "String"))]
168pub struct PackageName {
169    /// A namespace such as `wasi` in `wasi:foo/bar`
170    pub namespace: String,
171    /// The kebab-name of this package, which is always specified.
172    pub name: String,
173    /// Optional major/minor version information.
174    pub version: Option<Version>,
175}
176
177impl From<PackageName> for String {
178    fn from(name: PackageName) -> String {
179        name.to_string()
180    }
181}
182
183impl PackageName {
184    /// Returns the ID that this package name would assign the `interface` name
185    /// specified.
186    pub fn interface_id(&self, interface: &str) -> String {
187        let mut s = String::new();
188        s.push_str(&format!("{}:{}/{interface}", self.namespace, self.name));
189        if let Some(version) = &self.version {
190            s.push_str(&format!("@{version}"));
191        }
192        s
193    }
194
195    /// Determines the "semver compatible track" for the given version.
196    ///
197    /// This method implements the logic from the component model where semver
198    /// versions can be compatible with one another. For example versions 1.2.0
199    /// and 1.2.1 would be considered both compatible with one another because
200    /// they're on the same semver compatible track.
201    ///
202    /// This predicate is used during
203    /// [`Resolve::merge_world_imports_based_on_semver`] for example to
204    /// determine whether two imports can be merged together. This is
205    /// additionally used when creating components to match up imports in
206    /// core wasm to imports in worlds.
207    pub fn version_compat_track(version: &Version) -> Version {
208        let mut version = version.clone();
209        version.build = semver::BuildMetadata::EMPTY;
210        if !version.pre.is_empty() {
211            return version;
212        }
213        if version.major != 0 {
214            version.minor = 0;
215            version.patch = 0;
216            return version;
217        }
218        if version.minor != 0 {
219            version.patch = 0;
220            return version;
221        }
222        version
223    }
224
225    /// Returns the string corresponding to
226    /// [`PackageName::version_compat_track`]. This is done to match the
227    /// component model's expected naming scheme of imports and exports.
228    pub fn version_compat_track_string(version: &Version) -> String {
229        let version = Self::version_compat_track(version);
230        if !version.pre.is_empty() {
231            return version.to_string();
232        }
233        if version.major != 0 {
234            return format!("{}", version.major);
235        }
236        if version.minor != 0 {
237            return format!("{}.{}", version.major, version.minor);
238        }
239        version.to_string()
240    }
241}
242
243impl fmt::Display for PackageName {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        write!(f, "{}:{}", self.namespace, self.name)?;
246        if let Some(version) = &self.version {
247            write!(f, "@{version}")?;
248        }
249        Ok(())
250    }
251}
252
253#[derive(Debug)]
254struct Error {
255    span: Span,
256    msg: String,
257    highlighted: Option<String>,
258}
259
260impl Error {
261    fn new(span: Span, msg: impl Into<String>) -> Error {
262        Error {
263            span,
264            msg: msg.into(),
265            highlighted: None,
266        }
267    }
268}
269
270impl fmt::Display for Error {
271    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272        self.highlighted.as_ref().unwrap_or(&self.msg).fmt(f)
273    }
274}
275
276impl std::error::Error for Error {}
277
278#[derive(Debug)]
279struct PackageNotFoundError {
280    span: Span,
281    requested: PackageName,
282    known: Vec<PackageName>,
283    highlighted: Option<String>,
284}
285
286impl PackageNotFoundError {
287    pub fn new(span: Span, requested: PackageName, known: Vec<PackageName>) -> Self {
288        Self {
289            span,
290            requested,
291            known,
292            highlighted: None,
293        }
294    }
295}
296
297impl fmt::Display for PackageNotFoundError {
298    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299        if let Some(highlighted) = &self.highlighted {
300            return highlighted.fmt(f);
301        }
302        if self.known.is_empty() {
303            write!(
304                f,
305                "package '{}' not found. no known packages.",
306                self.requested
307            )?;
308        } else {
309            write!(
310                f,
311                "package '{}' not found. known packages:\n",
312                self.requested
313            )?;
314            for known in self.known.iter() {
315                write!(f, "    {known}\n")?;
316            }
317        }
318        Ok(())
319    }
320}
321
322impl std::error::Error for PackageNotFoundError {}
323
324impl UnresolvedPackageGroup {
325    /// Parses the given string as a wit document.
326    ///
327    /// The `path` argument is used for error reporting. The `contents` provided
328    /// are considered to be the contents of `path`. This function does not read
329    /// the filesystem.
330    pub fn parse(path: impl AsRef<Path>, contents: &str) -> Result<UnresolvedPackageGroup> {
331        let mut map = SourceMap::default();
332        map.push(path.as_ref(), contents);
333        map.parse()
334    }
335
336    /// Parse a WIT package at the provided path.
337    ///
338    /// The path provided is inferred whether it's a file or a directory. A file
339    /// is parsed with [`UnresolvedPackageGroup::parse_file`] and a directory is
340    /// parsed with [`UnresolvedPackageGroup::parse_dir`].
341    pub fn parse_path(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
342        let path = path.as_ref();
343        if path.is_dir() {
344            UnresolvedPackageGroup::parse_dir(path)
345        } else {
346            UnresolvedPackageGroup::parse_file(path)
347        }
348    }
349
350    /// Parses a WIT package from the file provided.
351    ///
352    /// The return value represents all packages found in the WIT file which
353    /// might be either one or multiple depending on the syntax used.
354    pub fn parse_file(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
355        let path = path.as_ref();
356        let contents = std::fs::read_to_string(path)
357            .with_context(|| format!("failed to read file {path:?}"))?;
358        Self::parse(path, &contents)
359    }
360
361    /// Parses a WIT package from the directory provided.
362    ///
363    /// This method will look at all files under the `path` specified. All
364    /// `*.wit` files are parsed and assumed to be part of the same package
365    /// grouping. This is useful when a WIT package is split across multiple
366    /// files.
367    pub fn parse_dir(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
368        let path = path.as_ref();
369        let mut map = SourceMap::default();
370        let cx = || format!("failed to read directory {path:?}");
371        for entry in path.read_dir().with_context(&cx)? {
372            let entry = entry.with_context(&cx)?;
373            let path = entry.path();
374            let ty = entry.file_type().with_context(&cx)?;
375            if ty.is_dir() {
376                continue;
377            }
378            if ty.is_symlink() {
379                if path.is_dir() {
380                    continue;
381                }
382            }
383            let filename = match path.file_name().and_then(|s| s.to_str()) {
384                Some(name) => name,
385                None => continue,
386            };
387            if !filename.ends_with(".wit") {
388                continue;
389            }
390            map.push_file(&path)?;
391        }
392        map.parse()
393    }
394}
395
396#[derive(Debug, Clone)]
397#[cfg_attr(feature = "serde", derive(Serialize))]
398pub struct World {
399    /// The WIT identifier name of this world.
400    pub name: String,
401
402    /// All imported items into this interface, both worlds and functions.
403    pub imports: IndexMap<WorldKey, WorldItem>,
404
405    /// All exported items from this interface, both worlds and functions.
406    pub exports: IndexMap<WorldKey, WorldItem>,
407
408    /// The package that owns this world.
409    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
410    pub package: Option<PackageId>,
411
412    /// Documentation associated with this world declaration.
413    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
414    pub docs: Docs,
415
416    /// Stability annotation for this world itself.
417    #[cfg_attr(
418        feature = "serde",
419        serde(skip_serializing_if = "Stability::is_unknown")
420    )]
421    pub stability: Stability,
422
423    /// All the included worlds from this world. Empty if this is fully resolved
424    #[cfg_attr(feature = "serde", serde(skip))]
425    pub includes: Vec<(Stability, WorldId)>,
426
427    /// All the included worlds names. Empty if this is fully resolved
428    #[cfg_attr(feature = "serde", serde(skip))]
429    pub include_names: Vec<Vec<IncludeName>>,
430}
431
432#[derive(Debug, Clone)]
433pub struct IncludeName {
434    /// The name of the item
435    pub name: String,
436
437    /// The name to be replaced with
438    pub as_: String,
439}
440
441/// The key to the import/export maps of a world. Either a kebab-name or a
442/// unique interface.
443#[derive(Debug, Clone, Eq)]
444#[cfg_attr(feature = "serde", derive(Serialize))]
445#[cfg_attr(feature = "serde", serde(into = "String"))]
446pub enum WorldKey {
447    /// A kebab-name.
448    Name(String),
449    /// An interface which is assigned no kebab-name.
450    Interface(InterfaceId),
451}
452
453impl Hash for WorldKey {
454    fn hash<H: Hasher>(&self, hasher: &mut H) {
455        match self {
456            WorldKey::Name(s) => {
457                0u8.hash(hasher);
458                s.as_str().hash(hasher);
459            }
460            WorldKey::Interface(i) => {
461                1u8.hash(hasher);
462                i.hash(hasher);
463            }
464        }
465    }
466}
467
468impl PartialEq for WorldKey {
469    fn eq(&self, other: &WorldKey) -> bool {
470        match (self, other) {
471            (WorldKey::Name(a), WorldKey::Name(b)) => a.as_str() == b.as_str(),
472            (WorldKey::Name(_), _) => false,
473            (WorldKey::Interface(a), WorldKey::Interface(b)) => a == b,
474            (WorldKey::Interface(_), _) => false,
475        }
476    }
477}
478
479impl From<WorldKey> for String {
480    fn from(key: WorldKey) -> String {
481        match key {
482            WorldKey::Name(name) => name,
483            WorldKey::Interface(id) => format!("interface-{}", id.index()),
484        }
485    }
486}
487
488impl WorldKey {
489    /// Asserts that this is `WorldKey::Name` and returns the name.
490    #[track_caller]
491    pub fn unwrap_name(self) -> String {
492        match self {
493            WorldKey::Name(name) => name,
494            WorldKey::Interface(_) => panic!("expected a name, found interface"),
495        }
496    }
497}
498
499#[derive(Debug, Clone, PartialEq)]
500#[cfg_attr(feature = "serde", derive(Serialize))]
501#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
502pub enum WorldItem {
503    /// An interface is being imported or exported from a world, indicating that
504    /// it's a namespace of functions.
505    Interface {
506        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
507        id: InterfaceId,
508        #[cfg_attr(
509            feature = "serde",
510            serde(skip_serializing_if = "Stability::is_unknown")
511        )]
512        stability: Stability,
513    },
514
515    /// A function is being directly imported or exported from this world.
516    Function(Function),
517
518    /// A type is being exported from this world.
519    ///
520    /// Note that types are never imported into worlds at this time.
521    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
522    Type(TypeId),
523}
524
525impl WorldItem {
526    pub fn stability<'a>(&'a self, resolve: &'a Resolve) -> &'a Stability {
527        match self {
528            WorldItem::Interface { stability, .. } => stability,
529            WorldItem::Function(f) => &f.stability,
530            WorldItem::Type(id) => &resolve.types[*id].stability,
531        }
532    }
533}
534
535#[derive(Debug, Clone)]
536#[cfg_attr(feature = "serde", derive(Serialize))]
537pub struct Interface {
538    /// Optionally listed name of this interface.
539    ///
540    /// This is `None` for inline interfaces in worlds.
541    pub name: Option<String>,
542
543    /// Exported types from this interface.
544    ///
545    /// Export names are listed within the types themselves. Note that the
546    /// export name here matches the name listed in the `TypeDef`.
547    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id_map"))]
548    pub types: IndexMap<String, TypeId>,
549
550    /// Exported functions from this interface.
551    pub functions: IndexMap<String, Function>,
552
553    /// Documentation associated with this interface.
554    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
555    pub docs: Docs,
556
557    /// Stability attribute for this interface.
558    #[cfg_attr(
559        feature = "serde",
560        serde(skip_serializing_if = "Stability::is_unknown")
561    )]
562    pub stability: Stability,
563
564    /// The package that owns this interface.
565    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_optional_id"))]
566    pub package: Option<PackageId>,
567}
568
569#[derive(Debug, Clone, PartialEq)]
570#[cfg_attr(feature = "serde", derive(Serialize))]
571pub struct TypeDef {
572    pub name: Option<String>,
573    pub kind: TypeDefKind,
574    pub owner: TypeOwner,
575    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
576    pub docs: Docs,
577    /// Stability attribute for this type.
578    #[cfg_attr(
579        feature = "serde",
580        serde(skip_serializing_if = "Stability::is_unknown")
581    )]
582    pub stability: Stability,
583}
584
585#[derive(Debug, Clone, PartialEq, Hash, Eq)]
586#[cfg_attr(feature = "serde", derive(Serialize))]
587#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
588pub enum TypeDefKind {
589    Record(Record),
590    Resource,
591    Handle(Handle),
592    Flags(Flags),
593    Tuple(Tuple),
594    Variant(Variant),
595    Enum(Enum),
596    Option(Type),
597    Result(Result_),
598    List(Type),
599    FixedSizeList(Type, u32),
600    Future(Option<Type>),
601    Stream(Option<Type>),
602    Type(Type),
603
604    /// This represents a type of unknown structure imported from a foreign
605    /// interface.
606    ///
607    /// This variant is only used during the creation of `UnresolvedPackage` but
608    /// by the time a `Resolve` is created then this will not exist.
609    Unknown,
610}
611
612impl TypeDefKind {
613    pub fn as_str(&self) -> &'static str {
614        match self {
615            TypeDefKind::Record(_) => "record",
616            TypeDefKind::Resource => "resource",
617            TypeDefKind::Handle(handle) => match handle {
618                Handle::Own(_) => "own",
619                Handle::Borrow(_) => "borrow",
620            },
621            TypeDefKind::Flags(_) => "flags",
622            TypeDefKind::Tuple(_) => "tuple",
623            TypeDefKind::Variant(_) => "variant",
624            TypeDefKind::Enum(_) => "enum",
625            TypeDefKind::Option(_) => "option",
626            TypeDefKind::Result(_) => "result",
627            TypeDefKind::List(_) => "list",
628            TypeDefKind::FixedSizeList(..) => "fixed size list",
629            TypeDefKind::Future(_) => "future",
630            TypeDefKind::Stream(_) => "stream",
631            TypeDefKind::Type(_) => "type",
632            TypeDefKind::Unknown => "unknown",
633        }
634    }
635}
636
637#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
638#[cfg_attr(feature = "serde", derive(Serialize))]
639#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
640pub enum TypeOwner {
641    /// This type was defined within a `world` block.
642    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
643    World(WorldId),
644    /// This type was defined within an `interface` block.
645    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
646    Interface(InterfaceId),
647    /// This type wasn't inherently defined anywhere, such as a `list<T>`, which
648    /// doesn't need an owner.
649    #[cfg_attr(feature = "serde", serde(untagged, serialize_with = "serialize_none"))]
650    None,
651}
652
653#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
654#[cfg_attr(feature = "serde", derive(Serialize))]
655#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
656pub enum Handle {
657    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
658    Own(TypeId),
659    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
660    Borrow(TypeId),
661}
662
663#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
664pub enum Type {
665    Bool,
666    U8,
667    U16,
668    U32,
669    U64,
670    S8,
671    S16,
672    S32,
673    S64,
674    F32,
675    F64,
676    Char,
677    String,
678    ErrorContext,
679    Id(TypeId),
680}
681
682#[derive(Debug, Copy, Clone, Eq, PartialEq)]
683pub enum Int {
684    U8,
685    U16,
686    U32,
687    U64,
688}
689
690#[derive(Debug, Clone, PartialEq, Hash, Eq)]
691#[cfg_attr(feature = "serde", derive(Serialize))]
692pub struct Record {
693    pub fields: Vec<Field>,
694}
695
696#[derive(Debug, Clone, PartialEq, Hash, Eq)]
697#[cfg_attr(feature = "serde", derive(Serialize))]
698pub struct Field {
699    pub name: String,
700    #[cfg_attr(feature = "serde", serde(rename = "type"))]
701    pub ty: Type,
702    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
703    pub docs: Docs,
704}
705
706#[derive(Debug, Clone, PartialEq, Hash, Eq)]
707#[cfg_attr(feature = "serde", derive(Serialize))]
708pub struct Flags {
709    pub flags: Vec<Flag>,
710}
711
712#[derive(Debug, Clone, PartialEq, Hash, Eq)]
713#[cfg_attr(feature = "serde", derive(Serialize))]
714pub struct Flag {
715    pub name: String,
716    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
717    pub docs: Docs,
718}
719
720#[derive(Debug, Clone, PartialEq)]
721pub enum FlagsRepr {
722    U8,
723    U16,
724    U32(usize),
725}
726
727impl Flags {
728    pub fn repr(&self) -> FlagsRepr {
729        match self.flags.len() {
730            0 => FlagsRepr::U32(0),
731            n if n <= 8 => FlagsRepr::U8,
732            n if n <= 16 => FlagsRepr::U16,
733            n => FlagsRepr::U32(sizealign::align_to(n, 32) / 32),
734        }
735    }
736}
737
738impl FlagsRepr {
739    pub fn count(&self) -> usize {
740        match self {
741            FlagsRepr::U8 => 1,
742            FlagsRepr::U16 => 1,
743            FlagsRepr::U32(n) => *n,
744        }
745    }
746}
747
748#[derive(Debug, Clone, PartialEq, Hash, Eq)]
749#[cfg_attr(feature = "serde", derive(Serialize))]
750pub struct Tuple {
751    pub types: Vec<Type>,
752}
753
754#[derive(Debug, Clone, PartialEq, Hash, Eq)]
755#[cfg_attr(feature = "serde", derive(Serialize))]
756pub struct Variant {
757    pub cases: Vec<Case>,
758}
759
760#[derive(Debug, Clone, PartialEq, Hash, Eq)]
761#[cfg_attr(feature = "serde", derive(Serialize))]
762pub struct Case {
763    pub name: String,
764    #[cfg_attr(feature = "serde", serde(rename = "type"))]
765    pub ty: Option<Type>,
766    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
767    pub docs: Docs,
768}
769
770impl Variant {
771    pub fn tag(&self) -> Int {
772        discriminant_type(self.cases.len())
773    }
774}
775
776#[derive(Debug, Clone, PartialEq, Hash, Eq)]
777#[cfg_attr(feature = "serde", derive(Serialize))]
778pub struct Enum {
779    pub cases: Vec<EnumCase>,
780}
781
782#[derive(Debug, Clone, PartialEq, Hash, Eq)]
783#[cfg_attr(feature = "serde", derive(Serialize))]
784pub struct EnumCase {
785    pub name: String,
786    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
787    pub docs: Docs,
788}
789
790impl Enum {
791    pub fn tag(&self) -> Int {
792        discriminant_type(self.cases.len())
793    }
794}
795
796/// This corresponds to the `discriminant_type` function in the Canonical ABI.
797fn discriminant_type(num_cases: usize) -> Int {
798    match num_cases.checked_sub(1) {
799        None => Int::U8,
800        Some(n) if n <= u8::max_value() as usize => Int::U8,
801        Some(n) if n <= u16::max_value() as usize => Int::U16,
802        Some(n) if n <= u32::max_value() as usize => Int::U32,
803        _ => panic!("too many cases to fit in a repr"),
804    }
805}
806
807#[derive(Debug, Clone, PartialEq, Hash, Eq)]
808#[cfg_attr(feature = "serde", derive(Serialize))]
809pub struct Result_ {
810    pub ok: Option<Type>,
811    pub err: Option<Type>,
812}
813
814#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
815#[cfg_attr(feature = "serde", derive(Serialize))]
816pub struct Docs {
817    pub contents: Option<String>,
818}
819
820impl Docs {
821    pub fn is_empty(&self) -> bool {
822        self.contents.is_none()
823    }
824}
825
826#[derive(Debug, Clone, PartialEq, Eq)]
827#[cfg_attr(feature = "serde", derive(Serialize))]
828pub struct Function {
829    pub name: String,
830    pub kind: FunctionKind,
831    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_params"))]
832    pub params: Vec<(String, Type)>,
833    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
834    pub result: Option<Type>,
835    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Docs::is_empty"))]
836    pub docs: Docs,
837    /// Stability attribute for this function.
838    #[cfg_attr(
839        feature = "serde",
840        serde(skip_serializing_if = "Stability::is_unknown")
841    )]
842    pub stability: Stability,
843}
844
845#[derive(Debug, Clone, PartialEq, Eq)]
846#[cfg_attr(feature = "serde", derive(Serialize))]
847#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
848pub enum FunctionKind {
849    /// A freestanding function.
850    ///
851    /// ```wit
852    /// interface foo {
853    ///     the-func: func();
854    /// }
855    /// ```
856    Freestanding,
857
858    /// An async freestanding function.
859    ///
860    /// ```wit
861    /// interface foo {
862    ///     the-func: async func();
863    /// }
864    /// ```
865    AsyncFreestanding,
866
867    /// A resource method where the first parameter is implicitly
868    /// `borrow<T>`.
869    ///
870    /// ```wit
871    /// interface foo {
872    ///     resource r {
873    ///         the-func: func();
874    ///     }
875    /// }
876    /// ```
877    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
878    Method(TypeId),
879
880    /// An async resource method where the first parameter is implicitly
881    /// `borrow<T>`.
882    ///
883    /// ```wit
884    /// interface foo {
885    ///     resource r {
886    ///         the-func: async func();
887    ///     }
888    /// }
889    /// ```
890    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
891    AsyncMethod(TypeId),
892
893    /// A static resource method.
894    ///
895    /// ```wit
896    /// interface foo {
897    ///     resource r {
898    ///         the-func: static func();
899    ///     }
900    /// }
901    /// ```
902    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
903    Static(TypeId),
904
905    /// An async static resource method.
906    ///
907    /// ```wit
908    /// interface foo {
909    ///     resource r {
910    ///         the-func: static async func();
911    ///     }
912    /// }
913    /// ```
914    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
915    AsyncStatic(TypeId),
916
917    /// A resource constructor where the return value is implicitly `own<T>`.
918    ///
919    /// ```wit
920    /// interface foo {
921    ///     resource r {
922    ///         constructor();
923    ///     }
924    /// }
925    /// ```
926    #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
927    Constructor(TypeId),
928}
929
930impl FunctionKind {
931    /// Returns whether this is an async function or not.
932    pub fn is_async(&self) -> bool {
933        match self {
934            FunctionKind::Freestanding
935            | FunctionKind::Method(_)
936            | FunctionKind::Static(_)
937            | FunctionKind::Constructor(_) => false,
938            FunctionKind::AsyncFreestanding
939            | FunctionKind::AsyncMethod(_)
940            | FunctionKind::AsyncStatic(_) => true,
941        }
942    }
943
944    /// Returns the resource, if present, that this function kind refers to.
945    pub fn resource(&self) -> Option<TypeId> {
946        match self {
947            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
948            FunctionKind::Method(id)
949            | FunctionKind::Static(id)
950            | FunctionKind::Constructor(id)
951            | FunctionKind::AsyncMethod(id)
952            | FunctionKind::AsyncStatic(id) => Some(*id),
953        }
954    }
955
956    /// Returns the resource, if present, that this function kind refers to.
957    pub fn resource_mut(&mut self) -> Option<&mut TypeId> {
958        match self {
959            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => None,
960            FunctionKind::Method(id)
961            | FunctionKind::Static(id)
962            | FunctionKind::Constructor(id)
963            | FunctionKind::AsyncMethod(id)
964            | FunctionKind::AsyncStatic(id) => Some(id),
965        }
966    }
967}
968
969/// Possible forms of name mangling that are supported by this crate.
970#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
971pub enum Mangling {
972    /// The "standard" component model mangling format for 32-bit linear
973    /// memories. This is specified in WebAssembly/component-model#378
974    Standard32,
975
976    /// The "legacy" name mangling supported in versions 218-and-prior for this
977    /// crate. This is the original support for how components were created from
978    /// core wasm modules and this does not correspond to any standard. This is
979    /// preserved for now while tools transition to the new scheme.
980    Legacy,
981}
982
983impl std::str::FromStr for Mangling {
984    type Err = anyhow::Error;
985
986    fn from_str(s: &str) -> Result<Mangling> {
987        match s {
988            "legacy" => Ok(Mangling::Legacy),
989            "standard32" => Ok(Mangling::Standard32),
990            _ => {
991                bail!(
992                    "unknown name mangling `{s}`, \
993                     supported values are `legacy` or `standard32`"
994                )
995            }
996        }
997    }
998}
999
1000/// Possible lift/lower ABI choices supported when mangling names.
1001#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1002pub enum LiftLowerAbi {
1003    /// Both imports and exports will use the synchronous ABI.
1004    Sync,
1005
1006    /// Both imports and exports will use the async ABI (with a callback for
1007    /// each export).
1008    AsyncCallback,
1009
1010    /// Both imports and exports will use the async ABI (with no callbacks for
1011    /// exports).
1012    AsyncStackful,
1013}
1014
1015impl LiftLowerAbi {
1016    fn import_prefix(self) -> &'static str {
1017        match self {
1018            Self::Sync => "",
1019            Self::AsyncCallback | Self::AsyncStackful => "[async-lower]",
1020        }
1021    }
1022
1023    /// Get the import [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1024    pub fn import_variant(self) -> AbiVariant {
1025        match self {
1026            Self::Sync => AbiVariant::GuestImport,
1027            Self::AsyncCallback | Self::AsyncStackful => AbiVariant::GuestImportAsync,
1028        }
1029    }
1030
1031    fn export_prefix(self) -> &'static str {
1032        match self {
1033            Self::Sync => "",
1034            Self::AsyncCallback => "[async-lift]",
1035            Self::AsyncStackful => "[async-lift-stackful]",
1036        }
1037    }
1038
1039    /// Get the export [`AbiVariant`] corresponding to this [`LiftLowerAbi`]
1040    pub fn export_variant(self) -> AbiVariant {
1041        match self {
1042            Self::Sync => AbiVariant::GuestExport,
1043            Self::AsyncCallback => AbiVariant::GuestExportAsync,
1044            Self::AsyncStackful => AbiVariant::GuestExportAsyncStackful,
1045        }
1046    }
1047}
1048
1049/// Combination of [`Mangling`] and [`LiftLowerAbi`].
1050#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1051pub enum ManglingAndAbi {
1052    /// See [`Mangling::Standard32`].
1053    ///
1054    /// As of this writing, the standard name mangling only supports the
1055    /// synchronous ABI.
1056    Standard32,
1057
1058    /// See [`Mangling::Legacy`] and [`LiftLowerAbi`].
1059    Legacy(LiftLowerAbi),
1060}
1061
1062impl ManglingAndAbi {
1063    /// Get the import [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1064    pub fn import_variant(self) -> AbiVariant {
1065        match self {
1066            Self::Standard32 => AbiVariant::GuestImport,
1067            Self::Legacy(abi) => abi.import_variant(),
1068        }
1069    }
1070
1071    /// Get the export [`AbiVariant`] corresponding to this [`ManglingAndAbi`]
1072    pub fn export_variant(self) -> AbiVariant {
1073        match self {
1074            Self::Standard32 => AbiVariant::GuestExport,
1075            Self::Legacy(abi) => abi.export_variant(),
1076        }
1077    }
1078
1079    /// Switch the ABI to be sync if it's async.
1080    pub fn sync(self) -> Self {
1081        match self {
1082            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => self,
1083            Self::Legacy(LiftLowerAbi::AsyncCallback)
1084            | Self::Legacy(LiftLowerAbi::AsyncStackful) => Self::Legacy(LiftLowerAbi::Sync),
1085        }
1086    }
1087
1088    /// Returns whether this is an async ABI
1089    pub fn is_async(&self) -> bool {
1090        match self {
1091            Self::Standard32 | Self::Legacy(LiftLowerAbi::Sync) => false,
1092            Self::Legacy(LiftLowerAbi::AsyncCallback)
1093            | Self::Legacy(LiftLowerAbi::AsyncStackful) => true,
1094        }
1095    }
1096
1097    pub fn mangling(&self) -> Mangling {
1098        match self {
1099            Self::Standard32 => Mangling::Standard32,
1100            Self::Legacy(_) => Mangling::Legacy,
1101        }
1102    }
1103}
1104
1105impl Function {
1106    pub fn item_name(&self) -> &str {
1107        match &self.kind {
1108            FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => &self.name,
1109            FunctionKind::Method(_)
1110            | FunctionKind::Static(_)
1111            | FunctionKind::AsyncMethod(_)
1112            | FunctionKind::AsyncStatic(_) => &self.name[self.name.find('.').unwrap() + 1..],
1113            FunctionKind::Constructor(_) => "constructor",
1114        }
1115    }
1116
1117    /// Returns an iterator over the types used in parameters and results.
1118    ///
1119    /// Note that this iterator is not transitive, it only iterates over the
1120    /// direct references to types that this function has.
1121    pub fn parameter_and_result_types(&self) -> impl Iterator<Item = Type> + '_ {
1122        self.params.iter().map(|(_, t)| *t).chain(self.result)
1123    }
1124
1125    /// Gets the core export name for this function.
1126    pub fn standard32_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1127        self.core_export_name(interface, Mangling::Standard32)
1128    }
1129
1130    pub fn legacy_core_export_name<'a>(&'a self, interface: Option<&str>) -> Cow<'a, str> {
1131        self.core_export_name(interface, Mangling::Legacy)
1132    }
1133    /// Gets the core export name for this function.
1134    pub fn core_export_name<'a>(
1135        &'a self,
1136        interface: Option<&str>,
1137        mangling: Mangling,
1138    ) -> Cow<'a, str> {
1139        match interface {
1140            Some(interface) => match mangling {
1141                Mangling::Standard32 => Cow::Owned(format!("cm32p2|{interface}|{}", self.name)),
1142                Mangling::Legacy => Cow::Owned(format!("{interface}#{}", self.name)),
1143            },
1144            None => match mangling {
1145                Mangling::Standard32 => Cow::Owned(format!("cm32p2||{}", self.name)),
1146                Mangling::Legacy => Cow::Borrowed(&self.name),
1147            },
1148        }
1149    }
1150    /// Collect any future and stream types appearing in the signature of this
1151    /// function by doing a depth-first search over the parameter types and then
1152    /// the result types.
1153    ///
1154    /// For example, given the WIT function `foo: func(x: future<future<u32>>,
1155    /// y: u32) -> stream<u8>`, we would return `[future<u32>,
1156    /// future<future<u32>>, stream<u8>]`.
1157    ///
1158    /// This may be used by binding generators to refer to specific `future` and
1159    /// `stream` types when importing canonical built-ins such as `stream.new`,
1160    /// `future.read`, etc.  Using the example above, the import
1161    /// `[future-new-0]foo` would indicate a call to `future.new` for the type
1162    /// `future<u32>`.  Likewise, `[future-new-1]foo` would indicate a call to
1163    /// `future.new` for `future<future<u32>>`, and `[stream-new-2]foo` would
1164    /// indicate a call to `stream.new` for `stream<u8>`.
1165    pub fn find_futures_and_streams(&self, resolve: &Resolve) -> Vec<TypeId> {
1166        let mut results = Vec::new();
1167        for (_, ty) in self.params.iter() {
1168            find_futures_and_streams(resolve, *ty, &mut results);
1169        }
1170        if let Some(ty) = self.result {
1171            find_futures_and_streams(resolve, ty, &mut results);
1172        }
1173        results
1174    }
1175
1176    /// Check if this function is a resource constructor in shorthand form.
1177    /// I.e. without an explicit return type annotation.
1178    pub fn is_constructor_shorthand(&self, resolve: &Resolve) -> bool {
1179        let FunctionKind::Constructor(containing_resource_id) = self.kind else {
1180            return false;
1181        };
1182
1183        let Some(Type::Id(id)) = &self.result else {
1184            return false;
1185        };
1186
1187        let TypeDefKind::Handle(Handle::Own(returned_resource_id)) = resolve.types[*id].kind else {
1188            return false;
1189        };
1190
1191        return containing_resource_id == returned_resource_id;
1192    }
1193
1194    /// Returns the `module`, `name`, and signature to use when importing this
1195    /// function's `task.return` intrinsic using the `mangling` specified.
1196    pub fn task_return_import(
1197        &self,
1198        resolve: &Resolve,
1199        interface: Option<&WorldKey>,
1200        mangling: Mangling,
1201    ) -> (String, String, abi::WasmSignature) {
1202        match mangling {
1203            Mangling::Standard32 => todo!(),
1204            Mangling::Legacy => {}
1205        }
1206        // For exported async functions, generate a `task.return` intrinsic.
1207        let module = match interface {
1208            Some(key) => format!("[export]{}", resolve.name_world_key(key)),
1209            None => "[export]$root".to_string(),
1210        };
1211        let name = format!("[task-return]{}", self.name);
1212
1213        let mut func_tmp = self.clone();
1214        func_tmp.params = Vec::new();
1215        func_tmp.result = None;
1216        if let Some(ty) = self.result {
1217            func_tmp.params.push(("x".to_string(), ty));
1218        }
1219        let sig = resolve.wasm_signature(AbiVariant::GuestImport, &func_tmp);
1220        (module, name, sig)
1221    }
1222
1223    // push_imported_future_and_stream_intrinsics(wat, resolve, "[export]", interface, func);
1224}
1225
1226fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeId>) {
1227    let Type::Id(id) = ty else {
1228        return;
1229    };
1230
1231    match &resolve.types[id].kind {
1232        TypeDefKind::Resource
1233        | TypeDefKind::Handle(_)
1234        | TypeDefKind::Flags(_)
1235        | TypeDefKind::Enum(_) => {}
1236        TypeDefKind::Record(r) => {
1237            for Field { ty, .. } in &r.fields {
1238                find_futures_and_streams(resolve, *ty, results);
1239            }
1240        }
1241        TypeDefKind::Tuple(t) => {
1242            for ty in &t.types {
1243                find_futures_and_streams(resolve, *ty, results);
1244            }
1245        }
1246        TypeDefKind::Variant(v) => {
1247            for Case { ty, .. } in &v.cases {
1248                if let Some(ty) = ty {
1249                    find_futures_and_streams(resolve, *ty, results);
1250                }
1251            }
1252        }
1253        TypeDefKind::Option(ty)
1254        | TypeDefKind::List(ty)
1255        | TypeDefKind::FixedSizeList(ty, ..)
1256        | TypeDefKind::Type(ty) => {
1257            find_futures_and_streams(resolve, *ty, results);
1258        }
1259        TypeDefKind::Result(r) => {
1260            if let Some(ty) = r.ok {
1261                find_futures_and_streams(resolve, ty, results);
1262            }
1263            if let Some(ty) = r.err {
1264                find_futures_and_streams(resolve, ty, results);
1265            }
1266        }
1267        TypeDefKind::Future(ty) => {
1268            if let Some(ty) = ty {
1269                find_futures_and_streams(resolve, *ty, results);
1270            }
1271            results.push(id);
1272        }
1273        TypeDefKind::Stream(ty) => {
1274            if let Some(ty) = ty {
1275                find_futures_and_streams(resolve, *ty, results);
1276            }
1277            results.push(id);
1278        }
1279        TypeDefKind::Unknown => unreachable!(),
1280    }
1281}
1282
1283/// Representation of the stability attributes associated with a world,
1284/// interface, function, or type.
1285///
1286/// This is added for WebAssembly/component-model#332 where @since and @unstable
1287/// annotations were added to WIT.
1288///
1289/// The order of the of enum values is significant since it is used with Ord and PartialOrd
1290#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1291#[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
1292#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1293pub enum Stability {
1294    /// This item does not have either `@since` or `@unstable`.
1295    Unknown,
1296
1297    /// `@unstable(feature = foo)`
1298    ///
1299    /// This item is explicitly tagged `@unstable`. A feature name is listed and
1300    /// this item is excluded by default in `Resolve` unless explicitly enabled.
1301    Unstable {
1302        feature: String,
1303        #[cfg_attr(
1304            feature = "serde",
1305            serde(
1306                skip_serializing_if = "Option::is_none",
1307                default,
1308                serialize_with = "serialize_optional_version",
1309                deserialize_with = "deserialize_optional_version"
1310            )
1311        )]
1312        deprecated: Option<Version>,
1313    },
1314
1315    /// `@since(version = 1.2.3)`
1316    ///
1317    /// This item is explicitly tagged with `@since` as stable since the
1318    /// specified version.  This may optionally have a feature listed as well.
1319    Stable {
1320        #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_version"))]
1321        #[cfg_attr(feature = "serde", serde(deserialize_with = "deserialize_version"))]
1322        since: Version,
1323        #[cfg_attr(
1324            feature = "serde",
1325            serde(
1326                skip_serializing_if = "Option::is_none",
1327                default,
1328                serialize_with = "serialize_optional_version",
1329                deserialize_with = "deserialize_optional_version"
1330            )
1331        )]
1332        deprecated: Option<Version>,
1333    },
1334}
1335
1336impl Stability {
1337    /// Returns whether this is `Stability::Unknown`.
1338    pub fn is_unknown(&self) -> bool {
1339        matches!(self, Stability::Unknown)
1340    }
1341
1342    pub fn is_stable(&self) -> bool {
1343        matches!(self, Stability::Stable { .. })
1344    }
1345}
1346
1347impl Default for Stability {
1348    fn default() -> Stability {
1349        Stability::Unknown
1350    }
1351}
1352
1353#[cfg(test)]
1354mod test {
1355    use super::*;
1356
1357    #[test]
1358    fn test_discriminant_type() {
1359        assert_eq!(discriminant_type(1), Int::U8);
1360        assert_eq!(discriminant_type(0x100), Int::U8);
1361        assert_eq!(discriminant_type(0x101), Int::U16);
1362        assert_eq!(discriminant_type(0x10000), Int::U16);
1363        assert_eq!(discriminant_type(0x10001), Int::U32);
1364        if let Ok(num_cases) = usize::try_from(0x100000000_u64) {
1365            assert_eq!(discriminant_type(num_cases), Int::U32);
1366        }
1367    }
1368
1369    #[test]
1370    fn test_find_futures_and_streams() {
1371        let mut resolve = Resolve::default();
1372        let t0 = resolve.types.alloc(TypeDef {
1373            name: None,
1374            kind: TypeDefKind::Future(Some(Type::U32)),
1375            owner: TypeOwner::None,
1376            docs: Docs::default(),
1377            stability: Stability::Unknown,
1378        });
1379        let t1 = resolve.types.alloc(TypeDef {
1380            name: None,
1381            kind: TypeDefKind::Future(Some(Type::Id(t0))),
1382            owner: TypeOwner::None,
1383            docs: Docs::default(),
1384            stability: Stability::Unknown,
1385        });
1386        let t2 = resolve.types.alloc(TypeDef {
1387            name: None,
1388            kind: TypeDefKind::Stream(Some(Type::U32)),
1389            owner: TypeOwner::None,
1390            docs: Docs::default(),
1391            stability: Stability::Unknown,
1392        });
1393        let found = Function {
1394            name: "foo".into(),
1395            kind: FunctionKind::Freestanding,
1396            params: vec![("p1".into(), Type::Id(t1)), ("p2".into(), Type::U32)],
1397            result: Some(Type::Id(t2)),
1398            docs: Docs::default(),
1399            stability: Stability::Unknown,
1400        }
1401        .find_futures_and_streams(&resolve);
1402        assert_eq!(3, found.len());
1403        assert_eq!(t0, found[0]);
1404        assert_eq!(t1, found[1]);
1405        assert_eq!(t2, found[2]);
1406    }
1407}