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.128";
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 suspending: bool,
73 method: Option<MethodData<'a>>,
74 structural: bool,
75 function: Function<'a>,
76 generic_per_mono: bool,
82 }
83
84 struct MethodData<'a> {
85 class: &'a str,
86 kind: MethodKind<'a>,
87 }
88
89 enum MethodKind<'a> {
90 Constructor,
91 Operation(Operation<'a>),
92 }
93
94 struct Operation<'a> {
95 is_static: bool,
96 kind: OperationKind<'a>,
97 }
98
99 enum OperationKind<'a> {
100 Regular,
101 RegularThis,
102 Getter(&'a str),
103 Setter(&'a str),
104 IndexingGetter,
105 IndexingSetter,
106 IndexingDeleter,
107 }
108
109 struct ImportStatic<'a> {
110 name: &'a str,
111 shim: &'a str,
112 }
113
114 struct ImportString<'a> {
115 shim: &'a str,
116 string: &'a str,
117 }
118
119 struct ImportType<'a> {
120 name: &'a str,
121 instanceof_shim: &'a str,
122 vendor_prefixes: Vec<&'a str>,
123 }
124
125 struct StringEnum<'a> {
126 name: &'a str,
127 variant_values: Vec<&'a str>,
128 comments: Vec<&'a str>,
129 generate_typescript: bool,
130 private: bool,
131 js_namespace: Option<Vec<&'a str>>,
132 }
133
134 enum StartKind {
135 None,
136 Public,
137 Private,
138 }
139
140 struct DynamicUnion<'a> {
141 name: &'a str,
142 variant_strings: Vec<&'a str>,
143 variant_type_cnt: u32,
144 comments: Vec<&'a str>,
145 generate_typescript: bool,
146 private: bool,
147 fallback: bool,
148 }
149
150
151 struct Export<'a> {
152 class: Option<&'a str>,
153 comments: Vec<&'a str>,
154 consumed: bool,
155 function: Function<'a>,
156 js_namespace: Option<Vec<&'a str>>,
157 method_kind: MethodKind<'a>,
158 start: StartKind,
159 }
160
161 struct Enum<'a> {
162 name: &'a str,
163 signed: bool,
164 variants: Vec<EnumVariant<'a>>,
165 comments: Vec<&'a str>,
166 generate_typescript: bool,
167 js_namespace: Option<Vec<&'a str>>,
168 private: bool,
169 }
170
171 struct EnumVariant<'a> {
172 name: &'a str,
173 value: u32,
174 comments: Vec<&'a str>,
175 }
176
177 struct Function<'a> {
178 args: Vec<FunctionArgumentData<'a>>,
179 asyncness: bool,
180 jspi: bool,
181 name: &'a str,
182 generate_typescript: bool,
183 generate_jsdoc: bool,
184 variadic: bool,
185 ret_ty_override: Option<&'a str>,
186 ret_desc: Option<&'a str>,
187 }
188
189 struct FunctionArgumentData<'a> {
190 name: String,
191 ty_override: Option<&'a str>,
192 optional: bool,
193 desc: Option<&'a str>,
194 }
195
196 struct Struct<'a> {
197 name: &'a str,
198 fields: Vec<StructField<'a>>,
199 comments: Vec<&'a str>,
200 is_inspectable: bool,
201 generate_typescript: bool,
202 js_namespace: Option<Vec<&'a str>>,
203 private: bool,
204 extends: Option<&'a str>,
205 extends_js_class: Option<&'a str>,
206 extends_js_namespace: Option<Vec<&'a str>>,
207 }
208
209 struct StructField<'a> {
210 name: &'a str,
211 readonly: bool,
212 comments: Vec<&'a str>,
213 generate_typescript: bool,
214 generate_jsdoc: bool,
215 }
216
217 struct LocalModule<'a> {
218 identifier: &'a str,
219 contents: &'a str,
220 linked_module: bool,
221 }
222 }
223 }; } pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
232 match js_namespace {
233 Some(ns) if !ns.is_empty() => {
234 let mut name = ns
235 .iter()
236 .map(|s| s.as_ref())
237 .collect::<alloc::vec::Vec<_>>()
238 .join("__");
239 name.push_str("__");
240 name.push_str(js_name);
241 name
242 }
243 _ => js_name.to_string(),
244 }
245}
246
247pub fn mangled_symbol(base: &str, crate_hash: &str) -> String {
254 let mut name = base.to_string();
255 name.push('_');
256 name.push_str(crate_hash);
257 name
258}
259
260pub fn crate_hash(unique_crate_identifier: &str) -> &str {
263 unique_crate_identifier
264 .rsplit_once('-')
265 .map(|(_, hash)| hash)
266 .unwrap_or(unique_crate_identifier)
267}
268
269pub fn new_function(struct_name: &str) -> String {
270 let mut name = "__wbg_".to_string();
271 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
272 name.push_str("_new");
273 name
274}
275
276pub fn free_function(struct_name: &str) -> String {
277 let mut name = "__wbg_".to_string();
278 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
279 name.push_str("_free");
280 name
281}
282
283pub fn unwrap_function(struct_name: &str) -> String {
284 let mut name = "__wbg_".to_string();
285 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
286 name.push_str("_unwrap");
287 name
288}
289
290fn export_name_suffix(name: &str) -> alloc::borrow::Cow<'_, str> {
296 if name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') {
297 return alloc::borrow::Cow::Borrowed(name);
298 }
299 let mut out = String::with_capacity(name.len());
300 for c in name.chars() {
301 if c.is_ascii_alphanumeric() || c == '_' {
302 out.push(c);
303 } else if c == '.' || c == '[' || c == ']' {
304 if c == '.' {
308 out.push('_');
309 }
310 } else {
311 out.push('_');
312 }
313 }
314 alloc::borrow::Cow::Owned(out)
315}
316
317pub fn upcast_function(child_struct: &str, parent_struct: &str) -> String {
321 let mut name = "__wbg_upcast_".to_string();
322 name.extend(child_struct.chars().flat_map(|s| s.to_lowercase()));
323 name.push_str("_to_");
324 name.extend(parent_struct.chars().flat_map(|s| s.to_lowercase()));
325 name
326}
327
328pub fn free_function_export_name(function_name: &str) -> String {
329 export_name_suffix(function_name).into_owned()
330}
331
332pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
333 let mut name = struct_
334 .chars()
335 .flat_map(|s| s.to_lowercase())
336 .collect::<String>();
337 name.push('_');
338 name.push_str(&export_name_suffix(f));
339 name
340}
341
342pub fn struct_field_get(struct_: &str, f: &str) -> String {
343 let mut name = String::from("__wbg_get_");
344 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
345 name.push('_');
346 name.push_str(&export_name_suffix(f));
347 name
348}
349
350pub fn struct_field_set(struct_: &str, f: &str) -> String {
351 let mut name = String::from("__wbg_set_");
352 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
353 name.push('_');
354 name.push_str(&export_name_suffix(f));
355 name
356}
357
358pub fn dynamic_union_variant(union_name: &str, variant_idx: u32) -> String {
359 let mut name = String::from("__wbg_dynamic_union_");
360 name.extend(union_name.chars().flat_map(|s| s.to_lowercase()));
361 name.push('_');
362 name.push_str(&variant_idx.to_string());
363 name
364}
365
366pub fn version() -> String {
367 let mut v = env!("CARGO_PKG_VERSION").to_string();
368 if let Some(s) = option_env!("WBG_VERSION") {
369 v.push_str(" (");
370 v.push_str(s);
371 v.push(')');
372 }
373 v
374}
375
376pub fn escape_string(s: &str) -> String {
377 let mut result = String::with_capacity(s.len());
378 for c in s.chars() {
379 match c {
380 '\\' => result.push_str("\\\\"),
381 '\n' => result.push_str("\\n"),
382 '\r' => result.push_str("\\r"),
383 '\'' => result.push_str("\\'"),
384 '"' => result.push_str("\\\""),
385 _ => result.push(c),
386 }
387 }
388 result
389}