1#![doc(html_root_url = "https://docs.rs/wasm-bindgen-shared/0.2")]
2#![no_std]
3
4extern crate alloc;
5
6use alloc::string::{String, ToString};
7
8pub mod identifier;
9#[cfg(test)]
10mod schema_hash_approval;
11pub mod tys;
12
13pub const SCHEMA_VERSION: &str = "0.2.121";
17
18#[macro_export]
19macro_rules! shared_api {
20 ($mac:ident) => {
21 $mac! {
22 struct Program<'a> {
23 exports: Vec<Export<'a>>,
24 enums: Vec<Enum<'a>>,
25 imports: Vec<Import<'a>>,
26 structs: Vec<Struct<'a>>,
27 typescript_custom_sections: Vec<LitOrExpr<'a>>,
32 local_modules: Vec<LocalModule<'a>>,
33 inline_js: Vec<&'a str>,
34 unique_crate_identifier: &'a str,
35 package_json: Option<&'a str>,
36 linked_modules: Vec<LinkedModule<'a>>,
37 }
38
39 struct Import<'a> {
40 module: Option<ImportModule<'a>>,
41 js_namespace: Option<Vec<String>>,
42 reexport: Option<String>,
43 generate_typescript: bool,
44 kind: ImportKind<'a>,
45 }
46
47 struct LinkedModule<'a> {
48 module: ImportModule<'a>,
49 link_function_name: &'a str,
50 }
51
52 enum ImportModule<'a> {
53 Named(&'a str),
54 RawNamed(&'a str),
55 Inline(u32),
56 }
57
58 enum ImportKind<'a> {
59 Function(ImportFunction<'a>),
60 Static(ImportStatic<'a>),
61 String(ImportString<'a>),
62 Type(ImportType<'a>),
63 Enum(StringEnum<'a>),
64 DynamicUnion(DynamicUnion<'a>),
65 }
66
67 struct ImportFunction<'a> {
68 shim: &'a str,
69 catch: bool,
70 variadic: bool,
71 assert_no_shim: bool,
72 method: Option<MethodData<'a>>,
73 structural: bool,
74 function: Function<'a>,
75 }
76
77 struct MethodData<'a> {
78 class: &'a str,
79 kind: MethodKind<'a>,
80 }
81
82 enum MethodKind<'a> {
83 Constructor,
84 Operation(Operation<'a>),
85 }
86
87 struct Operation<'a> {
88 is_static: bool,
89 kind: OperationKind<'a>,
90 }
91
92 enum OperationKind<'a> {
93 Regular,
94 RegularThis,
95 Getter(&'a str),
96 Setter(&'a str),
97 IndexingGetter,
98 IndexingSetter,
99 IndexingDeleter,
100 }
101
102 struct ImportStatic<'a> {
103 name: &'a str,
104 shim: &'a str,
105 }
106
107 struct ImportString<'a> {
108 shim: &'a str,
109 string: &'a str,
110 }
111
112 struct ImportType<'a> {
113 name: &'a str,
114 instanceof_shim: &'a str,
115 vendor_prefixes: Vec<&'a str>,
116 }
117
118 struct StringEnum<'a> {
119 name: &'a str,
120 variant_values: Vec<&'a str>,
121 comments: Vec<&'a str>,
122 generate_typescript: bool,
123 private: bool,
124 js_namespace: Option<Vec<&'a str>>,
125 }
126
127 enum StartKind {
128 None,
129 Public,
130 Private,
131 }
132
133 struct DynamicUnion<'a> {
134 name: &'a str,
135 variant_strings: Vec<&'a str>,
136 variant_type_cnt: u32,
137 comments: Vec<&'a str>,
138 generate_typescript: bool,
139 private: bool,
140 fallback: bool,
141 }
142
143
144 struct Export<'a> {
145 class: Option<&'a str>,
146 comments: Vec<&'a str>,
147 consumed: bool,
148 function: Function<'a>,
149 js_namespace: Option<Vec<&'a str>>,
150 method_kind: MethodKind<'a>,
151 start: StartKind,
152 }
153
154 struct Enum<'a> {
155 name: &'a str,
156 signed: bool,
157 variants: Vec<EnumVariant<'a>>,
158 comments: Vec<&'a str>,
159 generate_typescript: bool,
160 js_namespace: Option<Vec<&'a str>>,
161 private: bool,
162 }
163
164 struct EnumVariant<'a> {
165 name: &'a str,
166 value: u32,
167 comments: Vec<&'a str>,
168 }
169
170 struct Function<'a> {
171 args: Vec<FunctionArgumentData<'a>>,
172 asyncness: bool,
173 name: &'a str,
174 generate_typescript: bool,
175 generate_jsdoc: bool,
176 variadic: bool,
177 ret_ty_override: Option<&'a str>,
178 ret_desc: Option<&'a str>,
179 }
180
181 struct FunctionArgumentData<'a> {
182 name: String,
183 ty_override: Option<&'a str>,
184 optional: bool,
185 desc: Option<&'a str>,
186 }
187
188 struct Struct<'a> {
189 name: &'a str,
190 rust_name: &'a str,
191 fields: Vec<StructField<'a>>,
192 comments: Vec<&'a str>,
193 is_inspectable: bool,
194 generate_typescript: bool,
195 js_namespace: Option<Vec<&'a str>>,
196 private: bool,
197 extends: Option<&'a str>,
198 }
199
200 struct StructField<'a> {
201 name: &'a str,
202 readonly: bool,
203 comments: Vec<&'a str>,
204 generate_typescript: bool,
205 generate_jsdoc: bool,
206 }
207
208 struct LocalModule<'a> {
209 identifier: &'a str,
210 contents: &'a str,
211 linked_module: bool,
212 }
213 }
214 }; } pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
223 match js_namespace {
224 Some(ns) if !ns.is_empty() => {
225 let mut name = ns
226 .iter()
227 .map(|s| s.as_ref())
228 .collect::<alloc::vec::Vec<_>>()
229 .join("__");
230 name.push_str("__");
231 name.push_str(js_name);
232 name
233 }
234 _ => js_name.to_string(),
235 }
236}
237
238pub fn new_function(struct_name: &str) -> String {
239 let mut name = "__wbg_".to_string();
240 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
241 name.push_str("_new");
242 name
243}
244
245pub fn free_function(struct_name: &str) -> String {
246 let mut name = "__wbg_".to_string();
247 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
248 name.push_str("_free");
249 name
250}
251
252pub fn unwrap_function(struct_name: &str) -> String {
253 let mut name = "__wbg_".to_string();
254 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
255 name.push_str("_unwrap");
256 name
257}
258
259fn export_name_suffix(name: &str) -> alloc::borrow::Cow<'_, str> {
265 if name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') {
266 return alloc::borrow::Cow::Borrowed(name);
267 }
268 let mut out = String::with_capacity(name.len());
269 for c in name.chars() {
270 if c.is_ascii_alphanumeric() || c == '_' {
271 out.push(c);
272 } else if c == '.' || c == '[' || c == ']' {
273 if c == '.' {
277 out.push('_');
278 }
279 } else {
280 out.push('_');
281 }
282 }
283 alloc::borrow::Cow::Owned(out)
284}
285
286pub fn upcast_function(child_struct: &str, parent_struct: &str) -> String {
290 let mut name = "__wbg_upcast_".to_string();
291 name.extend(child_struct.chars().flat_map(|s| s.to_lowercase()));
292 name.push_str("_to_");
293 name.extend(parent_struct.chars().flat_map(|s| s.to_lowercase()));
294 name
295}
296
297pub fn free_function_export_name(function_name: &str) -> String {
298 export_name_suffix(function_name).into_owned()
299}
300
301pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
302 let mut name = struct_
303 .chars()
304 .flat_map(|s| s.to_lowercase())
305 .collect::<String>();
306 name.push('_');
307 name.push_str(&export_name_suffix(f));
308 name
309}
310
311pub fn struct_field_get(struct_: &str, f: &str) -> String {
312 let mut name = String::from("__wbg_get_");
313 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
314 name.push('_');
315 name.push_str(&export_name_suffix(f));
316 name
317}
318
319pub fn struct_field_set(struct_: &str, f: &str) -> String {
320 let mut name = String::from("__wbg_set_");
321 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
322 name.push('_');
323 name.push_str(&export_name_suffix(f));
324 name
325}
326
327pub fn dynamic_union_variant(union_name: &str, variant_idx: u32) -> String {
328 let mut name = String::from("__wbg_dynamic_union_");
329 name.extend(union_name.chars().flat_map(|s| s.to_lowercase()));
330 name.push('_');
331 name.push_str(&variant_idx.to_string());
332 name
333}
334
335pub fn version() -> String {
336 let mut v = env!("CARGO_PKG_VERSION").to_string();
337 if let Some(s) = option_env!("WBG_VERSION") {
338 v.push_str(" (");
339 v.push_str(s);
340 v.push(')');
341 }
342 v
343}
344
345pub fn escape_string(s: &str) -> String {
346 let mut result = String::with_capacity(s.len());
347 for c in s.chars() {
348 match c {
349 '\\' => result.push_str("\\\\"),
350 '\n' => result.push_str("\\n"),
351 '\r' => result.push_str("\\r"),
352 '\'' => result.push_str("\\'"),
353 '"' => result.push_str("\\\""),
354 _ => result.push(c),
355 }
356 }
357 result
358}