wai_bindgen_gen_core/
lib.rs

1use anyhow::Result;
2use std::collections::{btree_map::Entry, BTreeMap, HashMap};
3use std::fmt::{self, Write};
4use std::ops::Deref;
5use std::path::Path;
6use wai_parser::*;
7
8pub use wai_parser;
9mod ns;
10
11pub use ns::Ns;
12
13/// This is the direction from the user's perspective. Are we importing
14/// functions to call, or defining functions and exporting them to be called?
15///
16/// This is only used outside of `Generator` implementations. Inside of
17/// `Generator` implementations, the `Direction` is translated to an
18/// `AbiVariant` instead. The ABI variant is usually the same as the
19/// `Direction`, but it's different in the case of the Wasmtime host bindings:
20///
21/// In a wasm-calling-wasm use case, one wasm module would use the `Import`
22/// ABI, the other would use the `Export` ABI, and there would be an adapter
23/// layer between the two that translates from one ABI to the other.
24///
25/// But with wasm-calling-host, we don't go through a separate adapter layer;
26/// the binding code we generate on the host side just does everything itself.
27/// So when the host is conceptually "exporting" a function to wasm, it uses
28/// the `Import` ABI so that wasm can also use the `Import` ABI and import it
29/// directly from the host.
30///
31/// These are all implementation details; from the user perspective, and
32/// from the perspective of everything outside of `Generator` implementations,
33/// `export` means I'm exporting functions to be called, and `import` means I'm
34/// importing functions that I'm going to call, in both wasm modules and host
35/// code. The enum here represents this user perspective.
36#[derive(Copy, Clone, Eq, PartialEq)]
37pub enum Direction {
38    Import,
39    Export,
40}
41
42pub trait Generator {
43    fn preprocess_all(&mut self, imports: &[Interface], exports: &[Interface]) {
44        drop((imports, exports));
45    }
46
47    fn preprocess_one(&mut self, iface: &Interface, dir: Direction) {
48        drop((iface, dir));
49    }
50
51    fn type_record(
52        &mut self,
53        iface: &Interface,
54        id: TypeId,
55        name: &str,
56        record: &Record,
57        docs: &Docs,
58    );
59    fn type_flags(&mut self, iface: &Interface, id: TypeId, name: &str, flags: &Flags, docs: &Docs);
60    fn type_tuple(&mut self, iface: &Interface, id: TypeId, name: &str, flags: &Tuple, docs: &Docs);
61    fn type_variant(
62        &mut self,
63        iface: &Interface,
64        id: TypeId,
65        name: &str,
66        variant: &Variant,
67        docs: &Docs,
68    );
69    fn type_option(
70        &mut self,
71        iface: &Interface,
72        id: TypeId,
73        name: &str,
74        payload: &Type,
75        docs: &Docs,
76    );
77    fn type_expected(
78        &mut self,
79        iface: &Interface,
80        id: TypeId,
81        name: &str,
82        expected: &Expected,
83        docs: &Docs,
84    );
85    fn type_union(&mut self, iface: &Interface, id: TypeId, name: &str, union: &Union, docs: &Docs);
86    fn type_enum(&mut self, iface: &Interface, id: TypeId, name: &str, enum_: &Enum, docs: &Docs);
87    fn type_resource(&mut self, iface: &Interface, ty: ResourceId);
88    fn type_alias(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
89    fn type_list(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
90    fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs);
91
92    fn preprocess_functions(&mut self, iface: &Interface, dir: Direction) {
93        drop((iface, dir));
94    }
95    fn import(&mut self, iface: &Interface, func: &Function);
96    fn export(&mut self, iface: &Interface, func: &Function);
97    fn finish_functions(&mut self, iface: &Interface, dir: Direction) {
98        drop((iface, dir));
99    }
100
101    fn finish_one(&mut self, iface: &Interface, files: &mut Files);
102
103    fn finish_all(&mut self, files: &mut Files) {
104        drop(files);
105    }
106
107    fn generate_one(&mut self, iface: &Interface, dir: Direction, files: &mut Files) {
108        self.preprocess_one(iface, dir);
109
110        for (id, ty) in iface.types.iter() {
111            // assert!(ty.foreign_module.is_none()); // TODO
112            let name = match &ty.name {
113                Some(name) => name,
114                None => continue,
115            };
116            match &ty.kind {
117                TypeDefKind::Record(record) => self.type_record(iface, id, name, record, &ty.docs),
118                TypeDefKind::Flags(flags) => self.type_flags(iface, id, name, flags, &ty.docs),
119                TypeDefKind::Tuple(tuple) => self.type_tuple(iface, id, name, tuple, &ty.docs),
120                TypeDefKind::Enum(enum_) => self.type_enum(iface, id, name, enum_, &ty.docs),
121                TypeDefKind::Variant(variant) => {
122                    self.type_variant(iface, id, name, variant, &ty.docs)
123                }
124                TypeDefKind::Option(t) => self.type_option(iface, id, name, t, &ty.docs),
125                TypeDefKind::Expected(e) => self.type_expected(iface, id, name, e, &ty.docs),
126                TypeDefKind::Union(u) => self.type_union(iface, id, name, u, &ty.docs),
127                TypeDefKind::List(t) => self.type_list(iface, id, name, t, &ty.docs),
128                TypeDefKind::Type(t) => self.type_alias(iface, id, name, t, &ty.docs),
129                TypeDefKind::Future(_) => todo!("generate for future"),
130                TypeDefKind::Stream(_) => todo!("generate for stream"),
131            }
132        }
133
134        for (id, _resource) in iface.resources.iter() {
135            self.type_resource(iface, id);
136        }
137
138        self.preprocess_functions(iface, dir);
139
140        for f in iface.functions.iter() {
141            match dir {
142                Direction::Import => self.import(iface, f),
143                Direction::Export => self.export(iface, f),
144            }
145        }
146
147        self.finish_functions(iface, dir);
148
149        self.finish_one(iface, files)
150    }
151
152    fn generate_all(&mut self, imports: &[Interface], exports: &[Interface], files: &mut Files) {
153        self.preprocess_all(imports, exports);
154
155        for imp in imports {
156            self.generate_one(imp, Direction::Import, files);
157        }
158
159        for exp in exports {
160            self.generate_one(exp, Direction::Export, files);
161        }
162
163        self.finish_all(files);
164    }
165}
166
167#[derive(Default)]
168pub struct Types {
169    type_info: HashMap<TypeId, TypeInfo>,
170}
171
172#[derive(Default, Clone, Copy)]
173pub struct TypeInfo {
174    /// Whether or not this type is ever used (transitively) within the
175    /// parameter of a function.
176    pub param: bool,
177
178    /// Whether or not this type is ever used (transitively) within the
179    /// result of a function.
180    pub result: bool,
181
182    /// Whether or not this type (transitively) has a list.
183    pub has_list: bool,
184
185    /// Whether or not this type (transitively) has a handle.
186    pub has_handle: bool,
187}
188
189impl std::ops::BitOrAssign for TypeInfo {
190    fn bitor_assign(&mut self, rhs: Self) {
191        self.param |= rhs.param;
192        self.result |= rhs.result;
193        self.has_list |= rhs.has_list;
194        self.has_handle |= rhs.has_handle;
195    }
196}
197
198impl Types {
199    pub fn analyze(&mut self, iface: &Interface) {
200        for (t, _) in iface.types.iter() {
201            self.type_id_info(iface, t);
202        }
203        for f in iface.functions.iter() {
204            for (_, ty) in f.params.iter() {
205                self.set_param_result_ty(iface, ty, true, false);
206            }
207            self.set_param_result_ty(iface, &f.result, false, true);
208        }
209    }
210
211    pub fn get(&self, id: TypeId) -> TypeInfo {
212        self.type_info[&id]
213    }
214
215    pub fn type_id_info(&mut self, iface: &Interface, ty: TypeId) -> TypeInfo {
216        if let Some(info) = self.type_info.get(&ty) {
217            return *info;
218        }
219        let mut info = TypeInfo::default();
220        match &iface.types[ty].kind {
221            TypeDefKind::Record(r) => {
222                for field in r.fields.iter() {
223                    info |= self.type_info(iface, &field.ty);
224                }
225            }
226            TypeDefKind::Tuple(t) => {
227                for ty in t.types.iter() {
228                    info |= self.type_info(iface, ty);
229                }
230            }
231            TypeDefKind::Flags(_) => {}
232            TypeDefKind::Enum(_) => {}
233            TypeDefKind::Variant(v) => {
234                for case in v.cases.iter() {
235                    info |= self.type_info(iface, &case.ty);
236                }
237            }
238            TypeDefKind::List(ty) => {
239                info = self.type_info(iface, ty);
240                info.has_list = true;
241            }
242            TypeDefKind::Type(ty) => {
243                info = self.type_info(iface, ty);
244            }
245            TypeDefKind::Option(ty) => {
246                info = self.type_info(iface, ty);
247            }
248            TypeDefKind::Expected(e) => {
249                info = self.type_info(iface, &e.ok);
250                info |= self.type_info(iface, &e.err);
251            }
252            TypeDefKind::Union(u) => {
253                for case in u.cases.iter() {
254                    info |= self.type_info(iface, &case.ty);
255                }
256            }
257            TypeDefKind::Future(ty) => {
258                info = self.type_info(iface, ty);
259            }
260            TypeDefKind::Stream(stream) => {
261                info = self.type_info(iface, &stream.element);
262                info |= self.type_info(iface, &stream.end);
263            }
264        }
265        self.type_info.insert(ty, info);
266        info
267    }
268
269    pub fn type_info(&mut self, iface: &Interface, ty: &Type) -> TypeInfo {
270        let mut info = TypeInfo::default();
271        match ty {
272            Type::Handle(_) => info.has_handle = true,
273            Type::String => info.has_list = true,
274            Type::Id(id) => return self.type_id_info(iface, *id),
275            _ => {}
276        }
277        info
278    }
279
280    fn set_param_result_id(&mut self, iface: &Interface, ty: TypeId, param: bool, result: bool) {
281        match &iface.types[ty].kind {
282            TypeDefKind::Record(r) => {
283                for field in r.fields.iter() {
284                    self.set_param_result_ty(iface, &field.ty, param, result)
285                }
286            }
287            TypeDefKind::Tuple(t) => {
288                for ty in t.types.iter() {
289                    self.set_param_result_ty(iface, ty, param, result)
290                }
291            }
292            TypeDefKind::Flags(_) => {}
293            TypeDefKind::Enum(_) => {}
294            TypeDefKind::Variant(v) => {
295                for case in v.cases.iter() {
296                    self.set_param_result_ty(iface, &case.ty, param, result)
297                }
298            }
299            TypeDefKind::List(ty) | TypeDefKind::Type(ty) | TypeDefKind::Option(ty) => {
300                self.set_param_result_ty(iface, ty, param, result)
301            }
302            TypeDefKind::Expected(e) => {
303                self.set_param_result_ty(iface, &e.ok, param, result);
304                self.set_param_result_ty(iface, &e.err, param, result);
305            }
306            TypeDefKind::Union(u) => {
307                for case in u.cases.iter() {
308                    self.set_param_result_ty(iface, &case.ty, param, result)
309                }
310            }
311            TypeDefKind::Future(ty) => self.set_param_result_ty(iface, ty, param, result),
312            TypeDefKind::Stream(stream) => {
313                self.set_param_result_ty(iface, &stream.element, param, result);
314                self.set_param_result_ty(iface, &stream.end, param, result);
315            }
316        }
317    }
318
319    fn set_param_result_ty(&mut self, iface: &Interface, ty: &Type, param: bool, result: bool) {
320        match ty {
321            Type::Id(id) => {
322                self.type_id_info(iface, *id);
323                let info = self.type_info.get_mut(id).unwrap();
324                if (param && !info.param) || (result && !info.result) {
325                    info.param = info.param || param;
326                    info.result = info.result || result;
327                    self.set_param_result_id(iface, *id, param, result);
328                }
329            }
330            _ => {}
331        }
332    }
333}
334
335#[derive(Default)]
336pub struct Files {
337    files: BTreeMap<String, Vec<u8>>,
338}
339
340impl Files {
341    pub fn push(&mut self, name: &str, contents: &[u8]) {
342        match self.files.entry(name.to_owned()) {
343            Entry::Vacant(entry) => {
344                entry.insert(contents.to_owned());
345            }
346            Entry::Occupied(ref mut entry) => {
347                entry.get_mut().extend_from_slice(contents);
348            }
349        }
350    }
351
352    pub fn iter(&self) -> impl Iterator<Item = (&'_ str, &'_ [u8])> {
353        self.files.iter().map(|p| (p.0.as_str(), p.1.as_slice()))
354    }
355}
356
357pub fn load(path: impl AsRef<Path>) -> Result<Interface> {
358    Interface::parse_file(path)
359}
360
361#[derive(Default)]
362pub struct Source {
363    s: String,
364    indent: usize,
365}
366
367impl Source {
368    pub fn push_str(&mut self, src: &str) {
369        let lines = src.lines().collect::<Vec<_>>();
370        for (i, line) in lines.iter().enumerate() {
371            let trimmed = line.trim();
372            if trimmed.starts_with('}') && self.s.ends_with("  ") {
373                self.s.pop();
374                self.s.pop();
375            }
376            self.s.push_str(if lines.len() == 1 {
377                line
378            } else {
379                line.trim_start()
380            });
381            if trimmed.ends_with('{') {
382                self.indent += 1;
383            }
384            if trimmed.starts_with('}') {
385                self.indent -= 1;
386            }
387            if i != lines.len() - 1 || src.ends_with('\n') {
388                self.newline();
389            }
390        }
391    }
392
393    pub fn indent(&mut self, amt: usize) {
394        self.indent += amt;
395    }
396
397    pub fn deindent(&mut self, amt: usize) {
398        self.indent -= amt;
399    }
400
401    fn newline(&mut self) {
402        self.s.push('\n');
403        for _ in 0..self.indent {
404            self.s.push_str("  ");
405        }
406    }
407
408    pub fn as_mut_string(&mut self) -> &mut String {
409        &mut self.s
410    }
411}
412
413impl Write for Source {
414    fn write_str(&mut self, s: &str) -> fmt::Result {
415        self.push_str(s);
416        Ok(())
417    }
418}
419
420impl Deref for Source {
421    type Target = str;
422    fn deref(&self) -> &str {
423        &self.s
424    }
425}
426
427impl From<Source> for String {
428    fn from(s: Source) -> String {
429        s.s
430    }
431}
432
433/// Calls [`write!`] with the passed arguments and unwraps the result.
434///
435/// Useful for writing to things with infallible `Write` implementations like
436/// `Source` and `String`.
437///
438/// [`write!`]: std::write
439#[macro_export]
440macro_rules! uwrite {
441    ($dst:expr, $($arg:tt)*) => {
442        write!($dst, $($arg)*).unwrap()
443    };
444}
445
446/// Calls [`writeln!`] with the passed arguments and unwraps the result.
447///
448/// Useful for writing to things with infallible `Write` implementations like
449/// `Source` and `String`.
450///
451/// [`writeln!`]: std::writeln
452#[macro_export]
453macro_rules! uwriteln {
454    ($dst:expr, $($arg:tt)*) => {
455        writeln!($dst, $($arg)*).unwrap()
456    };
457}
458
459#[cfg(test)]
460mod tests {
461    use super::{Generator, Source};
462
463    #[test]
464    fn simple_append() {
465        let mut s = Source::default();
466        s.push_str("x");
467        assert_eq!(s.s, "x");
468        s.push_str("y");
469        assert_eq!(s.s, "xy");
470        s.push_str("z ");
471        assert_eq!(s.s, "xyz ");
472        s.push_str(" a ");
473        assert_eq!(s.s, "xyz  a ");
474        s.push_str("\na");
475        assert_eq!(s.s, "xyz  a \na");
476    }
477
478    #[test]
479    fn newline_remap() {
480        let mut s = Source::default();
481        s.push_str("function() {\n");
482        s.push_str("y\n");
483        s.push_str("}\n");
484        assert_eq!(s.s, "function() {\n  y\n}\n");
485    }
486
487    #[test]
488    fn if_else() {
489        let mut s = Source::default();
490        s.push_str("if() {\n");
491        s.push_str("y\n");
492        s.push_str("} else if () {\n");
493        s.push_str("z\n");
494        s.push_str("}\n");
495        assert_eq!(s.s, "if() {\n  y\n} else if () {\n  z\n}\n");
496    }
497
498    #[test]
499    fn trim_ws() {
500        let mut s = Source::default();
501        s.push_str(
502            "function() {
503                x
504        }",
505        );
506        assert_eq!(s.s, "function() {\n  x\n}");
507    }
508
509    #[test]
510    fn generator_is_object_safe() {
511        fn _assert(_: &dyn Generator) {}
512    }
513}