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.114";
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            kind: ImportKind<'a>,
44        }
45
46        struct LinkedModule<'a> {
47            module: ImportModule<'a>,
48            link_function_name: &'a str,
49        }
50
51        enum ImportModule<'a> {
52            Named(&'a str),
53            RawNamed(&'a str),
54            Inline(u32),
55        }
56
57        enum ImportKind<'a> {
58            Function(ImportFunction<'a>),
59            Static(ImportStatic<'a>),
60            String(ImportString<'a>),
61            Type(ImportType<'a>),
62            Enum(StringEnum<'a>),
63        }
64
65        struct ImportFunction<'a> {
66            shim: &'a str,
67            catch: bool,
68            variadic: bool,
69            assert_no_shim: bool,
70            method: Option<MethodData<'a>>,
71            structural: bool,
72            function: Function<'a>,
73        }
74
75        struct MethodData<'a> {
76            class: &'a str,
77            kind: MethodKind<'a>,
78        }
79
80        enum MethodKind<'a> {
81            Constructor,
82            Operation(Operation<'a>),
83        }
84
85        struct Operation<'a> {
86            is_static: bool,
87            kind: OperationKind<'a>,
88        }
89
90        enum OperationKind<'a> {
91            Regular,
92            RegularThis,
93            Getter(&'a str),
94            Setter(&'a str),
95            IndexingGetter,
96            IndexingSetter,
97            IndexingDeleter,
98        }
99
100        struct ImportStatic<'a> {
101            name: &'a str,
102            shim: &'a str,
103        }
104
105        struct ImportString<'a> {
106            shim: &'a str,
107            string: &'a str,
108        }
109
110        struct ImportType<'a> {
111            name: &'a str,
112            instanceof_shim: &'a str,
113            vendor_prefixes: Vec<&'a str>,
114        }
115
116        struct StringEnum<'a> {
117            name: &'a str,
118            variant_values: Vec<&'a str>,
119            comments: Vec<&'a str>,
120            generate_typescript: bool,
121            js_namespace: Option<Vec<&'a str>>,
122        }
123
124        struct Export<'a> {
125            class: Option<&'a str>,
126            comments: Vec<&'a str>,
127            consumed: bool,
128            function: Function<'a>,
129            js_namespace: Option<Vec<&'a str>>,
130            method_kind: MethodKind<'a>,
131            start: bool,
132        }
133
134        struct Enum<'a> {
135            name: &'a str,
136            signed: bool,
137            variants: Vec<EnumVariant<'a>>,
138            comments: Vec<&'a str>,
139            generate_typescript: bool,
140            js_namespace: Option<Vec<&'a str>>,
141            private: bool,
142        }
143
144        struct EnumVariant<'a> {
145            name: &'a str,
146            value: u32,
147            comments: Vec<&'a str>,
148        }
149
150        struct Function<'a> {
151            args: Vec<FunctionArgumentData<'a>>,
152            asyncness: bool,
153            name: &'a str,
154            generate_typescript: bool,
155            generate_jsdoc: bool,
156            variadic: bool,
157            ret_ty_override: Option<&'a str>,
158            ret_desc: Option<&'a str>,
159        }
160
161        struct FunctionArgumentData<'a> {
162            name: String,
163            ty_override: Option<&'a str>,
164            optional: bool,
165            desc: Option<&'a str>,
166        }
167
168        struct Struct<'a> {
169            name: &'a str,
170            rust_name: &'a str,
171            fields: Vec<StructField<'a>>,
172            comments: Vec<&'a str>,
173            is_inspectable: bool,
174            generate_typescript: bool,
175            js_namespace: Option<Vec<&'a str>>,
176            private: bool,
177        }
178
179        struct StructField<'a> {
180            name: &'a str,
181            readonly: bool,
182            comments: Vec<&'a str>,
183            generate_typescript: bool,
184            generate_jsdoc: bool,
185        }
186
187        struct LocalModule<'a> {
188            identifier: &'a str,
189            contents: &'a str,
190            linked_module: bool,
191        }
192        }
193    }; // end of mac case
194} // end of mac definition
195
196/// Compute a "qualified name" by prepending the namespace (joined with `__`) to the js_name.
197/// When there is no namespace, this returns the js_name unchanged.
198/// This is used to disambiguate internal wasm symbols when the same js_name
199/// appears in different namespaces. `__` is used as the separator because
200/// double underscores are unlikely to appear in user-defined names.
201pub fn qualified_name(js_namespace: Option<&[impl AsRef<str>]>, js_name: &str) -> String {
202    match js_namespace {
203        Some(ns) if !ns.is_empty() => {
204            let mut name = ns
205                .iter()
206                .map(|s| s.as_ref())
207                .collect::<alloc::vec::Vec<_>>()
208                .join("__");
209            name.push_str("__");
210            name.push_str(js_name);
211            name
212        }
213        _ => js_name.to_string(),
214    }
215}
216
217pub fn new_function(struct_name: &str) -> String {
218    let mut name = "__wbg_".to_string();
219    name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));
220    name.push_str("_new");
221    name
222}
223
224pub fn free_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("_free");
228    name
229}
230
231pub fn unwrap_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("_unwrap");
235    name
236}
237
238pub fn free_function_export_name(function_name: &str) -> String {
239    function_name.to_string()
240}
241
242pub fn struct_function_export_name(struct_: &str, f: &str) -> String {
243    let mut name = struct_
244        .chars()
245        .flat_map(|s| s.to_lowercase())
246        .collect::<String>();
247    name.push('_');
248    name.push_str(f);
249    name
250}
251
252pub fn struct_field_get(struct_: &str, f: &str) -> String {
253    let mut name = String::from("__wbg_get_");
254    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
255    name.push('_');
256    name.push_str(f);
257    name
258}
259
260pub fn struct_field_set(struct_: &str, f: &str) -> String {
261    let mut name = String::from("__wbg_set_");
262    name.extend(struct_.chars().flat_map(|s| s.to_lowercase()));
263    name.push('_');
264    name.push_str(f);
265    name
266}
267
268pub fn version() -> String {
269    let mut v = env!("CARGO_PKG_VERSION").to_string();
270    if let Some(s) = option_env!("WBG_VERSION") {
271        v.push_str(" (");
272        v.push_str(s);
273        v.push(')');
274    }
275    v
276}
277
278pub fn escape_string(s: &str) -> String {
279    let mut result = String::with_capacity(s.len());
280    for c in s.chars() {
281        match c {
282            '\\' => result.push_str("\\\\"),
283            '\n' => result.push_str("\\n"),
284            '\r' => result.push_str("\\r"),
285            '\'' => result.push_str("\\'"),
286            '"' => result.push_str("\\\""),
287            _ => result.push(c),
288        }
289    }
290    result
291}