Skip to main content

wit_bindgen_core/
lib.rs

1use std::fmt::Write;
2
3use anyhow::Result;
4pub use wit_parser;
5use wit_parser::*;
6pub mod abi;
7mod ns;
8pub use ns::Ns;
9pub mod source;
10pub use source::{Files, Source};
11mod types;
12pub use types::{TypeInfo, Types};
13mod path;
14pub use path::name_package_module;
15mod async_;
16pub use async_::AsyncFilterSet;
17mod chainable_method;
18pub use chainable_method::{ChainableMethodFilterSet, ChainingMode};
19
20#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
21pub enum Direction {
22    #[default]
23    Import,
24    Export,
25}
26
27pub trait WorldGenerator {
28    fn generate(&mut self, resolve: &mut Resolve, id: WorldId, files: &mut Files) -> Result<()> {
29        if self.uses_nominal_type_ids() {
30            resolve.generate_nominal_type_ids(id);
31        }
32        let world = &resolve.worlds[id];
33        self.preprocess(resolve, id)?;
34
35        fn unwrap_name(key: &WorldKey) -> &str {
36            match key {
37                WorldKey::Name(name) => name,
38                WorldKey::Interface(_) => panic!("unexpected interface key"),
39            }
40        }
41
42        let mut funcs = Vec::new();
43        let mut types = Vec::new();
44        for (name, import) in world.imports.iter() {
45            match import {
46                WorldItem::Function(f) => funcs.push((unwrap_name(name), f)),
47                WorldItem::Interface { id, .. } => {
48                    self.import_interface(resolve, name, *id, files)?
49                }
50                WorldItem::Type { id, .. } => types.push((unwrap_name(name), *id)),
51            }
52        }
53        if !types.is_empty() {
54            self.import_types(resolve, id, &types, files);
55        }
56        if !funcs.is_empty() {
57            self.import_funcs(resolve, id, &funcs, files);
58        }
59        funcs.clear();
60
61        self.finish_imports(resolve, id, files);
62
63        // First generate bindings for any freestanding functions, if any. If
64        // these refer to types defined in the world they need to refer to the
65        // imported types generated above.
66        //
67        // Interfaces are then generated afterwards so if the same interface is
68        // both imported and exported the right types are all used everywhere.
69        let mut interfaces = Vec::new();
70        for (name, export) in world.exports.iter() {
71            match export {
72                WorldItem::Function(f) => funcs.push((unwrap_name(name), f)),
73                WorldItem::Interface { id, .. } => interfaces.push((name, id)),
74                WorldItem::Type { .. } => unreachable!(),
75            }
76        }
77        if !funcs.is_empty() {
78            self.export_funcs(resolve, id, &funcs, files)?;
79        }
80
81        self.pre_export_interface(resolve, files)?;
82
83        for (name, id) in interfaces {
84            self.export_interface(resolve, name, *id, files)?;
85        }
86        self.finish(resolve, id, files)
87    }
88
89    /// Whether or not this bindings generator expects
90    /// [`Resolve::generate_nominal_type_ids`] to be used before generating
91    /// bindings.
92    fn uses_nominal_type_ids(&self) -> bool {
93        true
94    }
95
96    fn finish_imports(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) {
97        let _ = (resolve, world, files);
98    }
99
100    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) -> Result<()> {
101        let _ = (resolve, world);
102        Ok(())
103    }
104
105    fn import_interface(
106        &mut self,
107        resolve: &Resolve,
108        name: &WorldKey,
109        iface: InterfaceId,
110        files: &mut Files,
111    ) -> Result<()>;
112
113    /// Called before any exported interfaces are generated.
114    fn pre_export_interface(&mut self, resolve: &Resolve, files: &mut Files) -> Result<()> {
115        let _ = (resolve, files);
116        Ok(())
117    }
118
119    fn export_interface(
120        &mut self,
121        resolve: &Resolve,
122        name: &WorldKey,
123        iface: InterfaceId,
124        files: &mut Files,
125    ) -> Result<()>;
126    fn import_funcs(
127        &mut self,
128        resolve: &Resolve,
129        world: WorldId,
130        funcs: &[(&str, &Function)],
131        files: &mut Files,
132    );
133    fn export_funcs(
134        &mut self,
135        resolve: &Resolve,
136        world: WorldId,
137        funcs: &[(&str, &Function)],
138        files: &mut Files,
139    ) -> Result<()>;
140    fn import_types(
141        &mut self,
142        resolve: &Resolve,
143        world: WorldId,
144        types: &[(&str, TypeId)],
145        files: &mut Files,
146    );
147    fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()>;
148}
149
150/// This is a possible replacement for the `Generator` trait above, currently
151/// only used by the JS bindings for generating bindings for a component.
152///
153/// The current plan is to see how things shake out with worlds and various
154/// other generators to see if everything can be updated to a less
155/// per-`*.wit`-file centric interface in the future. Even this will probably
156/// change for JS though. In any case it's something that was useful for JS and
157/// is suitable to replace otherwise at any time.
158pub trait InterfaceGenerator<'a> {
159    fn resolve(&self) -> &'a Resolve;
160
161    fn type_record(&mut self, id: TypeId, name: &str, record: &Record, docs: &Docs);
162    fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs);
163    fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs);
164    fn type_tuple(&mut self, id: TypeId, name: &str, tuple: &Tuple, docs: &Docs);
165    fn type_variant(&mut self, id: TypeId, name: &str, variant: &Variant, docs: &Docs);
166    fn type_option(&mut self, id: TypeId, name: &str, payload: &Type, docs: &Docs);
167    fn type_result(&mut self, id: TypeId, name: &str, result: &Result_, docs: &Docs);
168    fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs);
169    fn type_alias(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);
170    fn type_list(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);
171    fn type_fixed_length_list(&mut self, id: TypeId, name: &str, ty: &Type, size: u32, docs: &Docs);
172    fn type_map(&mut self, id: TypeId, name: &str, key: &Type, value: &Type, docs: &Docs);
173    fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs);
174    fn type_future(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs);
175    fn type_stream(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs);
176    fn types(&mut self, iface: InterfaceId) {
177        let iface = &self.resolve().interfaces[iface];
178        for (name, id) in iface.types.iter() {
179            self.define_type(name, *id);
180        }
181    }
182
183    fn define_type(&mut self, name: &str, id: TypeId) {
184        define_type(self, name, id)
185    }
186}
187
188pub fn define_type<'a, T>(generator: &mut T, name: &str, id: TypeId)
189where
190    T: InterfaceGenerator<'a> + ?Sized,
191{
192    let ty = &generator.resolve().types[id];
193    match &ty.kind {
194        TypeDefKind::Record(record) => generator.type_record(id, name, record, &ty.docs),
195        TypeDefKind::Resource => generator.type_resource(id, name, &ty.docs),
196        TypeDefKind::Flags(flags) => generator.type_flags(id, name, flags, &ty.docs),
197        TypeDefKind::Tuple(tuple) => generator.type_tuple(id, name, tuple, &ty.docs),
198        TypeDefKind::Enum(enum_) => generator.type_enum(id, name, enum_, &ty.docs),
199        TypeDefKind::Variant(variant) => generator.type_variant(id, name, variant, &ty.docs),
200        TypeDefKind::Option(t) => generator.type_option(id, name, t, &ty.docs),
201        TypeDefKind::Result(r) => generator.type_result(id, name, r, &ty.docs),
202        TypeDefKind::List(t) => generator.type_list(id, name, t, &ty.docs),
203        TypeDefKind::Type(t) => generator.type_alias(id, name, t, &ty.docs),
204        TypeDefKind::Future(t) => generator.type_future(id, name, t, &ty.docs),
205        TypeDefKind::Stream(t) => generator.type_stream(id, name, t, &ty.docs),
206        TypeDefKind::Handle(_) => panic!("handle types do not require definition"),
207        TypeDefKind::FixedLengthList(t, size) => {
208            generator.type_fixed_length_list(id, name, t, *size, &ty.docs)
209        }
210        TypeDefKind::Map(key, value) => generator.type_map(id, name, key, value, &ty.docs),
211        TypeDefKind::Unknown => unreachable!(),
212    }
213}
214
215pub trait AnonymousTypeGenerator<'a> {
216    fn resolve(&self) -> &'a Resolve;
217
218    fn anonymous_type_handle(&mut self, id: TypeId, handle: &Handle, docs: &Docs);
219    fn anonymous_type_tuple(&mut self, id: TypeId, ty: &Tuple, docs: &Docs);
220    fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, docs: &Docs);
221    fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, docs: &Docs);
222    fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, docs: &Docs);
223    fn anonymous_type_fixed_length_list(&mut self, id: TypeId, ty: &Type, size: u32, docs: &Docs);
224    fn anonymous_type_map(&mut self, id: TypeId, key: &Type, value: &Type, docs: &Docs);
225    fn anonymous_type_future(&mut self, id: TypeId, ty: &Option<Type>, docs: &Docs);
226    fn anonymous_type_stream(&mut self, id: TypeId, ty: &Option<Type>, docs: &Docs);
227    fn anonymous_type_type(&mut self, id: TypeId, ty: &Type, docs: &Docs);
228
229    fn define_anonymous_type(&mut self, id: TypeId) {
230        let ty = &self.resolve().types[id];
231        match &ty.kind {
232            TypeDefKind::Flags(_)
233            | TypeDefKind::Record(_)
234            | TypeDefKind::Resource
235            | TypeDefKind::Enum(_)
236            | TypeDefKind::Variant(_) => {
237                unreachable!()
238            }
239            TypeDefKind::Type(t) => self.anonymous_type_type(id, t, &ty.docs),
240            TypeDefKind::Tuple(tuple) => self.anonymous_type_tuple(id, tuple, &ty.docs),
241            TypeDefKind::Option(t) => self.anonymous_type_option(id, t, &ty.docs),
242            TypeDefKind::Result(r) => self.anonymous_type_result(id, r, &ty.docs),
243            TypeDefKind::List(t) => self.anonymous_type_list(id, t, &ty.docs),
244            TypeDefKind::Future(f) => self.anonymous_type_future(id, f, &ty.docs),
245            TypeDefKind::Stream(s) => self.anonymous_type_stream(id, s, &ty.docs),
246            TypeDefKind::Handle(handle) => self.anonymous_type_handle(id, handle, &ty.docs),
247            TypeDefKind::FixedLengthList(t, size) => {
248                self.anonymous_type_fixed_length_list(id, t, *size, &ty.docs)
249            }
250            TypeDefKind::Map(key, value) => self.anonymous_type_map(id, key, value, &ty.docs),
251            TypeDefKind::Unknown => unreachable!(),
252        }
253    }
254}
255
256pub fn generated_preamble(src: &mut Source, version: &str) {
257    uwriteln!(src, "// Generated by `wit-bindgen` {version}. DO NOT EDIT!")
258}
259
260pub fn dealias(resolve: &Resolve, mut id: TypeId) -> TypeId {
261    loop {
262        match &resolve.types[id].kind {
263            TypeDefKind::Type(Type::Id(that_id)) => id = *that_id,
264            _ => break id,
265        }
266    }
267}