Skip to content

Commit 34fbd2a

Browse files
authored
Fold resolve_world_from_name helper into select_world (#1611)
* Fold `resolve_world_from_name` helper into `select_world` This is a follow-up to #1577 to refactor a bit to have bindings generators continue to use `Resolve::select_world` for figuring out what to generate bindings for. * Review comments and API changes * Rename `Resolve::append` to `Resolve::push_group` * Add `Resolve::push_str` * Change `&Path` arguments to `impl AsRef<Path>` * Fix fuzzer build
1 parent 2a80d3d commit 34fbd2a

File tree

12 files changed

+317
-218
lines changed

12 files changed

+317
-218
lines changed

crates/wit-component/src/encoding.rs

+13-20
Original file line numberDiff line numberDiff line change
@@ -2129,39 +2129,32 @@ impl ComponentEncoder {
21292129

21302130
#[cfg(all(test, feature = "dummy-module"))]
21312131
mod test {
2132-
use crate::{dummy_module, embed_component_metadata};
2133-
21342132
use super::*;
2135-
use std::path::Path;
2136-
use wit_parser::UnresolvedPackageGroup;
2133+
use crate::{dummy_module, embed_component_metadata};
21372134

21382135
#[test]
21392136
fn it_renames_imports() {
21402137
let mut resolve = Resolve::new();
2141-
let UnresolvedPackageGroup {
2142-
mut packages,
2143-
source_map,
2144-
} = UnresolvedPackageGroup::parse(
2145-
Path::new("test.wit"),
2146-
r#"
2138+
let pkgs = resolve
2139+
.push_str(
2140+
"test.wit",
2141+
r#"
21472142
package test:wit;
21482143
21492144
interface i {
2150-
f: func();
2145+
f: func();
21512146
}
21522147
21532148
world test {
2154-
import i;
2155-
import foo: interface {
2156-
f: func();
2157-
}
2149+
import i;
2150+
import foo: interface {
2151+
f: func();
2152+
}
21582153
}
21592154
"#,
2160-
)
2161-
.unwrap();
2162-
let pkg = resolve.push(packages.remove(0), &source_map).unwrap();
2163-
2164-
let world = resolve.select_world(pkg, None).unwrap();
2155+
)
2156+
.unwrap();
2157+
let world = resolve.select_world(&pkgs, None).unwrap();
21652158

21662159
let mut module = dummy_module(&resolve, world);
21672160

crates/wit-component/src/lib.rs

+5-48
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
use std::str::FromStr;
66
use std::{borrow::Cow, fmt::Display};
77

8-
use anyhow::{bail, Context, Result};
8+
use anyhow::{bail, Result};
99
use wasm_encoder::{CanonicalOption, Encode, Section};
10-
use wit_parser::{parse_use_path, PackageId, ParsedUsePath, Resolve, WorldId};
10+
use wit_parser::{Resolve, WorldId};
1111

1212
mod encoding;
1313
mod gc;
@@ -79,43 +79,6 @@ impl From<StringEncoding> for wasm_encoder::CanonicalOption {
7979
}
8080
}
8181

82-
/// Handles world name resolution for cases when multiple packages may have been resolved. If this
83-
/// is the case, and we're dealing with input that contains a user-supplied world name (like via a
84-
/// CLI command, for instance), we want to ensure that the world name follows the following rules:
85-
///
86-
/// * If there is a single resolved package with a single world, the world name name MAY be
87-
/// omitted.
88-
/// * If there is a single resolved package with multiple worlds, the world name MUST be supplied,
89-
/// but MAY or MAY NOT be fully-qualified.
90-
/// * If there are multiple resolved packages, the world name MUST be fully-qualified.
91-
pub fn resolve_world_from_name(
92-
resolve: &Resolve,
93-
resolved_packages: Vec<PackageId>,
94-
world_name: Option<&str>,
95-
) -> Result<WorldId> {
96-
match resolved_packages.len() {
97-
0 => bail!("all of the supplied WIT source files were empty"),
98-
1 => resolve.select_world(resolved_packages[0], world_name.as_deref()),
99-
_ => match world_name.as_deref() {
100-
Some(name) => {
101-
let world_path = parse_use_path(name).with_context(|| {
102-
format!("failed to parse world specifier `{name}`")
103-
})?;
104-
match world_path {
105-
ParsedUsePath::Name(name) => bail!("the world specifier must be of the fully-qualified, id-based form (ex: \"wasi:http/proxy\" rather than \"proxy\"); you used {name}"),
106-
ParsedUsePath::Package(pkg_name, _) => {
107-
match resolve.package_names.get(&pkg_name) {
108-
Some(pkg_id) => resolve.select_world(pkg_id.clone(), world_name.as_deref()),
109-
None => bail!("the world specifier you provided named {pkg_name}, but no package with that name was found"),
110-
}
111-
}
112-
}
113-
}
114-
None => bail!("the supplied WIT source files describe multiple packages; please provide a fully-qualified world-specifier to the `embed` command"),
115-
},
116-
}
117-
}
118-
11982
/// A producer section to be added to all modules and components synthesized by
12083
/// this crate
12184
pub(crate) fn base_producers() -> wasm_metadata::Producers {
@@ -145,11 +108,9 @@ pub fn embed_component_metadata(
145108

146109
#[cfg(test)]
147110
mod tests {
148-
use std::path::Path;
149-
150111
use anyhow::Result;
151112
use wasmparser::Payload;
152-
use wit_parser::{Resolve, UnresolvedPackageGroup};
113+
use wit_parser::Resolve;
153114

154115
use super::{embed_component_metadata, StringEncoding};
155116

@@ -184,12 +145,8 @@ world test-world {}
184145

185146
// Parse pre-canned WIT to build resolver
186147
let mut resolver = Resolve::default();
187-
let UnresolvedPackageGroup {
188-
mut packages,
189-
source_map,
190-
} = UnresolvedPackageGroup::parse(&Path::new("in-code.wit"), COMPONENT_WIT)?;
191-
let pkg_id = resolver.push(packages.remove(0), &source_map)?;
192-
let world = resolver.select_world(pkg_id, Some("test-world").into())?;
148+
let pkgs = resolver.push_str("in-code.wit", COMPONENT_WIT)?;
149+
let world = resolver.select_world(&pkgs, Some("test-world"))?;
193150

194151
// Embed component metadata
195152
embed_component_metadata(&mut bytes, &resolver, world, StringEncoding::UTF8)?;

crates/wit-component/src/metadata.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
//! the three arguments originally passed to `encode`.
4343
4444
use crate::validation::BARE_FUNC_MODULE_NAME;
45-
use crate::{resolve_world_from_name, DecodedWasm, StringEncoding};
45+
use crate::{DecodedWasm, StringEncoding};
4646
use anyhow::{bail, Context, Result};
4747
use indexmap::IndexMap;
4848
use std::borrow::Cow;
@@ -264,7 +264,7 @@ impl Bindgen {
264264
DecodedWasm::Component(..) => bail!("expected encoded wit package(s)"),
265265
};
266266
resolve = r;
267-
world = resolve_world_from_name(&resolve, pkgs, Some(world_name.into()))?;
267+
world = resolve.select_world(&pkgs, Some(world_name.into()))?;
268268
}
269269

270270
// Current format where `data` is a wasm component itself.

crates/wit-component/tests/components.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ fn read_core_module(path: &Path, resolve: &Resolve, pkg: PackageId) -> Result<Ve
245245
let mut wasm = wat::parse_file(path)?;
246246
let name = path.file_stem().and_then(|s| s.to_str()).unwrap();
247247
let world = resolve
248-
.select_world(pkg, Some(name))
248+
.select_world(&[pkg], Some(name))
249249
.context("failed to select a world")?;
250250

251251
// Add this producer data to the wit-component metadata so we can make sure it gets through the

crates/wit-component/tests/interfaces.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn run_test(path: &Path, is_dir: bool) -> Result<()> {
5151
let packages = if is_dir {
5252
resolve.push_dir(path)?.0
5353
} else {
54-
resolve.append(UnresolvedPackageGroup::parse_file(path)?)?
54+
resolve.push_file(path)?
5555
};
5656

5757
for package in packages {
@@ -107,8 +107,7 @@ fn assert_print(resolve: &Resolve, pkg_ids: &[PackageId], path: &Path, is_dir: b
107107
assert_output(&expected, &output)?;
108108
}
109109

110-
UnresolvedPackageGroup::parse("foo.wit".as_ref(), &output)
111-
.context("failed to parse printed output")?;
110+
UnresolvedPackageGroup::parse("foo.wit", &output).context("failed to parse printed output")?;
112111
Ok(())
113112
}
114113

crates/wit-component/tests/linking.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use {
22
anyhow::{Context, Result},
3-
std::path::Path,
43
wit_component::StringEncoding,
5-
wit_parser::{Resolve, UnresolvedPackageGroup},
4+
wit_parser::Resolve,
65
};
76

87
const FOO: &str = r#"
@@ -141,12 +140,8 @@ fn encode(wat: &str, wit: Option<&str>) -> Result<Vec<u8>> {
141140

142141
if let Some(wit) = wit {
143142
let mut resolve = Resolve::default();
144-
let UnresolvedPackageGroup {
145-
mut packages,
146-
source_map,
147-
} = UnresolvedPackageGroup::parse(Path::new("wit"), wit)?;
148-
let pkg = resolve.push(packages.remove(0), &source_map)?;
149-
let world = resolve.select_world(pkg, None)?;
143+
let pkgs = resolve.push_str("test.wit", wit)?;
144+
let world = resolve.select_world(&pkgs, None)?;
150145

151146
wit_component::embed_component_metadata(
152147
&mut module,

crates/wit-component/tests/targets.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use anyhow::{bail, Context, Result};
1+
use anyhow::{Context, Result};
22
use std::{fs, path::Path};
3-
use wit_parser::{Resolve, UnresolvedPackageGroup, WorldId};
3+
use wit_parser::{Resolve, WorldId};
44

55
/// Tests whether a component targets a world.
66
///
@@ -22,7 +22,7 @@ use wit_parser::{Resolve, UnresolvedPackageGroup, WorldId};
2222
/// Run the test with the environment variable `BLESS` set to update `error.txt`.
2323
///
2424
/// Each test is effectively executing as:
25-
/// ```wasm-tools component targets -w foobar test.wit test.wat```
25+
/// `wasm-tools component targets -w foobar test.wit test.wat`
2626
#[test]
2727
fn targets() -> Result<()> {
2828
drop(env_logger::try_init());
@@ -79,23 +79,10 @@ fn load_test_wit(path: &Path) -> Result<(Resolve, WorldId)> {
7979
const TEST_TARGET_WORLD_ID: &str = "foobar";
8080

8181
let test_wit_path = path.join("test.wit");
82-
let UnresolvedPackageGroup {
83-
mut packages,
84-
source_map,
85-
} = UnresolvedPackageGroup::parse_file(&test_wit_path)
86-
.context("failed to parse WIT package")?;
87-
if packages.is_empty() {
88-
bail!("Files were completely empty - are you sure these are the files you're looking for?")
89-
}
90-
if packages.len() > 1 {
91-
bail!("Multi-package targeting tests are not yet supported.")
92-
}
93-
9482
let mut resolve = Resolve::default();
95-
let package_id = resolve.push(packages.remove(0), &source_map)?;
96-
83+
let pkgs = resolve.push_file(&test_wit_path)?;
9784
let world_id = resolve
98-
.select_world(package_id, Some(TEST_TARGET_WORLD_ID))
85+
.select_world(&pkgs, Some(TEST_TARGET_WORLD_ID))
9986
.with_context(|| "failed to select world from package".to_string())?;
10087

10188
Ok((resolve, world_id))

crates/wit-component/tests/wit.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ fn parse_wit_dir() -> Result<()> {
99
drop(env_logger::try_init());
1010

1111
let mut resolver = Resolve::default();
12-
let package_id = resolver.push_path("tests/wit/parse-dir/wit")?.0[0];
12+
let (package_ids, _) = resolver.push_path("tests/wit/parse-dir/wit")?;
1313
assert!(resolver
14-
.select_world(package_id, "foo-world".into())
14+
.select_world(&package_ids, "foo-world".into())
1515
.is_ok());
1616

1717
Ok(())
@@ -23,10 +23,8 @@ fn parse_wit_file() -> Result<()> {
2323
drop(env_logger::try_init());
2424

2525
let mut resolver = Resolve::default();
26-
let package_id = resolver
27-
.push_path("tests/wit/parse-dir/wit/deps/bar/bar.wit")?
28-
.0[0];
29-
resolver.select_world(package_id, "bar-world".into())?;
26+
let (package_ids, _) = resolver.push_path("tests/wit/parse-dir/wit/deps/bar/bar.wit")?;
27+
resolver.select_world(&package_ids, "bar-world".into())?;
3028
assert!(resolver
3129
.interfaces
3230
.iter()

crates/wit-parser/src/lib.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,11 @@ impl UnresolvedPackageGroup {
228228
/// Parses the given string as a wit document.
229229
///
230230
/// The `path` argument is used for error reporting. The `contents` provided
231-
/// will not be able to use `pkg` use paths to other documents.
232-
pub fn parse(path: &Path, contents: &str) -> Result<UnresolvedPackageGroup> {
231+
/// are considered to be the contents of `path`. This function does not read
232+
/// the filesystem.
233+
pub fn parse(path: impl AsRef<Path>, contents: &str) -> Result<UnresolvedPackageGroup> {
233234
let mut map = SourceMap::default();
234-
map.push(path, contents);
235+
map.push(path.as_ref(), contents);
235236
map.parse()
236237
}
237238

@@ -240,7 +241,8 @@ impl UnresolvedPackageGroup {
240241
/// The path provided is inferred whether it's a file or a directory. A file
241242
/// is parsed with [`UnresolvedPackageGroup::parse_file`] and a directory is
242243
/// parsed with [`UnresolvedPackageGroup::parse_dir`].
243-
pub fn parse_path(path: &Path) -> Result<UnresolvedPackageGroup> {
244+
pub fn parse_path(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
245+
let path = path.as_ref();
244246
if path.is_dir() {
245247
UnresolvedPackageGroup::parse_dir(path)
246248
} else {
@@ -250,19 +252,23 @@ impl UnresolvedPackageGroup {
250252

251253
/// Parses a WIT package from the file provided.
252254
///
253-
/// The WIT package returned will be a single-document package and will not
254-
/// be able to use `pkg` paths to other documents.
255-
pub fn parse_file(path: &Path) -> Result<UnresolvedPackageGroup> {
255+
/// The return value represents all packages found in the WIT file which
256+
/// might be either one or multiple depending on the syntax used.
257+
pub fn parse_file(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
258+
let path = path.as_ref();
256259
let contents = std::fs::read_to_string(path)
257260
.with_context(|| format!("failed to read file {path:?}"))?;
258261
Self::parse(path, &contents)
259262
}
260263

261264
/// Parses a WIT package from the directory provided.
262265
///
263-
/// All files with the extension `*.wit` or `*.wit.md` will be loaded from
264-
/// `path` into the returned package.
265-
pub fn parse_dir(path: &Path) -> Result<UnresolvedPackageGroup> {
266+
/// This method will look at all files under the `path` specified. All
267+
/// `*.wit` files are parsed and assumed to be part of the same package
268+
/// grouping. This is useful when a WIT package is split across multiple
269+
/// files.
270+
pub fn parse_dir(path: impl AsRef<Path>) -> Result<UnresolvedPackageGroup> {
271+
let path = path.as_ref();
266272
let mut map = SourceMap::default();
267273
let cx = || format!("failed to read directory {path:?}");
268274
for entry in path.read_dir().with_context(&cx)? {
@@ -281,7 +287,7 @@ impl UnresolvedPackageGroup {
281287
Some(name) => name,
282288
None => continue,
283289
};
284-
if !filename.ends_with(".wit") && !filename.ends_with(".wit.md") {
290+
if !filename.ends_with(".wit") {
285291
continue;
286292
}
287293
map.push_file(&path)?;

0 commit comments

Comments
 (0)