Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wit-bindgen/src/config.rs
1693 views
1
use crate::{LookupItem, lookup_keys};
2
use anyhow::Result;
3
use wit_parser::{Function, FunctionKind, Resolve, WorldKey};
4
5
bitflags::bitflags! {
6
#[derive(Default, Copy, Clone, Debug)]
7
pub struct FunctionFlags: u8 {
8
const ASYNC = 1 << 0;
9
const TRAPPABLE = 1 << 1;
10
const STORE = 1 << 2;
11
const TRACING = 1 << 3;
12
const VERBOSE_TRACING = 1 << 4;
13
const IGNORE_WIT = 1 << 5;
14
const EXACT = 1 << 6;
15
}
16
}
17
18
#[derive(Default, Debug, Clone)]
19
pub struct FunctionConfig {
20
rules: Vec<FunctionRule>,
21
default: FunctionFlags,
22
}
23
24
#[derive(Debug, Clone)]
25
struct FunctionRule {
26
filter: String,
27
flags: FunctionFlags,
28
used: bool,
29
}
30
31
#[derive(Debug, Clone)]
32
pub enum FunctionFilter {
33
Name(String),
34
Default,
35
}
36
37
impl FunctionConfig {
38
/// Creates a blank set of configuration.
39
pub fn new() -> FunctionConfig {
40
FunctionConfig::default()
41
}
42
43
/// Adds a new rule to this configuration.
44
///
45
/// Note that the order rules are added is significant as only the first
46
/// matching rule is used for a function.
47
pub fn push(&mut self, filter: FunctionFilter, flags: FunctionFlags) {
48
match filter {
49
FunctionFilter::Name(filter) => {
50
self.rules.push(FunctionRule {
51
filter,
52
flags,
53
used: false,
54
});
55
}
56
FunctionFilter::Default => {
57
self.default = flags;
58
}
59
}
60
}
61
62
/// Returns the set of configuration flags associated with `func`.
63
///
64
/// The `name` provided should include the full name of the function
65
/// including its interface. The `kind` is the classification of the
66
/// function in WIT which affects the default set of flags.
67
pub(crate) fn flags(
68
&mut self,
69
resolve: &Resolve,
70
ns: Option<&WorldKey>,
71
func: &Function,
72
) -> FunctionFlags {
73
let mut wit_flags = FunctionFlags::empty();
74
75
// If the kind is async, then set the async/store flags as that's a
76
// concurrent function which requires access to both.
77
match &func.kind {
78
FunctionKind::Freestanding
79
| FunctionKind::Method(_)
80
| FunctionKind::Static(_)
81
| FunctionKind::Constructor(_) => {}
82
83
FunctionKind::AsyncFreestanding
84
| FunctionKind::AsyncMethod(_)
85
| FunctionKind::AsyncStatic(_) => {
86
wit_flags |= FunctionFlags::ASYNC | FunctionFlags::STORE;
87
}
88
}
89
90
let mut ret = FunctionFlags::empty();
91
self.add_function_flags(resolve, ns, &func.name, &mut ret);
92
if !ret.contains(FunctionFlags::IGNORE_WIT) {
93
ret |= wit_flags;
94
}
95
ret
96
}
97
98
pub(crate) fn resource_drop_flags(
99
&mut self,
100
resolve: &Resolve,
101
ns: Option<&WorldKey>,
102
resource_name: &str,
103
) -> FunctionFlags {
104
let mut ret = FunctionFlags::empty();
105
self.add_function_flags(resolve, ns, &format!("[drop]{resource_name}"), &mut ret);
106
ret
107
}
108
109
fn add_function_flags(
110
&mut self,
111
resolve: &Resolve,
112
key: Option<&WorldKey>,
113
name: &str,
114
base: &mut FunctionFlags,
115
) {
116
let mut apply_rules = |name: &str, is_exact: bool| {
117
for rule in self.rules.iter_mut() {
118
if name != rule.filter {
119
continue;
120
}
121
if !is_exact && rule.flags.contains(FunctionFlags::EXACT) {
122
continue;
123
}
124
rule.used = true;
125
*base |= rule.flags;
126
127
// only the first rule is used.
128
return true;
129
}
130
131
false
132
};
133
match key {
134
Some(key) => {
135
for (lookup, projection) in lookup_keys(resolve, key, LookupItem::Name(name)) {
136
if apply_rules(&lookup, projection.is_empty()) {
137
return;
138
}
139
}
140
}
141
None => {
142
if apply_rules(name, true) {
143
return;
144
}
145
}
146
}
147
148
*base |= self.default;
149
}
150
151
pub(crate) fn assert_all_rules_used(&self, kind: &str) -> Result<()> {
152
let mut unused = Vec::new();
153
for rule in self.rules.iter().filter(|r| !r.used) {
154
unused.push(format!("{:?}: {:?}", rule.filter, rule.flags));
155
}
156
157
if unused.is_empty() {
158
return Ok(());
159
}
160
161
anyhow::bail!("unused `{kind}` rules found: {unused:?}");
162
}
163
}
164
165