Skip to content

Commit 7f0967a

Browse files
Revert the de-dups
1 parent f183d49 commit 7f0967a

10 files changed

Lines changed: 268 additions & 310 deletions

File tree

crates/c/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use wit_bindgen_core::abi::{
1010
self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmSignature, WasmType,
1111
};
1212
use wit_bindgen_core::{
13-
AnonymousTypeGenerator, AsyncFilterSet, Direction, Files, FilterSet, InterfaceGenerator as _,
14-
Ns, WorldGenerator, dealias, uwrite, uwriteln, wit_parser::*,
13+
AnonymousTypeGenerator, AsyncFilterSet, Direction, Files, InterfaceGenerator as _, Ns,
14+
WorldGenerator, dealias, uwrite, uwriteln, wit_parser::*,
1515
};
1616
use wit_component::StringEncoding;
1717

@@ -2077,7 +2077,7 @@ impl InterfaceGenerator<'_> {
20772077
.r#gen
20782078
.opts
20792079
.async_
2080-
.apply_rules(self.resolve, interface_name, func, true);
2080+
.is_async(self.resolve, interface_name, func, true);
20812081
if async_ {
20822082
self.r#gen.needs_async = true;
20832083
}
@@ -2246,7 +2246,7 @@ impl InterfaceGenerator<'_> {
22462246
.r#gen
22472247
.opts
22482248
.async_
2249-
.apply_rules(self.resolve, interface_name, func, false);
2249+
.is_async(self.resolve, interface_name, func, false);
22502250

22512251
let (variant, prefix) = if async_ {
22522252
self.r#gen.needs_async = true;

crates/core/src/async_.rs

Lines changed: 108 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,70 @@
1+
use anyhow::{Result, bail};
2+
use std::collections::HashSet;
13
use std::fmt;
2-
use std::fmt::Write;
34
use wit_parser::{Function, FunctionKind, Resolve, WorldKey};
45

5-
use crate::define_filter_set;
6-
use crate::filter::{FilterMode, FilterRule, FilterTarget};
7-
8-
define_filter_set! {
9-
/// Structure used to parse the command line argument `--async` consistently
10-
/// across guest generators.
11-
pub struct AsyncFilterSet,
6+
/// Structure used to parse the command line argument `--async` consistently
7+
/// across guest generators.
8+
#[cfg_attr(feature = "clap", derive(clap::Parser))]
9+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
10+
#[derive(Clone, Default, Debug)]
11+
pub struct AsyncFilterSet {
1212
/// Determines which functions to lift or lower `async`, if any.
1313
///
1414
/// This option can be passed multiple times and additionally accepts
1515
/// comma-separated values for each option passed. Each individual argument
1616
/// passed here can be one of:
1717
///
1818
/// - `all` - all imports and exports will be async
19-
///
2019
/// - `-all` - force all imports and exports to be sync
21-
///
2220
/// - `foo:bar/baz#method` - force this method to be async
23-
///
2421
/// - `import:foo:bar/baz#method` - force this method to be async, but only
2522
/// as an import
26-
///
2723
/// - `-export:foo:bar/baz#method` - force this export to be sync
2824
///
29-
///
3025
/// If a method is not listed in this option then the WIT's default bindings
3126
/// mode will be used. If the WIT function is defined as `async` then async
3227
/// bindings will be generated, otherwise sync bindings will be generated.
3328
///
3429
/// Options are processed in the order they are passed here, so if a method
3530
/// matches two directives passed the least-specific one should be last.
36-
bool, AsyncFilter,
37-
"async"
31+
#[cfg_attr(
32+
feature = "clap",
33+
arg(
34+
long = "async",
35+
value_parser = parse_async,
36+
value_delimiter =',',
37+
value_name = "FILTER",
38+
),
39+
)]
40+
#[cfg_attr(feature = "serde", serde(rename = "async"))]
41+
async_: Vec<Async>,
42+
43+
#[cfg_attr(feature = "clap", arg(skip))]
44+
#[cfg_attr(feature = "serde", serde(skip))]
45+
used_options: HashSet<usize>,
46+
}
47+
48+
#[cfg(feature = "clap")]
49+
fn parse_async(s: &str) -> Result<Async, String> {
50+
Ok(Async::parse(s))
3851
}
3952

4053
impl AsyncFilterSet {
41-
pub fn any_enabled(&self) -> bool {
42-
self.rules.iter().any(|o| o.mode)
54+
/// Returns a set where all functions should be async or not depending on
55+
/// `async_` provided.
56+
pub fn all(async_: bool) -> AsyncFilterSet {
57+
AsyncFilterSet {
58+
async_: vec![Async {
59+
enabled: async_,
60+
filter: AsyncFilter::All,
61+
}],
62+
used_options: HashSet::new(),
63+
}
4364
}
4465

45-
fn apply_rules(
66+
/// Returns whether the `func` provided is to be bound `async` or not.
67+
pub fn is_async(
4668
&mut self,
4769
resolve: &Resolve,
4870
interface: Option<&WorldKey>,
@@ -53,12 +75,11 @@ impl AsyncFilterSet {
5375
Some(key) => format!("{}#{}", resolve.name_world_key(key), func.name),
5476
None => func.name.clone(),
5577
};
56-
57-
for (i, opt) in self.rules.iter().enumerate() {
78+
for (i, opt) in self.async_.iter().enumerate() {
5879
let name = match &opt.filter {
5980
AsyncFilter::All => {
6081
self.used_options.insert(i);
61-
return opt.mode;
82+
return opt.enabled;
6283
}
6384
AsyncFilter::Function(s) => s,
6485
AsyncFilter::Import(s) => {
@@ -76,62 +97,97 @@ impl AsyncFilterSet {
7697
};
7798
if *name == name_to_test {
7899
self.used_options.insert(i);
79-
return opt.mode;
100+
return opt.enabled;
80101
}
81102
}
82103

83-
matches!(
84-
func.kind,
104+
match &func.kind {
105+
FunctionKind::Freestanding
106+
| FunctionKind::Method(_)
107+
| FunctionKind::Static(_)
108+
| FunctionKind::Constructor(_) => false,
85109
FunctionKind::AsyncFreestanding
86-
| FunctionKind::AsyncMethod(_)
87-
| FunctionKind::AsyncStatic(_)
88-
)
110+
| FunctionKind::AsyncMethod(_)
111+
| FunctionKind::AsyncStatic(_) => true,
112+
}
89113
}
90-
}
91114

92-
impl FilterMode for bool {
93-
fn parse(s: &str) -> (Self, &str) {
94-
match s.strip_prefix('-') {
95-
Some(rest) => (false, rest),
96-
None => (true, s),
97-
}
115+
/// Intended to be used in the header comment of generated code to help
116+
/// indicate what options were specified.
117+
pub fn debug_opts(&self) -> impl Iterator<Item = String> + '_ {
118+
self.async_.iter().map(|opt| opt.to_string())
98119
}
99-
fn fmt_prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100-
if !*self {
101-
f.write_char('-')?;
120+
121+
/// Tests whether all `--async` options were used throughout bindings
122+
/// generation, returning an error if any were unused.
123+
pub fn ensure_all_used(&self) -> Result<()> {
124+
for (i, opt) in self.async_.iter().enumerate() {
125+
if self.used_options.contains(&i) {
126+
continue;
127+
}
128+
if !matches!(opt.filter, AsyncFilter::All) {
129+
bail!("unused async option: {opt}");
130+
}
102131
}
103132
Ok(())
104133
}
134+
135+
/// Returns whether any option explicitly requests that async is enabled.
136+
pub fn any_enabled(&self) -> bool {
137+
self.async_.iter().any(|o| o.enabled)
138+
}
139+
140+
/// Pushes a new option into this set.
141+
pub fn push(&mut self, directive: &str) {
142+
self.async_.push(Async::parse(directive));
143+
}
105144
}
106145

107-
#[derive(Debug, Clone, PartialEq)]
146+
#[derive(Debug, Clone)]
108147
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
109-
pub enum AsyncFilter {
110-
All,
111-
Function(String),
112-
Import(String),
113-
Export(String),
148+
struct Async {
149+
enabled: bool,
150+
filter: AsyncFilter,
114151
}
115152

116-
impl FilterTarget for AsyncFilter {
117-
fn parse(s: &str) -> Self {
118-
match s {
153+
impl Async {
154+
fn parse(s: &str) -> Async {
155+
let (s, enabled) = match s.strip_prefix('-') {
156+
Some(s) => (s, false),
157+
None => (s, true),
158+
};
159+
let filter = match s {
119160
"all" => AsyncFilter::All,
120161
other => match other.strip_prefix("import:") {
121-
Some(sub) => AsyncFilter::Import(sub.to_string()),
162+
Some(s) => AsyncFilter::Import(s.to_string()),
122163
None => match other.strip_prefix("export:") {
123-
Some(sub) => AsyncFilter::Export(sub.to_string()),
124-
None => AsyncFilter::Function(other.to_string()),
164+
Some(s) => AsyncFilter::Export(s.to_string()),
165+
None => AsyncFilter::Function(s.to_string()),
125166
},
126167
},
127-
}
168+
};
169+
Async { enabled, filter }
128170
}
171+
}
129172

130-
fn all() -> AsyncFilter {
131-
AsyncFilter::All
173+
impl fmt::Display for Async {
174+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175+
if !self.enabled {
176+
write!(f, "-")?;
177+
}
178+
self.filter.fmt(f)
132179
}
133180
}
134181

182+
#[derive(Debug, Clone)]
183+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
184+
enum AsyncFilter {
185+
All,
186+
Function(String),
187+
Import(String),
188+
Export(String),
189+
}
190+
135191
impl fmt::Display for AsyncFilter {
136192
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137193
match self {

0 commit comments

Comments
 (0)