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