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.122";
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 fields: Vec<StructField<'a>>,
191 comments: Vec<&'a str>,
192 is_inspectable: bool,
193 generate_typescript: bool,
194 js_namespace: Option<Vec<&'a str>>,
195 private: bool,
196 extends: Option<&'a str>,
197 extends_js_class: Option<&'a str>,
198 extends_js_namespace: Option<Vec<&'a str>>,
199 }
200
201 struct StructField<'a> {
202 name: &'a str,
203 readonly: bool,
204 comments: Vec<&'a str>,
205 generate_typescript: bool,
206 generate_jsdoc: bool,
207 }
208
209 struct LocalModule<'a> {
210 identifier: &'a str,
211 contents: &'a str,
212 linked_module: bool,
213 }
214 }
215 }; } pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
224 match js_namespace {
225 Some(ns) if !ns.is_empty() => {
226 let mut name = ns
227 .iter()
228 .map(|s| s.as_ref())
229 .collect::<alloc::vec::Vec<_>>()
230 .join("__");
231 name.push_str("__");
232 name.push_str(js_name);
233 name
234 }
235 _ => js_name.to_string(),
236 }
237}
238
239pub fn new_function(struct_name: &str) -> String {
240 let mut name = "__wbg_".to_string();
241 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
242 name.push_str("_new");
243 name
244}
245
246pub fn free_function(struct_name: &str) -> String {
247 let mut name = "__wbg_".to_string();
248 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
249 name.push_str("_free");
250 name
251}
252
253pub fn unwrap_function(struct_name: &str) -> String {
254 let mut name = "__wbg_".to_string();
255 name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
256 name.push_str("_unwrap");
257 name
258}
259
260fn export_name_suffix(name: &str) -> alloc::borrow::Cow<'_, str> {
266 if name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') {
267 return alloc::borrow::Cow::Borrowed(name);
268 }
269 let mut out = String::with_capacity(name.len());
270 for c in name.chars() {
271 if c.is_ascii_alphanumeric() || c == '_' {
272 out.push(c);
273 } else if c == '.' || c == '[' || c == ']' {
274 if c == '.' {
278 out.push('_');
279 }
280 } else {
281 out.push('_');
282 }
283 }
284 alloc::borrow::Cow::Owned(out)
285}
286
287pub fn upcast_function(child_struct: &str, parent_struct: &str) -> String {
291 let mut name = "__wbg_upcast_".to_string();
292 name.extend(child_struct.chars().flat_map(|s| s.to_lowercase()));
293 name.push_str("_to_");
294 name.extend(parent_struct.chars().flat_map(|s| s.to_lowercase()));
295 name
296}
297
298pub fn free_function_export_name(function_name: &str) -> String {
299 export_name_suffix(function_name).into_owned()
300}
301
302pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
303 let mut name = struct_
304 .chars()
305 .flat_map(|s| s.to_lowercase())
306 .collect::<String>();
307 name.push('_');
308 name.push_str(&export_name_suffix(f));
309 name
310}
311
312pub fn struct_field_get(struct_: &str, f: &str) -> String {
313 let mut name = String::from("__wbg_get_");
314 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
315 name.push('_');
316 name.push_str(&export_name_suffix(f));
317 name
318}
319
320pub fn struct_field_set(struct_: &str, f: &str) -> String {
321 let mut name = String::from("__wbg_set_");
322 name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
323 name.push('_');
324 name.push_str(&export_name_suffix(f));
325 name
326}
327
328pub fn dynamic_union_variant(union_name: &str, variant_idx: u32) -> String {
329 let mut name = String::from("__wbg_dynamic_union_");
330 name.extend(union_name.chars().flat_map(|s| s.to_lowercase()));
331 name.push('_');
332 name.push_str(&variant_idx.to_string());
333 name
334}
335
336pub fn version() -> String {
337 let mut v = env!("CARGO_PKG_VERSION").to_string();
338 if let Some(s) = option_env!("WBG_VERSION") {
339 v.push_str(" (");
340 v.push_str(s);
341 v.push(')');
342 }
343 v
344}
345
346pub fn escape_string(s: &str) -> String {
347 let mut result = String::with_capacity(s.len());
348 for c in s.chars() {
349 match c {
350 '\\' => result.push_str("\\\\"),
351 '\n' => result.push_str("\\n"),
352 '\r' => result.push_str("\\r"),
353 '\'' => result.push_str("\\'"),
354 '"' => result.push_str("\\\""),
355 _ => result.push(c),
356 }
357 }
358 result
359}