Skip to content

Commit 217b866

Browse files
authored
Add the ability to skip bindings in Rust (#422)
This commit adds a `skip` attribute and CLI argument for skipping generation of bindings for a set of named functions. This can be useful when the generated bindings can't be used for a reason such as they're to high-level, instead allowing applications to manually define functions which work with the raw inputs of the canonical ABI.
1 parent 4862162 commit 217b866

3 files changed

Lines changed: 48 additions & 1 deletion

File tree

crates/gen-guest-rust/src/lib.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use heck::*;
2+
use std::collections::HashSet;
23
use std::fmt::Write as _;
34
use std::io::{Read, Write};
45
use std::mem;
@@ -18,6 +19,7 @@ struct RustWasm {
1819
src: Source,
1920
opts: Opts,
2021
exports: Vec<Source>,
22+
skip: HashSet<String>,
2123
}
2224

2325
#[derive(Default, Debug, Clone)]
@@ -62,11 +64,16 @@ pub struct Opts {
6264
/// format `export_{world_name}!`.
6365
#[cfg_attr(feature = "clap", arg(long))]
6466
pub export_macro_name: Option<String>,
67+
68+
/// Names of functions to skip generating bindings for.
69+
#[cfg_attr(feature = "clap", arg(long))]
70+
pub skip: Vec<String>,
6571
}
6672

6773
impl Opts {
6874
pub fn build(self) -> Box<dyn WorldGenerator> {
6975
let mut r = RustWasm::new();
76+
r.skip = self.skip.iter().cloned().collect();
7077
r.opts = self;
7178
Box::new(r)
7279
}
@@ -243,6 +250,9 @@ impl InterfaceGenerator<'_> {
243250
let camel = name.to_upper_camel_case();
244251
uwriteln!(self.src, "pub trait {camel} {{");
245252
for func in self.iface.functions.iter() {
253+
if self.gen.skip.contains(&func.name) {
254+
continue;
255+
}
246256
let mut sig = FnSig::default();
247257
sig.private = true;
248258
self.print_signature(func, TypeMode::Owned, &sig);
@@ -289,6 +299,10 @@ impl InterfaceGenerator<'_> {
289299
}
290300

291301
fn generate_guest_import(&mut self, func: &Function) {
302+
if self.gen.skip.contains(&func.name) {
303+
return;
304+
}
305+
292306
let sig = FnSig::default();
293307
let param_mode = TypeMode::AllBorrowed("'_");
294308
match &func.kind {
@@ -325,13 +339,16 @@ impl InterfaceGenerator<'_> {
325339
}
326340

327341
fn generate_guest_export(&mut self, module_name: &str, func: &Function, default_export: bool) {
342+
if self.gen.skip.contains(&func.name) {
343+
return;
344+
}
345+
328346
let module_name = module_name.to_snake_case();
329347
let trait_bound = module_name.to_upper_camel_case();
330348
let iface_snake = self.iface.name.to_snake_case();
331349
let name_snake = func.name.to_snake_case();
332350
let export_name = self.iface.core_export_name(default_export, func);
333351
let mut macro_src = Source::default();
334-
335352
// Generate, simultaneously, the actual lifting/lowering function within
336353
// the original module (`call_{name_snake}`) as well as the function
337354
// which will ge exported from the wasm module itself through the export

crates/gen-guest-rust/tests/codegen.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,22 @@ mod macro_name {
174174

175175
jam!(Component);
176176
}
177+
178+
mod skip {
179+
wit_bindgen_guest_rust::generate!({
180+
export_str["exports"]: "
181+
foo: func()
182+
bar: func()
183+
",
184+
name: "baz",
185+
skip: ["foo"],
186+
});
187+
188+
struct Component;
189+
190+
impl exports::Exports for Component {
191+
fn bar() {}
192+
}
193+
194+
export_baz!(Component);
195+
}

crates/guest-rust-macro/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use proc_macro::TokenStream;
22
use syn::{
33
parse::{Parse, ParseStream, Result},
4+
punctuated::Punctuated,
45
LitStr, Token,
56
};
67
use wit_bindgen_gen_guest_rust::Opts;
@@ -16,6 +17,7 @@ mod kw {
1617
syn::custom_keyword!(raw_strings);
1718
syn::custom_keyword!(macro_call_prefix);
1819
syn::custom_keyword!(export_macro_name);
20+
syn::custom_keyword!(skip);
1921
}
2022

2123
enum Opt {
@@ -24,6 +26,7 @@ enum Opt {
2426
RawStrings,
2527
MacroCallPrefix(LitStr),
2628
ExportMacroName(LitStr),
29+
Skip(Vec<LitStr>),
2730
}
2831

2932
impl Parse for Opt {
@@ -46,6 +49,13 @@ impl Parse for Opt {
4649
input.parse::<kw::export_macro_name>()?;
4750
input.parse::<Token![:]>()?;
4851
Ok(Opt::ExportMacroName(input.parse()?))
52+
} else if l.peek(kw::skip) {
53+
input.parse::<kw::skip>()?;
54+
input.parse::<Token![:]>()?;
55+
let contents;
56+
syn::bracketed!(contents in input);
57+
let list = Punctuated::<_, Token![,]>::parse_terminated(&contents)?;
58+
Ok(Opt::Skip(list.iter().cloned().collect()))
4959
} else {
5060
Err(l.error())
5161
}
@@ -60,6 +70,7 @@ impl wit_bindgen_rust_macro_shared::Configure<Opts> for Opt {
6070
Opt::RawStrings => opts.raw_strings = true,
6171
Opt::MacroCallPrefix(prefix) => opts.macro_call_prefix = Some(prefix.value()),
6272
Opt::ExportMacroName(name) => opts.export_macro_name = Some(name.value()),
73+
Opt::Skip(list) => opts.skip.extend(list.iter().map(|i| i.value())),
6374
}
6475
}
6576
}

0 commit comments

Comments
 (0)