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