pub struct Resolve {
pub worlds: Arena<World>,
pub interfaces: Arena<Interface>,
pub types: Arena<TypeDef>,
pub packages: Arena<Package>,
pub package_names: IndexMap<PackageName, PackageId>,
pub features: IndexSet<String>,
pub all_features: bool,
}
Expand description
Representation of a fully resolved set of WIT packages.
This structure contains a graph of WIT packages and all of their contents
merged together into the contained arenas. All items are sorted
topologically and everything here is fully resolved, so with a Resolve
no
name lookups are necessary and instead everything is index-based.
Working with a WIT package requires inserting it into a Resolve
to ensure
that all of its dependencies are satisfied. This will give the full picture
of that package’s types and such.
Each item in a Resolve
has a parent link to trace it back to the original
package as necessary.
Fields§
§worlds: Arena<World>
All known worlds within this Resolve
.
Each world points at a PackageId
which is stored below. No ordering is
guaranteed between this list of worlds.
interfaces: Arena<Interface>
All known interfaces within this Resolve
.
Each interface points at a PackageId
which is stored below. No
ordering is guaranteed between this list of interfaces.
types: Arena<TypeDef>
All known types within this Resolve
.
Types are topologically sorted such that any type referenced from one type is guaranteed to be defined previously. Otherwise though these are not sorted by interface for example.
packages: Arena<Package>
All known packages within this Resolve
.
This list of packages is not sorted. Sorted packages can be queried
through Resolve::topological_packages
.
package_names: IndexMap<PackageName, PackageId>
A map of package names to the ID of the package with that name.
features: IndexSet<String>
Activated features for this Resolve
.
This set of features is empty by default. This is consulted for
@unstable
annotations in loaded WIT documents. Any items with
@unstable
are filtered out unless their feature is present within this
set.
all_features: bool
Activate all features for this Resolve
.
Implementations§
Source§impl Resolve
impl Resolve
Sourcepub fn wasm_signature(
&self,
variant: AbiVariant,
func: &Function,
) -> WasmSignature
pub fn wasm_signature( &self, variant: AbiVariant, func: &Function, ) -> WasmSignature
Get the WebAssembly type signature for this interface function
The first entry returned is the list of parameters and the second entry is the list of results for the wasm function signature.
Source§impl Resolve
impl Resolve
Sourcepub fn push_path(
&mut self,
path: impl AsRef<Path>,
) -> Result<(PackageId, PackageSourceMap)>
pub fn push_path( &mut self, path: impl AsRef<Path>, ) -> Result<(PackageId, PackageSourceMap)>
Parse WIT packages from the input path
.
The input path
can be one of:
- A directory containing a WIT package with an optional
deps
directory for any dependent WIT packages it references. - A single standalone WIT file.
- A wasm-encoded WIT package as a single file in the wasm binary format.
- A wasm-encoded WIT package as a single file in the wasm text format.
In all of these cases packages are allowed to depend on previously
inserted packages into this Resolve
. Resolution for packages is based
on the name of each package and reference.
This method returns a PackageId
and additionally a PackageSourceMap
.
The PackageId
represent the main package that was parsed. For example if a single WIT
file was specified this will be the main package found in the file. For a directory this
will be all the main package in the directory itself. The PackageId
value is useful
to pass to Resolve::select_world
to take a user-specified world in a
conventional fashion and select which to use for bindings generation.
The returned PackageSourceMap
contains all the sources used during this operation.
This can be useful for systems that want to rebuild or regenerate bindings based on files modified,
or for ones which like to identify the used files for a package.
More information can also be found at Resolve::push_dir
and
Resolve::push_file
.
Sourcepub fn push_dir(
&mut self,
path: impl AsRef<Path>,
) -> Result<(PackageId, PackageSourceMap)>
pub fn push_dir( &mut self, path: impl AsRef<Path>, ) -> Result<(PackageId, PackageSourceMap)>
Parses the filesystem directory at path
as a WIT package and returns
a fully resolved PackageId
list as a result.
The directory itself is parsed with UnresolvedPackageGroup::parse_dir
and then all packages found are inserted into this Resolve
. The path
specified may have a deps
subdirectory which is probed automatically
for any other WIT dependencies.
The deps
folder may contain:
$path/deps/my-package/*.wit
- a directory that may contain multiple WIT files. This is parsed withUnresolvedPackageGroup::parse_dir
and then inserted into thisResolve
. Note that cannot recursively contain adeps
directory.$path/deps/my-package.wit
- a single-file WIT package. This is parsed withResolve::push_file
and then added toself
for name resolution.$path/deps/my-package.{wasm,wat}
- a wasm-encoded WIT package either in the text for binary format.
In all cases entries in the deps
folder are added to self
first
before adding files found in path
itself. All WIT packages found are
candidates for name-based resolution that other packages may use.
This function returns a tuple of two values. The first value is a
PackageId
, which represents the main WIT package found within
path
. This argument is useful for passing to Resolve::select_world
for choosing something to bindgen with.
The second value returned is a PackageSourceMap
, which contains all the sources
that were parsed during resolving. This can be useful for:
- build systems that want to rebuild bindings whenever one of the files changed
- or other tools, which want to identify the sources for the resolved packages
Sourcepub fn push_file(&mut self, path: impl AsRef<Path>) -> Result<PackageId>
pub fn push_file(&mut self, path: impl AsRef<Path>) -> Result<PackageId>
Parses the contents of path
from the filesystem and pushes the result
into this Resolve
.
The path
referenced here can be one of:
- A WIT file. Note that in this case this single WIT file will be the
entire package and any dependencies it has must already be in
self
. - A WIT package encoded as WebAssembly, either in text or binary form.
In this the package and all of its dependencies are automatically
inserted into
self
.
In both situations the PackageId
s of the resulting resolved packages
are returned from this method. The return value is mostly useful in
conjunction with Resolve::select_world
.
Sourcepub fn push(
&mut self,
unresolved: UnresolvedPackage,
source_map: &SourceMap,
) -> Result<PackageId>
pub fn push( &mut self, unresolved: UnresolvedPackage, source_map: &SourceMap, ) -> Result<PackageId>
Appends a new UnresolvedPackage
to this Resolve
, creating a
fully resolved package with no dangling references.
All the dependencies of unresolved
must already have been loaded
within this Resolve
via previous calls to push
or other methods such
as Resolve::push_path
.
Any dependency resolution error or otherwise world-elaboration error will be returned here, if successful a package identifier is returned which corresponds to the package that was just inserted.
Sourcepub fn push_group(
&mut self,
unresolved_group: UnresolvedPackageGroup,
) -> Result<PackageId>
pub fn push_group( &mut self, unresolved_group: UnresolvedPackageGroup, ) -> Result<PackageId>
Appends new UnresolvedPackageGroup
to this Resolve
, creating a
fully resolved package with no dangling references.
Any dependency resolution error or otherwise world-elaboration error will be returned here, if successful a package identifier is returned which corresponds to the package that was just inserted.
The returned PackageId
s are listed in topologically sorted order.
Sourcepub fn push_str(
&mut self,
path: impl AsRef<Path>,
contents: &str,
) -> Result<PackageId>
pub fn push_str( &mut self, path: impl AsRef<Path>, contents: &str, ) -> Result<PackageId>
Convenience method for combining UnresolvedPackageGroup::parse
and
Resolve::push_group
.
The path
provided is used for error messages but otherwise is not
read. This method does not touch the filesystem. The contents
provided
are the contents of a WIT package.
pub fn all_bits_valid(&self, ty: &Type) -> bool
Sourcepub fn merge(&mut self, resolve: Resolve) -> Result<Remap>
pub fn merge(&mut self, resolve: Resolve) -> Result<Remap>
Merges all the contents of a different Resolve
into this one. The
Remap
structure returned provides a mapping from all old indices to
new indices
This operation can fail if resolve
disagrees with self
about the
packages being inserted. Otherwise though this will additionally attempt
to “union” packages found in resolve
with those found in self
.
Unioning packages is keyed on the name/url of packages for those with
URLs present. If found then it’s assumed that both Resolve
instances
were originally created from the same contents and are two views
of the same package.
Sourcepub fn merge_worlds(&mut self, from: WorldId, into: WorldId) -> Result<()>
pub fn merge_worlds(&mut self, from: WorldId, into: WorldId) -> Result<()>
Merges the world from
into the world into
.
This will attempt to merge one world into another, unioning all of its
imports and exports together. This is an operation performed by
wit-component
, for example where two different worlds from two
different libraries were linked into the same core wasm file and are
producing a singular world that will be the final component’s
interface.
This operation can fail if the imports/exports overlap.
Sourcepub fn id_of(&self, interface: InterfaceId) -> Option<String>
pub fn id_of(&self, interface: InterfaceId) -> Option<String>
Returns the ID of the specified interface
.
Returns None
for unnamed interfaces.
Sourcepub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String>
pub fn canonicalized_id_of(&self, interface: InterfaceId) -> Option<String>
Returns the “canonicalized interface name” of interface
.
Returns None
for unnamed interfaces. See BuildTargets.md
in the
upstream component model repository for more information about this.
Sourcepub fn importize(
&mut self,
world_id: WorldId,
out_world_name: Option<String>,
) -> Result<()>
pub fn importize( &mut self, world_id: WorldId, out_world_name: Option<String>, ) -> Result<()>
Convert a world to an “importized” version where the world is updated in-place to reflect what it would look like to be imported.
This is a transformation which is used as part of the process of
importing a component today. For example when a component depends on
another component this is useful for generating WIT which can be use to
represent the component being imported. The general idea is that this
function will update the world_id
specified such it imports the
functionality that it previously exported. The world will be left with
no exports.
This world is then suitable for merging into other worlds or generating bindings in a context that is importing the original world. This is intended to be used as part of language tooling when depending on other components.
Sourcepub fn id_of_name(&self, pkg: PackageId, name: &str) -> String
pub fn id_of_name(&self, pkg: PackageId, name: &str) -> String
Returns the ID of the specified name
within the pkg
.
Sourcepub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String
pub fn canonicalized_id_of_name(&self, pkg: PackageId, name: &str) -> String
Returns the “canonicalized interface name” of the specified name
within the pkg
.
See BuildTargets.md
in the upstream component model repository for
more information about this.
Sourcepub fn select_world(
&self,
main_packages: &[PackageId],
world: Option<&str>,
) -> Result<WorldId>
pub fn select_world( &self, main_packages: &[PackageId], world: Option<&str>, ) -> Result<WorldId>
Selects a world from among the packages in a Resolve
.
A Resolve
may have many packages, each with many worlds. Many WIT
tools need a specific world to operate on. This function choses a
world, failing if the choice is ambiguous.
main_packages
provides the package IDs returned by
push_path
, push_dir
,
push_file
, push_group
,
and push_str
, which are the “main packages”,
as distinguished from any packages nested inside them.
world
is a world name such as from a --world
command-line option or
a world:
macro parameter. world
can be:
-
A kebab-name of a world, for example
"the-world"
. It is resolved within the “main package”, if there is exactly one. -
An ID-based form of a world, for example
"wasi:http/proxy"
. Note that a version does not need to be specified in this string if there’s only one package of the same name and it has a version. In this situation the version can be omitted. -
None
. If there’s exactly one “main package” and it contains exactly one world, that world is chosen.
If successful, the chosen WorldId
is returned.
§Examples
use anyhow::Result;
use wit_parser::Resolve;
fn main() -> Result<()> {
let mut resolve = Resolve::default();
// If there's a single package and only one world, that world is
// the obvious choice.
let wit1 = resolve.push_str(
"./my-test.wit",
r#"
package example:wit1;
world foo {
// ...
}
"#,
)?;
assert!(resolve.select_world(&[wit1], None).is_ok());
// If there are multiple packages, we need to be told which package
// to use, either by a "main package" or by a fully-qualified name.
let wit2 = resolve.push_str(
"./my-test.wit",
r#"
package example:wit2;
world foo { /* ... */ }
"#,
)?;
assert!(resolve.select_world(&[wit1, wit2], None).is_err());
assert!(resolve.select_world(&[wit1, wit2], Some("foo")).is_err());
// Fix: use fully-qualified names.
assert!(resolve.select_world(&[wit1, wit2], Some("example:wit1/foo")).is_ok());
assert!(resolve.select_world(&[wit1, wit2], Some("example:wit2/foo")).is_ok());
// If a package has multiple worlds, then we can't guess the world
// even if we know the package.
let wit3 = resolve.push_str(
"./my-test.wit",
r#"
package example:wit3;
world foo { /* ... */ }
world bar { /* ... */ }
"#,
)?;
assert!(resolve.select_world(&[wit3], None).is_err());
// Fix: pick between "foo" and "bar" here.
assert!(resolve.select_world(&[wit3], Some("foo")).is_ok());
// When selecting with a version it's ok to drop the version when
// there's only a single copy of that package in `Resolve`.
let wit5_1 = resolve.push_str(
"./my-test.wit",
r#"
package example:wit5@1.0.0;
world foo { /* ... */ }
"#,
)?;
assert!(resolve.select_world(&[wit5_1], Some("foo")).is_ok());
assert!(resolve.select_world(&[wit5_1], Some("example:wit5/foo")).is_ok());
// However when a single package has multiple versions in a resolve
// it's required to specify the version to select which one.
let wit5_2 = resolve.push_str(
"./my-test.wit",
r#"
package example:wit5@2.0.0;
world foo { /* ... */ }
"#,
)?;
assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo")).is_err());
// Fix: Pass explicit versions.
assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@1.0.0")).is_ok());
assert!(resolve.select_world(&[wit5_1, wit5_2], Some("example:wit5/foo@2.0.0")).is_ok());
Ok(())
}
Sourcepub fn name_world_key(&self, key: &WorldKey) -> String
pub fn name_world_key(&self, key: &WorldKey) -> String
Assigns a human readable name to the WorldKey
specified.
Sourcepub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String
pub fn name_canonicalized_world_key(&self, key: &WorldKey) -> String
Same as Resolve::name_world_key
except that WorldKey::Interfaces
uses Resolve::canonicalized_id_of
.
Sourcepub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId>
pub fn type_interface_dep(&self, id: TypeId) -> Option<InterfaceId>
Returns the interface that id
uses a type from, if it uses a type from
a different interface than id
is defined within.
If id
is not a use-of-a-type or it’s using a type in the same
interface then None
is returned.
Sourcepub fn interface_direct_deps(
&self,
id: InterfaceId,
) -> impl Iterator<Item = InterfaceId> + '_
pub fn interface_direct_deps( &self, id: InterfaceId, ) -> impl Iterator<Item = InterfaceId> + '_
Returns an iterator of all interfaces that the interface id
depends
on.
Interfaces may depend on others for type information to resolve type imports.
Note that the returned iterator may yield the same interface as a
dependency multiple times. Additionally only direct dependencies of id
are yielded, not transitive dependencies.
Sourcepub fn package_direct_deps(
&self,
id: PackageId,
) -> impl Iterator<Item = PackageId> + '_
pub fn package_direct_deps( &self, id: PackageId, ) -> impl Iterator<Item = PackageId> + '_
Returns an iterator of all packages that the package id
depends
on.
Packages may depend on others for type information to resolve type imports or interfaces to resolve worlds.
Note that the returned iterator may yield the same package as a
dependency multiple times. Additionally only direct dependencies of id
are yielded, not transitive dependencies.
Sourcepub fn topological_packages(&self) -> Vec<PackageId> ⓘ
pub fn topological_packages(&self) -> Vec<PackageId> ⓘ
Returns a topological ordering of packages contained in this Resolve
.
This returns a list of PackageId
such that when visited in order it’s
guaranteed that all dependencies will have been defined by prior items
in the list.
Sourcepub fn merge_world_imports_based_on_semver(
&mut self,
world_id: WorldId,
) -> Result<()>
pub fn merge_world_imports_based_on_semver( &mut self, world_id: WorldId, ) -> Result<()>
Remove duplicate imports from a world if they import from the same interface with semver-compatible versions.
This will merge duplicate interfaces present at multiple versions in both a world by selecting the larger version of the two interfaces. This requires that the interfaces are indeed semver-compatible and it means that some imports might be removed and replaced. Note that this is only done within a single semver track, for example the world imports 0.2.0 and 0.2.1 then the result afterwards will be that it imports 0.2.1. If, however, 0.3.0 where imported then the final result would import both 0.2.0 and 0.3.0.
Sourcepub fn wasm_import_name(
&self,
mangling: ManglingAndAbi,
import: WasmImport<'_>,
) -> (String, String)
pub fn wasm_import_name( &self, mangling: ManglingAndAbi, import: WasmImport<'_>, ) -> (String, String)
Returns the core wasm module/field names for the specified import
.
This function will return the core wasm module/field that can be used to
use import
with the name mangling
scheme specified as well. This can
be useful for bindings generators, for example, and these names are
recognized by wit-component
and wasm-tools component new
.
Sourcepub fn wasm_export_name(
&self,
mangling: ManglingAndAbi,
export: WasmExport<'_>,
) -> String
pub fn wasm_export_name( &self, mangling: ManglingAndAbi, export: WasmExport<'_>, ) -> String
Returns the core wasm export name for the specified export
.
This is the same as Resolve::wasm_import_name
, except for exports.