Skip to main content

wasm_bindgen_shared/
lib.rs

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
13// This gets changed whenever our schema changes.
14// At this time versions of wasm-bindgen and wasm-bindgen-cli are required to have the exact same
15// SCHEMA_VERSION in order to work together.
16pub const SCHEMA_VERSION: &str = "0.2.118";
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            // NOTE: Originally typescript_custom_sections are just some strings
28            // But the expression type can only be parsed into a string during compilation
29            // So when encoding, LitOrExpr contains two types, one is that expressions are parsed into strings during compilation, and the other is can be parsed directly.
30            // When decoding, LitOrExpr can be decoded as a string.
31            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        }
65
66        struct ImportFunction<'a> {
67            shim: &'a str,
68            catch: bool,
69            variadic: bool,
70            assert_no_shim: bool,
71            method: Option<MethodData<'a>>,
72            structural: bool,
73            function: Function<'a>,
74        }
75
76        struct MethodData<'a> {
77            class: &'a str,
78            kind: MethodKind<'a>,
79        }
80
81        enum MethodKind<'a> {
82            Constructor,
83            Operation(Operation<'a>),
84        }
85
86        struct Operation<'a> {
87            is_static: bool,
88            kind: OperationKind<'a>,
89        }
90
91        enum OperationKind<'a> {
92            Regular,
93            RegularThis,
94            Getter(&'a str),
95            Setter(&'a str),
96            IndexingGetter,
97            IndexingSetter,
98            IndexingDeleter,
99        }
100
101        struct ImportStatic<'a> {
102            name: &'a str,
103            shim: &'a str,
104        }
105
106        struct ImportString<'a> {
107            shim: &'a str,
108            string: &'a str,
109        }
110
111        struct ImportType<'a> {
112            name: &'a str,
113            instanceof_shim: &'a str,
114            vendor_prefixes: Vec<&'a str>,
115        }
116
117        struct StringEnum<'a> {
118            name: &'a str,
119            variant_values: Vec<&'a str>,
120            comments: Vec<&'a str>,
121            generate_typescript: bool,
122            js_namespace: Option<Vec<&'a str>>,
123        }
124
125        enum StartKind {
126            None,
127            Public,
128            Private,
129        }
130
131        struct Export<'a> {
132            class: Option<&'a str>,
133            comments: Vec<&'a str>,
134            consumed: bool,
135            function: Function<'a>,
136            js_namespace: Option<Vec<&'a str>>,
137            method_kind: MethodKind<'a>,
138            start: StartKind,
139        }
140
141        struct Enum<'a> {
142            name: &'a str,
143            signed: bool,
144            variants: Vec<EnumVariant<'a>>,
145            comments: Vec<&'a str>,
146            generate_typescript: bool,
147            js_namespace: Option<Vec<&'a str>>,
148            private: bool,
149        }
150
151        struct EnumVariant<'a> {
152            name: &'a str,
153            value: u32,
154            comments: Vec<&'a str>,
155        }
156
157        struct Function<'a> {
158            args: Vec<FunctionArgumentData<'a>>,
159            asyncness: bool,
160            name: &'a str,
161            generate_typescript: bool,
162            generate_jsdoc: bool,
163            variadic: bool,
164            ret_ty_override: Option<&'a str>,
165            ret_desc: Option<&'a str>,
166        }
167
168        struct FunctionArgumentData<'a> {
169            name: String,
170            ty_override: Option<&'a str>,
171            optional: bool,
172            desc: Option<&'a str>,
173        }
174
175        struct Struct<'a> {
176            name: &'a str,
177            rust_name: &'a str,
178            fields: Vec<StructField<'a>>,
179            comments: Vec<&'a str>,
180            is_inspectable: bool,
181            generate_typescript: bool,
182            js_namespace: Option<Vec<&'a str>>,
183            private: bool,
184        }
185
186        struct StructField<'a> {
187            name: &'a str,
188            readonly: bool,
189            comments: Vec<&'a str>,
190            generate_typescript: bool,
191            generate_jsdoc: bool,
192        }
193
194        struct LocalModule<'a> {
195            identifier: &'a str,
196            contents: &'a str,
197            linked_module: bool,
198        }
199        }
200    }; // end of mac case
201} // end of mac definition
202
203/// Compute a "qualified name" by prepending the namespace (joined with `__`) to the js_name.
204/// When there is no namespace, this returns the js_name unchanged.
205/// This is used to disambiguate internal wasm symbols when the same js_name
206/// appears in different namespaces. `__` is used as the separator because
207/// double underscores are unlikely to appear in user-defined names.
208pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
209    match js_namespace {
210        Some(ns) if !ns.is_empty() => {
211            let mut name = ns
212                .iter()
213                .map(|s| s.as_ref())
214                .collect::<alloc::vec::Vec<_>>()
215                .join("__");
216            name.push_str("__");
217            name.push_str(js_name);
218            name
219        }
220        _ => js_name.to_string(),
221    }
222}
223
224pub fn new_function(struct_name: &str) -> String {
225    let mut name = "__wbg_".to_string();
226    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
227    name.push_str("_new");
228    name
229}
230
231pub fn free_function(struct_name: &str) -> String {
232    let mut name = "__wbg_".to_string();
233    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
234    name.push_str("_free");
235    name
236}
237
238pub fn unwrap_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("_unwrap");
242    name
243}
244
245pub fn free_function_export_name(function_name: &str) -> String {
246    function_name.to_string()
247}
248
249pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
250    let mut name = struct_
251        .chars()
252        .flat_map(|s| s.to_lowercase())
253        .collect::<String>();
254    name.push('_');
255    name.push_str(f);
256    name
257}
258
259pub fn struct_field_get(struct_: &str, f: &str) -> String {
260    let mut name = String::from("__wbg_get_");
261    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
262    name.push('_');
263    name.push_str(f);
264    name
265}
266
267pub fn struct_field_set(struct_: &str, f: &str) -> String {
268    let mut name = String::from("__wbg_set_");
269    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
270    name.push('_');
271    name.push_str(f);
272    name
273}
274
275pub fn version() -> String {
276    let mut v = env!("CARGO_PKG_VERSION").to_string();
277    if let Some(s) = option_env!("WBG_VERSION") {
278        v.push_str(" (");
279        v.push_str(s);
280        v.push(')');
281    }
282    v
283}
284
285pub fn escape_string(s: &str) -> String {
286    let mut result = String::with_capacity(s.len());
287    for c in s.chars() {
288        match c {
289            '\\' => result.push_str("\\\\"),
290            '\n' => result.push_str("\\n"),
291            '\r' => result.push_str("\\r"),
292            '\'' => result.push_str("\\'"),
293            '"' => result.push_str("\\\""),
294            _ => result.push(c),
295        }
296    }
297    result
298}