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 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 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 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
147pub 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}