Skip to content

Commit 5846295

Browse files
authored
Merge branch 'bytecodealliance:main' into dev/timmy/wasi-http-header-bug
2 parents 04ebdb0 + e5c8ce6 commit 5846295

10 files changed

Lines changed: 262 additions & 59 deletions

File tree

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ jobs:
226226
- run: cargo build --target wasm32-wasip1 -p wit-bindgen --no-default-features --features async-spawn
227227
- run: cargo build --target wasm32-wasip1 -p wit-bindgen --no-default-features --features async,macros
228228
- run: cargo build --target wasm32-wasip1 -p wit-bindgen --no-default-features --features inter-task-wakeup
229+
- run: cargo build --target wasm32-wasip1 -p wit-bindgen --no-default-features --features futures-stream
229230

230231
# Verity that documentation can be generated for the rust bindings crate.
231232
- run: rustup update nightly --no-self-update

crates/go/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ The generated files will reference the following files in the [bytecodealliance/
4343
- defines an `Option` type as required by the WIT world
4444
- defines a `Result` type as required by the WIT world
4545
- defines a `Unit` type as required by the WIT world
46-
- defines a `StreamReader` and `StreamWriter` types as required by the WIT world
47-
- defines a `FutureReader` and `FutureWriter` types as required by the WIT world
46+
- defines `StreamReader` and `StreamWriter` types as required by the WIT world
47+
- defines `FutureReader` and `FutureWriter` types as required by the WIT world
4848
- `go.bytecodealliance.org/pkg/wit/async` (if needed): defines low-level functions for integrating the Go scheduler with the component model async ABI
4949

50-
5150
Note that async support currently requires [a patched version of
5251
Go](https://github.com/dicej/go/releases/tag/go1.25.5-wasi-on-idle). Code
5352
generated for worlds that don't use any async features can be compiled using a

crates/go/src/lib.rs

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,29 @@ pub struct Opts {
116116
#[cfg_attr(feature = "clap", clap(long))]
117117
pub pkg_name: Option<String>,
118118

119+
/// When `--pkg-name` is specified, optionally specify a different package
120+
/// for exports.
121+
///
122+
/// This allows you to put the exports and imports in separate packages when
123+
/// building a library. If only `--pkg-name` is specified, this will
124+
/// default to that value.
125+
#[cfg_attr(feature = "clap", clap(long, requires = "pkg_name"))]
126+
pub export_pkg_name: Option<String>,
127+
119128
/// Print the version of the remote package being used for the shared WIT types.
120129
///
121130
/// Must be specified in addition to the `pkg-name` flag.
122131
#[cfg_attr(feature = "clap", clap(long))]
123132
pub print_remote_pkg_version: bool,
133+
134+
/// When generating Go package names, include the WIT package version even
135+
/// if only one version of that package is referenced by the specified
136+
/// world.
137+
///
138+
/// By default, the version will only be included in the name if the world
139+
/// references more than one version of the WIT package.
140+
#[cfg_attr(feature = "clap", clap(long))]
141+
pub include_versions: bool,
124142
}
125143

126144
impl Opts {
@@ -210,8 +228,12 @@ struct Go {
210228

211229
impl Go {
212230
/// Adds the bindings module prefix to a package name.
213-
fn mod_pkg(&self, name: &str) -> String {
214-
let prefix = self.opts.pkg_name.as_deref().unwrap_or("wit_component");
231+
fn mod_pkg(&self, for_export: bool, name: &str) -> String {
232+
let prefix = for_export
233+
.then_some(())
234+
.and(self.opts.export_pkg_name.as_deref())
235+
.or(self.opts.pkg_name.as_deref())
236+
.unwrap_or("wit_component");
215237
format!(r#""{prefix}/{name}""#)
216238
}
217239

@@ -229,14 +251,14 @@ impl Go {
229251
if local == owner && (exported ^ in_import) {
230252
String::new()
231253
} else {
232-
let package = interface_name(resolve, owner);
254+
let package = self.interface_name(resolve, owner);
233255
let package = if exported {
234256
format!("export_{package}")
235257
} else {
236258
package
237259
};
238260
let prefix = format!("{package}.");
239-
imports.insert(self.mod_pkg(&package));
261+
imports.insert(self.mod_pkg(exported, &package));
240262
prefix
241263
}
242264
}
@@ -610,7 +632,7 @@ func Lift{upper_kind}{camel}(handle int32) *witTypes.{upper_kind}Reader[{payload
610632
} else {
611633
format!(
612634
"{}_",
613-
interface_name(
635+
self.interface_name(
614636
resolve,
615637
Some(
616638
&self
@@ -722,7 +744,7 @@ impl WorldGenerator for Go {
722744
data.extend(self.import(resolve, func, Some(name)));
723745
}
724746
self.interfaces
725-
.entry(interface_name(resolve, Some(name)))
747+
.entry(self.interface_name(resolve, Some(name)))
726748
.or_default()
727749
.extend(data);
728750

@@ -741,7 +763,7 @@ impl WorldGenerator for Go {
741763
data.extend(self.import(resolve, func, None));
742764
}
743765
self.interfaces
744-
.entry(interface_name(resolve, None))
766+
.entry(self.interface_name(resolve, None))
745767
.or_default()
746768
.extend(data);
747769
}
@@ -770,12 +792,13 @@ impl WorldGenerator for Go {
770792

771793
let data = generator.into();
772794

795+
let name = self.interface_name(resolve, Some(name));
773796
if exported {
774797
&mut self.export_interfaces
775798
} else {
776799
&mut self.interfaces
777800
}
778-
.entry(interface_name(resolve, Some(name)))
801+
.entry(name)
779802
.or_default()
780803
.extend(data);
781804
}
@@ -818,7 +841,7 @@ impl WorldGenerator for Go {
818841
}
819842
let data = generator.into();
820843
self.interfaces
821-
.entry(interface_name(resolve, None))
844+
.entry(self.interface_name(resolve, None))
822845
.or_default()
823846
.extend(data);
824847
}
@@ -883,16 +906,14 @@ impl WorldGenerator for Go {
883906
files.push(
884907
"go.mod",
885908
format!(
886-
r#"module {}
909+
r#"module wit_component
887910
888911
go 1.25
889912
890913
require (
891-
go.bytecodealliance.org/pkg {}
914+
go.bytecodealliance.org/pkg {REMOTE_PKG_VERSION}
892915
)
893916
"#,
894-
self.opts.pkg_name.as_deref().unwrap_or("wit_component"),
895-
REMOTE_PKG_VERSION,
896917
)
897918
.as_bytes(),
898919
);
@@ -1215,7 +1236,7 @@ func {camel}({go_params}) {go_results} {{
12151236
let sig = resolve.wasm_signature(variant, func);
12161237
let core_module_name = interface.map(|v| resolve.name_world_key(v));
12171238
let export_name = func.legacy_core_export_name(core_module_name.as_deref());
1218-
let name = func_name(resolve, interface, func);
1239+
let name = self.func_name(resolve, interface, func);
12191240

12201241
let params = sig
12211242
.params
@@ -1340,7 +1361,7 @@ func wasm_export_post_return_{name}(result {results}) {{
13401361
let results = self.func_results(resolve, func, interface, false, &mut imports);
13411362

13421363
self.export_interfaces
1343-
.entry(interface_name(resolve, interface))
1364+
.entry(self.interface_name(resolve, interface))
13441365
.or_default()
13451366
.extend(InterfaceData {
13461367
code: format!(
@@ -1459,12 +1480,13 @@ func wasm_export_{name}({params}) {results} {{
14591480
&func.name,
14601481
);
14611482

1483+
let name = self.interface_name(resolve, interface);
14621484
if in_import || !exported {
14631485
&mut self.interfaces
14641486
} else {
14651487
&mut self.export_interfaces
14661488
}
1467-
.entry(interface_name(resolve, interface))
1489+
.entry(name)
14681490
.or_default()
14691491
.extend(data);
14701492
}
@@ -1483,6 +1505,47 @@ func wasm_export_{name}({params}) {results} {{
14831505
}
14841506
})
14851507
}
1508+
1509+
fn interface_name(&self, resolve: &Resolve, interface: Option<&WorldKey>) -> String {
1510+
match interface {
1511+
Some(WorldKey::Name(name)) => name.to_snake_case(),
1512+
Some(WorldKey::Interface(id)) => {
1513+
let interface = &resolve.interfaces[*id];
1514+
let package = &resolve.packages[interface.package.unwrap()];
1515+
let package_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
1516+
p.name.namespace == package.name.namespace
1517+
&& p.name.name == package.name.name
1518+
&& p.name.version != package.name.version
1519+
});
1520+
let version = if package_has_multiple_versions || self.opts.include_versions {
1521+
if let Some(version) = &package.name.version {
1522+
format!("{}_", version.to_string().replace(['.', '-', '+'], "_"))
1523+
} else {
1524+
String::new()
1525+
}
1526+
} else {
1527+
String::new()
1528+
};
1529+
let namespace = package.name.namespace.to_snake_case();
1530+
let package = package.name.name.to_snake_case();
1531+
let interface = interface.name.as_ref().unwrap().to_snake_case();
1532+
format!("{namespace}_{package}_{version}{interface}")
1533+
}
1534+
None => "wit_world".into(),
1535+
}
1536+
}
1537+
1538+
fn func_name(
1539+
&self,
1540+
resolve: &Resolve,
1541+
interface: Option<&WorldKey>,
1542+
func: &Function,
1543+
) -> String {
1544+
let prefix = self.interface_name(resolve, interface);
1545+
let name = func.name.to_snake_case().replace('.', "_");
1546+
1547+
format!("{prefix}_{name}")
1548+
}
14861549
}
14871550

14881551
struct FunctionGenerator<'a> {
@@ -1772,13 +1835,16 @@ for index := 0; index < int({length}); index++ {{
17721835
}
17731836

17741837
let name = func.item_name().to_upper_camel_case();
1775-
let package = format!("export_{}", interface_name(resolve, self.interface));
1838+
let package = format!(
1839+
"export_{}",
1840+
self.generator.interface_name(resolve, self.interface)
1841+
);
17761842

17771843
let call = match &func.kind {
17781844
FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
17791845
let args = operands.join(", ");
17801846
let call = format!("{package}.{name}({args})");
1781-
self.imports.insert(self.generator.mod_pkg(&package));
1847+
self.imports.insert(self.generator.mod_pkg(true, &package));
17821848
call
17831849
}
17841850
FunctionKind::Constructor(ty) => {
@@ -1789,7 +1855,7 @@ for index := 0; index < int({length}); index++ {{
17891855
.unwrap()
17901856
.to_upper_camel_case();
17911857
let call = format!("{package}.Make{ty}({args})");
1792-
self.imports.insert(self.generator.mod_pkg(&package));
1858+
self.imports.insert(self.generator.mod_pkg(true, &package));
17931859
call
17941860
}
17951861
FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
@@ -2934,42 +3000,6 @@ const (
29343000
}
29353001
}
29363002

2937-
fn interface_name(resolve: &Resolve, interface: Option<&WorldKey>) -> String {
2938-
match interface {
2939-
Some(WorldKey::Name(name)) => name.to_snake_case(),
2940-
Some(WorldKey::Interface(id)) => {
2941-
let interface = &resolve.interfaces[*id];
2942-
let package = &resolve.packages[interface.package.unwrap()];
2943-
let package_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
2944-
p.name.namespace == package.name.namespace
2945-
&& p.name.name == package.name.name
2946-
&& p.name.version != package.name.version
2947-
});
2948-
let version = if package_has_multiple_versions {
2949-
if let Some(version) = &package.name.version {
2950-
format!("{}_", version.to_string().replace(['.', '-', '+'], "_"))
2951-
} else {
2952-
String::new()
2953-
}
2954-
} else {
2955-
String::new()
2956-
};
2957-
let namespace = package.name.namespace.to_snake_case();
2958-
let package = package.name.name.to_snake_case();
2959-
let interface = interface.name.as_ref().unwrap().to_snake_case();
2960-
format!("{namespace}_{package}_{version}{interface}")
2961-
}
2962-
None => "wit_world".into(),
2963-
}
2964-
}
2965-
2966-
fn func_name(resolve: &Resolve, interface: Option<&WorldKey>, func: &Function) -> String {
2967-
let prefix = interface_name(resolve, interface);
2968-
let name = func.name.to_snake_case().replace('.', "_");
2969-
2970-
format!("{prefix}_{name}")
2971-
}
2972-
29733003
fn wasm_type(ty: WasmType) -> &'static str {
29743004
match ty {
29753005
WasmType::I32 => "int32",

crates/guest-rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ std = []
3535
async = ["std", "wit-bindgen-rust-macro?/async"]
3636
bitflags = ["dep:bitflags"]
3737
async-spawn = ['async', 'dep:futures']
38+
futures-stream = ['async', 'dep:futures']
3839
macro-string = ["wit-bindgen-rust-macro?/macro-string"]
3940

4041
# Unstable feature to support being a libstd dependency

crates/guest-rust/src/rt/async_support.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ mod abi_buffer;
6161
mod cabi;
6262
mod error_context;
6363
mod future_support;
64+
#[cfg(feature = "futures-stream")]
65+
mod futures_stream;
6466
#[cfg(feature = "inter-task-wakeup")]
6567
mod inter_task_wakeup;
6668
mod stream_support;
@@ -79,6 +81,8 @@ use self::waitable_set::WaitableSet;
7981
pub use abi_buffer::*;
8082
pub use error_context::*;
8183
pub use future_support::*;
84+
#[cfg(feature = "futures-stream")]
85+
pub use futures_stream::*;
8286
pub use stream_support::*;
8387
#[doc(hidden)]
8488
pub use subtask::Subtask;

0 commit comments

Comments
 (0)