Skip to content

Commit 4e2dcd4

Browse files
authored
Rust: add option for path to wit-bindgen runtime. (#619)
* Rust: add option for path to wit-bindgen runtime. This change adds an optional path to the `wit-bindgen` runtime to use for Rust code generation. This will allow a different crate from `wit-bindgen` to generate bindings while also re-exporting `wit-bindgen::rt` at a known path for the generated code to use. * Rust: add `runtime_path` macro option and a test.
1 parent cce4af4 commit 4e2dcd4

File tree

5 files changed

+95
-30
lines changed

5 files changed

+95
-30
lines changed

crates/rust-lib/src/lib.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ pub trait RustGenerator<'a> {
6565
true
6666
}
6767

68-
/// Return the fully-qualified name for the `Vec` type to use.
69-
fn vec_name(&self) -> &'static str;
68+
/// Pushes the name of the `Vec` type to use.
69+
fn push_vec_name(&mut self);
7070

71-
/// Return the fully-qualified name for the `String` type to use.
72-
fn string_name(&self) -> &'static str;
71+
/// Pushes the name of the `String` type to use.
72+
fn push_string_name(&mut self);
7373

7474
/// Return true iff the generator should use `&[u8]` instead of `&str` in bindings.
7575
fn use_raw_strings(&self) -> bool {
@@ -238,10 +238,10 @@ pub trait RustGenerator<'a> {
238238
}
239239
TypeMode::Owned => {
240240
if self.use_raw_strings() {
241-
self.push_str(self.vec_name());
241+
self.push_vec_name();
242242
self.push_str("::<u8>");
243243
} else {
244-
self.push_str(self.string_name());
244+
self.push_string_name();
245245
}
246246
}
247247
},
@@ -405,14 +405,14 @@ pub trait RustGenerator<'a> {
405405
if self.resolve().all_bits_valid(ty) {
406406
self.print_borrowed_slice(false, ty, lt, next_mode);
407407
} else {
408-
self.push_str(self.vec_name());
408+
self.push_vec_name();
409409
self.push_str("::<");
410410
self.print_ty(ty, next_mode);
411411
self.push_str(">");
412412
}
413413
}
414414
TypeMode::Owned => {
415-
self.push_str(self.vec_name());
415+
self.push_vec_name();
416416
self.push_str("::<");
417417
self.print_ty(ty, next_mode);
418418
self.push_str(">");

crates/rust-macro/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl Parse for Config {
6565
Opt::MacroCallPrefix(prefix) => opts.macro_call_prefix = Some(prefix.value()),
6666
Opt::ExportMacroName(name) => opts.export_macro_name = Some(name.value()),
6767
Opt::Skip(list) => opts.skip.extend(list.iter().map(|i| i.value())),
68+
Opt::RuntimePath(path) => opts.runtime_path = Some(path.value()),
6869
}
6970
}
7071
} else {
@@ -148,6 +149,7 @@ mod kw {
148149
syn::custom_keyword!(path);
149150
syn::custom_keyword!(inline);
150151
syn::custom_keyword!(ownership);
152+
syn::custom_keyword!(runtime_path);
151153
}
152154

153155
enum Opt {
@@ -161,6 +163,7 @@ enum Opt {
161163
ExportMacroName(syn::LitStr),
162164
Skip(Vec<syn::LitStr>),
163165
Ownership(Ownership),
166+
RuntimePath(syn::LitStr),
164167
}
165168

166169
impl Parse for Opt {
@@ -240,6 +243,10 @@ impl Parse for Opt {
240243
syn::bracketed!(contents in input);
241244
let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
242245
Ok(Opt::Skip(list.iter().cloned().collect()))
246+
} else if l.peek(kw::runtime_path) {
247+
input.parse::<kw::runtime_path>()?;
248+
input.parse::<Token![:]>()?;
249+
Ok(Opt::RuntimePath(input.parse()?))
243250
} else {
244251
Err(l.error())
245252
}

crates/rust/src/lib.rs

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ pub struct Opts {
8181
/// types for borrowing and owning, if necessary.
8282
#[cfg_attr(feature = "clap", arg(long))]
8383
pub ownership: Ownership,
84+
85+
/// The optional path to the wit-bindgen runtime module to use.
86+
///
87+
/// This defaults to `wit_bindgen::rt`.
88+
#[cfg_attr(feature = "clap", arg(long))]
89+
pub runtime_path: Option<String>,
8490
}
8591

8692
impl Opts {
@@ -149,6 +155,13 @@ impl RustWasm {
149155
uwriteln!(self.src, "}}");
150156
}
151157
}
158+
159+
fn runtime_path(&self) -> &str {
160+
self.opts
161+
.runtime_path
162+
.as_deref()
163+
.unwrap_or("wit_bindgen::rt")
164+
}
152165
}
153166

154167
impl WorldGenerator for RustWasm {
@@ -414,12 +427,13 @@ impl InterfaceGenerator<'_> {
414427
self.src,
415428
"
416429
#[allow(unused_imports)]
417-
use wit_bindgen::rt::{{alloc, vec::Vec, string::String}};
430+
use {rt}::{{alloc, vec::Vec, string::String}};
418431
419432
#[repr(align({align}))]
420433
struct _RetArea([u8; {size}]);
421434
static mut _RET_AREA: _RetArea = _RetArea([0; {size}]);
422435
",
436+
rt = self.gen.runtime_path(),
423437
align = self.return_pointer_area_align,
424438
size = self.return_pointer_area_size,
425439
);
@@ -498,12 +512,13 @@ impl InterfaceGenerator<'_> {
498512
self.src.push_str("#[allow(clippy::all)]\n");
499513
let params = self.print_signature(func, param_mode, &sig);
500514
self.src.push_str("{\n");
501-
self.src.push_str(
515+
self.src.push_str(&format!(
502516
"
503517
#[allow(unused_imports)]
504-
use wit_bindgen::rt::{alloc, vec::Vec, string::String};
518+
use {rt}::{{alloc, vec::Vec, string::String}};
505519
",
506-
);
520+
rt = self.gen.runtime_path()
521+
));
507522
self.src.push_str("unsafe {\n");
508523

509524
let mut f = FunctionBindgen::new(self, params);
@@ -613,7 +628,7 @@ impl InterfaceGenerator<'_> {
613628
self.src,
614629
"
615630
#[allow(unused_imports)]
616-
use wit_bindgen::rt::{{alloc, vec::Vec, string::String}};
631+
use {rt}::{{alloc, vec::Vec, string::String}};
617632
618633
// Before executing any other code, use this function to run all static
619634
// constructors, if they have not yet been run. This is a hack required
@@ -627,9 +642,10 @@ impl InterfaceGenerator<'_> {
627642
// https://github.com/bytecodealliance/preview2-prototyping/issues/99
628643
// for more details.
629644
#[cfg(target_arch=\"wasm32\")]
630-
wit_bindgen::rt::run_ctors_once();
645+
{rt}::run_ctors_once();
631646
632-
"
647+
",
648+
rt = self.gen.runtime_path()
633649
);
634650

635651
// Finish out the macro-generated export implementation.
@@ -774,12 +790,15 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
774790
self.gen.opts.raw_strings
775791
}
776792

777-
fn vec_name(&self) -> &'static str {
778-
"wit_bindgen::rt::vec::Vec"
793+
fn push_vec_name(&mut self) {
794+
self.push_str(&format!("{rt}::vec::Vec", rt = self.gen.runtime_path()));
779795
}
780796

781-
fn string_name(&self) -> &'static str {
782-
"wit_bindgen::rt::string::String"
797+
fn push_string_name(&mut self) {
798+
self.push_str(&format!(
799+
"{rt}::string::String",
800+
rt = self.gen.runtime_path()
801+
));
783802
}
784803

785804
fn push_str(&mut self, s: &str) {
@@ -1090,7 +1109,10 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10901109

10911110
Instruction::I64FromU64 | Instruction::I64FromS64 => {
10921111
let s = operands.pop().unwrap();
1093-
results.push(format!("wit_bindgen::rt::as_i64({})", s));
1112+
results.push(format!(
1113+
"{rt}::as_i64({s})",
1114+
rt = self.gen.gen.runtime_path()
1115+
));
10941116
}
10951117
Instruction::I32FromChar
10961118
| Instruction::I32FromU8
@@ -1100,16 +1122,25 @@ impl Bindgen for FunctionBindgen<'_, '_> {
11001122
| Instruction::I32FromU32
11011123
| Instruction::I32FromS32 => {
11021124
let s = operands.pop().unwrap();
1103-
results.push(format!("wit_bindgen::rt::as_i32({})", s));
1125+
results.push(format!(
1126+
"{rt}::as_i32({s})",
1127+
rt = self.gen.gen.runtime_path()
1128+
));
11041129
}
11051130

11061131
Instruction::F32FromFloat32 => {
11071132
let s = operands.pop().unwrap();
1108-
results.push(format!("wit_bindgen::rt::as_f32({})", s));
1133+
results.push(format!(
1134+
"{rt}::as_f32({s})",
1135+
rt = self.gen.gen.runtime_path()
1136+
));
11091137
}
11101138
Instruction::F64FromFloat64 => {
11111139
let s = operands.pop().unwrap();
1112-
results.push(format!("wit_bindgen::rt::as_f64({})", s));
1140+
results.push(format!(
1141+
"{rt}::as_f64({s})",
1142+
rt = self.gen.gen.runtime_path()
1143+
));
11131144
}
11141145
Instruction::Float32FromF32
11151146
| Instruction::Float64FromF64
@@ -1604,7 +1635,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
16041635
self.push_str("}\n");
16051636
results.push(result);
16061637
self.push_str(&format!(
1607-
"wit_bindgen::rt::dealloc({base}, ({len} as usize) * {size}, {align});\n",
1638+
"{rt}::dealloc({base}, ({len} as usize) * {size}, {align});\n",
1639+
rt = self.gen.gen.runtime_path(),
16081640
));
16091641
}
16101642

@@ -1742,15 +1774,18 @@ impl Bindgen for FunctionBindgen<'_, '_> {
17421774

17431775
Instruction::GuestDeallocate { size, align } => {
17441776
self.push_str(&format!(
1745-
"wit_bindgen::rt::dealloc({}, {}, {});\n",
1746-
operands[0], size, align
1777+
"{rt}::dealloc({op}, {size}, {align});\n",
1778+
rt = self.gen.gen.runtime_path(),
1779+
op = operands[0]
17471780
));
17481781
}
17491782

17501783
Instruction::GuestDeallocateString => {
17511784
self.push_str(&format!(
1752-
"wit_bindgen::rt::dealloc({}, ({}) as usize, 1);\n",
1753-
operands[0], operands[1],
1785+
"{rt}::dealloc({op0}, ({op1}) as usize, 1);\n",
1786+
rt = self.gen.gen.runtime_path(),
1787+
op0 = operands[0],
1788+
op1 = operands[1],
17541789
));
17551790
}
17561791

@@ -1802,7 +1837,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
18021837
self.push_str("\n}\n");
18031838
}
18041839
self.push_str(&format!(
1805-
"wit_bindgen::rt::dealloc({base}, ({len} as usize) * {size}, {align});\n",
1840+
"{rt}::dealloc({base}, ({len} as usize) * {size}, {align});\n",
1841+
rt = self.gen.gen.runtime_path(),
18061842
));
18071843
}
18081844

crates/rust/tests/codegen.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,25 @@ mod symbol_does_not_conflict {
226226

227227
export_foo!(Component);
228228
}
229+
230+
mod alternative_runtime_path {
231+
wit_bindgen::generate!({
232+
inline: "
233+
package my:inline
234+
world foo {
235+
export foo: func()
236+
}
237+
",
238+
runtime_path: "my_rt",
239+
});
240+
241+
pub(crate) use wit_bindgen::rt as my_rt;
242+
243+
struct Component;
244+
245+
impl Foo for Component {
246+
fn foo() {}
247+
}
248+
249+
export_foo!(Component);
250+
}

tests/runtime/records.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl test_imports::Host for MyImports {
1919

2020
fn roundtrip_flags1(&mut self, a: test_imports::F1) -> Result<test_imports::F1> {
2121
drop(format!("{:?}", a));
22-
drop(a & test_imports::F1::all());
22+
let _ = a & test_imports::F1::all();
2323
Ok(a)
2424
}
2525

0 commit comments

Comments
 (0)