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.115";
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        struct Export<'a> {
126            class: Option<&'a str>,
127            comments: Vec<&'a str>,
128            consumed: bool,
129            function: Function<'a>,
130            js_namespace: Option<Vec<&'a str>>,
131            method_kind: MethodKind<'a>,
132            start: bool,
133        }
134
135        struct Enum<'a> {
136            name: &'a str,
137            signed: bool,
138            variants: Vec<EnumVariant<'a>>,
139            comments: Vec<&'a str>,
140            generate_typescript: bool,
141            js_namespace: Option<Vec<&'a str>>,
142            private: bool,
143        }
144
145        struct EnumVariant<'a> {
146            name: &'a str,
147            value: u32,
148            comments: Vec<&'a str>,
149        }
150
151        struct Function<'a> {
152            args: Vec<FunctionArgumentData<'a>>,
153            asyncness: bool,
154            name: &'a str,
155            generate_typescript: bool,
156            generate_jsdoc: bool,
157            variadic: bool,
158            ret_ty_override: Option<&'a str>,
159            ret_desc: Option<&'a str>,
160        }
161
162        struct FunctionArgumentData<'a> {
163            name: String,
164            ty_override: Option<&'a str>,
165            optional: bool,
166            desc: Option<&'a str>,
167        }
168
169        struct Struct<'a> {
170            name: &'a str,
171            rust_name: &'a str,
172            fields: Vec<StructField<'a>>,
173            comments: Vec<&'a str>,
174            is_inspectable: bool,
175            generate_typescript: bool,
176            js_namespace: Option<Vec<&'a str>>,
177            private: bool,
178        }
179
180        struct StructField<'a> {
181            name: &'a str,
182            readonly: bool,
183            comments: Vec<&'a str>,
184            generate_typescript: bool,
185            generate_jsdoc: bool,
186        }
187
188        struct LocalModule<'a> {
189            identifier: &'a str,
190            contents: &'a str,
191            linked_module: bool,
192        }
193        }
194    }; // end of mac case
195} // end of mac definition
196
197/// Compute a "qualified name" by prepending the namespace (joined with `__`) to the js_name.
198/// When there is no namespace, this returns the js_name unchanged.
199/// This is used to disambiguate internal wasm symbols when the same js_name
200/// appears in different namespaces. `__` is used as the separator because
201/// double underscores are unlikely to appear in user-defined names.
202pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
203    match js_namespace {
204        Some(ns) if !ns.is_empty() => {
205            let mut name = ns
206                .iter()
207                .map(|s| s.as_ref())
208                .collect::<alloc::vec::Vec<_>>()
209                .join("__");
210            name.push_str("__");
211            name.push_str(js_name);
212            name
213        }
214        _ => js_name.to_string(),
215    }
216}
217
218pub fn new_function(struct_name: &str) -> String {
219    let mut name = "__wbg_".to_string();
220    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
221    name.push_str("_new");
222    name
223}
224
225pub fn free_function(struct_name: &str) -> String {
226    let mut name = "__wbg_".to_string();
227    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
228    name.push_str("_free");
229    name
230}
231
232pub fn unwrap_function(struct_name: &str) -> String {
233    let mut name = "__wbg_".to_string();
234    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
235    name.push_str("_unwrap");
236    name
237}
238
239pub fn free_function_export_name(function_name: &str) -> String {
240    function_name.to_string()
241}
242
243pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
244    let mut name = struct_
245        .chars()
246        .flat_map(|s| s.to_lowercase())
247        .collect::<String>();
248    name.push('_');
249    name.push_str(f);
250    name
251}
252
253pub fn struct_field_get(struct_: &str, f: &str) -> String {
254    let mut name = String::from("__wbg_get_");
255    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
256    name.push('_');
257    name.push_str(f);
258    name
259}
260
261pub fn struct_field_set(struct_: &str, f: &str) -> String {
262    let mut name = String::from("__wbg_set_");
263    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
264    name.push('_');
265    name.push_str(f);
266    name
267}
268
269pub fn version() -> String {
270    let mut v = env!("CARGO_PKG_VERSION").to_string();
271    if let Some(s) = option_env!("WBG_VERSION") {
272        v.push_str(" (");
273        v.push_str(s);
274        v.push(')');
275    }
276    v
277}
278
279pub fn escape_string(s: &str) -> String {
280    let mut result = String::with_capacity(s.len());
281    for c in s.chars() {
282        match c {
283            '\\' => result.push_str("\\\\"),
284            '\n' => result.push_str("\\n"),
285            '\r' => result.push_str("\\r"),
286            '\'' => result.push_str("\\'"),
287            '"' => result.push_str("\\\""),
288            _ => result.push(c),
289        }
290    }
291    result
292}