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.130";
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 module_path: LitOrExpr<'a>,
38 package_json: Option<&'a str>,
39 linked_modules: Vec<LinkedModule<'a>>,
40 }
41
42 struct Import<'a> {
43 module: Option<ImportModule<'a>>,
44 js_namespace: Option<Vec<String>>,
45 reexport: Option<String>,
46 generate_typescript: bool,
47 kind: ImportKind<'a>,
48 }
49
50 struct LinkedModule<'a> {
51 module: ImportModule<'a>,
52 link_function_name: &'a str,
53 }
54
55 enum ImportModule<'a> {
56 Named(&'a str),
57 RawNamed(&'a str),
58 Inline(u32),
59 }
60
61 enum ImportKind<'a> {
62 Function(ImportFunction<'a>),
63 Static(ImportStatic<'a>),
64 String(ImportString<'a>),
65 Type(ImportType<'a>),
66 Enum(StringEnum<'a>),
67 DynamicUnion(DynamicUnion<'a>),
68 }
69
70 struct ImportFunction<'a> {
71 shim: &'a str,
72 catch: bool,
73 variadic: bool,
74 assert_no_shim: bool,
75 suspending: bool,
76 method: Option<MethodData<'a>>,
77 structural: bool,
78 function: Function<'a>,
79 generic_per_mono: bool,
85 }
86
87 struct MethodData<'a> {
88 class: &'a str,
89 kind: MethodKind<'a>,
90 }
91
92 enum MethodKind<'a> {
93 Constructor,
94 Operation(Operation<'a>),
95 }
96
97 struct Operation<'a> {
98 is_static: bool,
99 kind: OperationKind<'a>,
100 }
101
102 enum OperationKind<'a> {
103 Regular,
104 RegularThis,
105 Getter(&'a str),
106 Setter(&'a str),
107 IndexingGetter,
108 IndexingSetter,
109 IndexingDeleter,
110 }
111
112 struct ImportStatic<'a> {
113 name: &'a str,
114 shim: &'a str,
115 }
116
117 struct ImportString<'a> {
118 shim: &'a str,
119 string: &'a str,
120 }
121
122 struct ImportType<'a> {
123 name: &'a str,
124 instanceof_shim: &'a str,
125 vendor_prefixes: Vec<&'a str>,
126 }
127
128 struct StringEnum<'a> {
129 name: &'a str,
130 variant_values: Vec<&'a str>,
131 comments: Vec<&'a str>,
132 generate_typescript: bool,
133 private: bool,
134 js_namespace: Option<Vec<&'a str>>,
135 }
136
137 enum StartKind {
138 None,
139 Public,
140 Private,
141 }
142
143 struct DynamicUnion<'a> {
144 name: &'a str,
145 variant_strings: Vec<&'a str>,
146 variant_type_cnt: u32,
147 comments: Vec<&'a str>,
148 generate_typescript: bool,
149 private: bool,
150 fallback: bool,
151 }
152
153
154 struct Export<'a> {
155 class: Option<&'a str>,
156 comments: Vec<&'a str>,
157 consumed: bool,
158 function: Function<'a>,
159 js_namespace: Option<Vec<&'a str>>,
160 method_kind: MethodKind<'a>,
161 start: StartKind,
162 }
163
164 struct Enum<'a> {
165 name: &'a str,
166 signed: bool,
167 variants: Vec<EnumVariant<'a>>,
168 comments: Vec<&'a str>,
169 generate_typescript: bool,
170 js_namespace: Option<Vec<&'a str>>,
171 private: bool,
172 }
173
174 struct EnumVariant<'a> {
175 name: &'a str,
176 value: u32,
177 comments: Vec<&'a str>,
178 }
179
180 struct Function<'a> {
181 args: Vec<FunctionArgumentData<'a>>,
182 asyncness: bool,
183 jspi: bool,
184 name: &'a str,
185 generate_typescript: bool,
186 generate_jsdoc: bool,
187 variadic: bool,
188 ret_ty_override: Option<&'a str>,
189 ret_desc: Option<&'a str>,
190 }
191
192 struct FunctionArgumentData<'a> {
193 name: String,
194 ty_override: Option<&'a str>,
195 optional: bool,
196 desc: Option<&'a str>,
197 }
198
199 struct Struct<'a> {
200 name: &'a str,
201 fields: Vec<StructField<'a>>,
202 comments: Vec<&'a str>,
203 is_inspectable: bool,
204 generate_typescript: bool,
205 js_namespace: Option<Vec<&'a str>>,
206 private: bool,
207 extends: Option<&'a str>,
208 extends_js_class: Option<&'a str>,
209 extends_js_namespace: Option<Vec<&'a str>>,
210 }
211
212 struct StructField<'a> {
213 name: &'a str,
214 readonly: bool,
215 comments: Vec<&'a str>,
216 generate_typescript: bool,
217 generate_jsdoc: bool,
218 }
219
220 struct LocalModule<'a> {
221 identifier: &'a str,
222 contents: &'a str,
223 linked_module: bool,
224 }
225 }
226 }; } pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
235 match js_namespace {
236 Some(ns) if !ns.is_empty() => {
237 let mut name = ns
238 .iter()
239 .map(|s| s.as_ref())
240 .collect::<alloc::vec::Vec<_>>()
241 .join("__");
242 name.push_str("__");
243 name.push_str(js_name);
244 name
245 }
246 _ => js_name.to_string(),
247 }
248}
249
250pub fn mangled_symbol(base: &str, crate_hash: &str) -> String {
257 let mut name = base.to_string();
258 name.push('_');
259 name.push_str(crate_hash);
260 name
261}
262
263pub fn module_mangled_symbol(base: &str, crate_hash: &str, module_path: &str) -> String {
268 let mut name = mangled_symbol(base, crate_hash);
269 name.push('_');
270 name.push_str(module_path);
271 name
272}
273
274pub const fn module_path_hash(module_path: &str) -> u32 {
280 let bytes = module_path.as_bytes();
281 let mut hash = 0x811c_9dc5u32;
282 let mut i = 0;
283 while i < bytes.len() {
284 hash ^= bytes[i] as u32;
285 hash = hash.wrapping_mul(0x0100_0193);
286 i += 1;
287 }
288 hash
289}
290
291pub fn crate_name(unique_crate_identifier: &str) -> &str {
294 unique_crate_identifier
295 .rsplit_once('-')
296 .map_or(unique_crate_identifier, |(name, _)| name)
297}
298
299pub fn crate_hash(unique_crate_identifier: &str) -> &str {
302 unique_crate_identifier
303 .rsplit_once('-')
304 .map(|(_, hash)| hash)
305 .unwrap_or(unique_crate_identifier)
306}
307
308pub fn new_function(struct_name: &str) -> String {
309 let mut name = "__wbg_".to_string();
310 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
311 name.push_str("_new");
312 name
313}
314
315pub fn free_function(struct_name: &str) -> String {
316 let mut name = "__wbg_".to_string();
317 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
318 name.push_str("_free");
319 name
320}
321
322pub fn unwrap_function(struct_name: &str) -> String {
323 let mut name = "__wbg_".to_string();
324 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
325 name.push_str("_unwrap");
326 name
327}
328
329fn export_name_suffix(name: &str) -> alloc::borrow::Cow<'_, str> {
335 if name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') {
336 return alloc::borrow::Cow::Borrowed(name);
337 }
338 let mut out = String::with_capacity(name.len());
339 for c in name.chars() {
340 if c.is_ascii_alphanumeric() || c == '_' {
341 out.push(c);
342 } else if c == '.' || c == '[' || c == ']' {
343 if c == '.' {
347 out.push('_');
348 }
349 } else {
350 out.push('_');
351 }
352 }
353 alloc::borrow::Cow::Owned(out)
354}
355
356pub fn upcast_function(child_struct: &str, parent_struct: &str) -> String {
360 let mut name = "__wbg_upcast_".to_string();
361 name.extend(child_struct.chars().flat_map(|s| s.to_lowercase()));
362 name.push_str("_to_");
363 name.extend(parent_struct.chars().flat_map(|s| s.to_lowercase()));
364 name
365}
366
367pub fn free_function_export_name(function_name: &str) -> String {
368 export_name_suffix(function_name).into_owned()
369}
370
371pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
372 let mut name = struct_
373 .chars()
374 .flat_map(|s| s.to_lowercase())
375 .collect::<String>();
376 name.push('_');
377 name.push_str(&export_name_suffix(f));
378 name
379}
380
381pub fn struct_field_get(struct_: &str, f: &str) -> String {
382 let mut name = String::from("__wbg_get_");
383 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
384 name.push('_');
385 name.push_str(&export_name_suffix(f));
386 name
387}
388
389pub fn struct_field_set(struct_: &str, f: &str) -> String {
390 let mut name = String::from("__wbg_set_");
391 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
392 name.push('_');
393 name.push_str(&export_name_suffix(f));
394 name
395}
396
397pub fn dynamic_union_variant(union_name: &str, variant_idx: u32) -> String {
398 let mut name = String::from("__wbg_dynamic_union_");
399 name.extend(union_name.chars().flat_map(|s| s.to_lowercase()));
400 name.push('_');
401 name.push_str(&variant_idx.to_string());
402 name
403}
404
405pub fn version() -> String {
406 let mut v = env!("CARGO_PKG_VERSION").to_string();
407 if let Some(s) = option_env!("WBG_VERSION") {
408 v.push_str(" (");
409 v.push_str(s);
410 v.push(')');
411 }
412 v
413}
414
415pub fn escape_string(s: &str) -> String {
416 let mut result = String::with_capacity(s.len());
417 for c in s.chars() {
418 match c {
419 '\\' => result.push_str("\\\\"),
420 '\n' => result.push_str("\\n"),
421 '\r' => result.push_str("\\r"),
422 '\'' => result.push_str("\\'"),
423 '"' => result.push_str("\\\""),
424 _ => result.push(c),
425 }
426 }
427 result
428}