1use crate::{
2 Enum, Flags, Ident, Interface, InterfaceItem, Package, PackageName, Params, Record, Resource,
3 ResourceFunc, Result_, StandaloneFunc, Tuple, Type, TypeDef, TypeDefKind, Variant, World,
4 WorldItem,
5};
6use id_arena::Id;
7use wit_parser::PackageId;
8
9pub fn packages_from_parsed(resolve: &wit_parser::Resolve) -> Vec<Package> {
10 let converter = Converter::new(resolve);
11 converter.convert()
12}
13
14struct Converter<'a> {
15 resolve: &'a wit_parser::Resolve,
16}
17
18impl<'a> Converter<'a> {
19 fn new(resolve: &'a wit_parser::Resolve) -> Self {
20 Self { resolve }
21 }
22
23 fn convert(&self) -> Vec<Package> {
24 self.resolve
25 .packages
26 .iter()
27 .map(|(p_id, p)| self.convert_package(p_id, p))
28 .collect()
29 }
30
31 fn convert_package(&self, package_id: PackageId, package: &wit_parser::Package) -> Package {
32 let mut output = Package::new(self.convert_package_name(&package.name));
33 for (_, id) in &package.interfaces {
34 let interface = self.resolve.interfaces.get(*id).unwrap();
35 output.interface(self.convert_interface(
36 package_id,
37 interface,
38 None,
39 wit_parser::TypeOwner::Interface(*id),
40 ));
41 }
42 for (_, id) in &package.worlds {
43 let world = self.resolve.worlds.get(*id).unwrap();
44 output.world(self.convert_world(package_id, world, wit_parser::TypeOwner::World(*id)));
45 }
46 output
47 }
48
49 fn convert_package_name(&self, package: &wit_parser::PackageName) -> PackageName {
50 PackageName::new(
51 package.namespace.clone(),
52 package.name.clone(),
53 package.version.clone(),
54 )
55 }
56
57 fn convert_world(
58 &self,
59 package_id: PackageId,
60 world: &wit_parser::World,
61 owner: wit_parser::TypeOwner,
62 ) -> World {
63 let mut output = World::new(world.name.clone());
64
65 for (key, item) in &world.imports {
66 match item {
67 wit_parser::WorldItem::Interface { id, .. } => {
68 let interface = self.resolve.interfaces.get(*id).unwrap();
69 let ident = self.interface_ident(package_id, Some(key), interface);
70
71 if interface.name.is_some() {
72 output.item(WorldItem::named_interface_import(ident))
73 } else {
74 output.item(WorldItem::inline_interface_import(self.convert_interface(
75 package_id,
76 interface,
77 Some(ident),
78 owner,
79 )))
80 }
81 }
82 wit_parser::WorldItem::Function(func) => {
83 if let Some(func) = self.standalone_func_convert(func) {
84 output.item(WorldItem::function_import(func));
85 }
86 }
87 wit_parser::WorldItem::Type { id, .. } => {
88 let (target, item, rename) = self.convert_world_item_type(package_id, *id);
89 output.use_type(target, item, rename)
90 }
91 }
92 }
93
94 for (key, item) in &world.exports {
95 match item {
96 wit_parser::WorldItem::Interface { id, .. } => {
97 let interface = self.resolve.interfaces.get(*id).unwrap();
98 let ident = self.interface_ident(package_id, Some(key), interface);
99 if interface.name.is_some() {
100 output.item(WorldItem::named_interface_export(ident));
101 } else {
102 output.item(WorldItem::inline_interface_export(self.convert_interface(
103 package_id,
104 interface,
105 Some(ident),
106 owner,
107 )));
108 }
109 }
110 wit_parser::WorldItem::Function(func) => {
111 if let Some(func) = self.standalone_func_convert(func) {
112 output.item(WorldItem::function_export(func));
113 }
114 }
115 wit_parser::WorldItem::Type { id, .. } => {
116 let (target, item, rename) = self.convert_world_item_type(package_id, *id);
117 output.use_type(target, item, rename)
118 }
119 }
120 }
121
122 output.uses_mut().sort();
123 output.items_mut().sort();
124
125 output
126 }
127
128 fn convert_world_item_type(
129 &self,
130 package_id: PackageId,
131 type_id: wit_parser::TypeId,
132 ) -> (Ident, Ident, Option<Ident>) {
133 let type_def = self.resolve.types.get(type_id).unwrap();
134 let underlying_type_def = self.underlying_type_def(&type_def);
135 let interface_ident = self
136 .type_def_owner_interface_ident(package_id, underlying_type_def)
137 .expect("Type not part of an interface");
138 let local_type_name = type_def.name.clone().unwrap();
139 let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
140 if underlying_local_type_name == local_type_name {
141 (interface_ident, local_type_name.into(), None)
142 } else {
143 (
144 interface_ident,
145 underlying_local_type_name.into(),
146 Some(local_type_name.into()),
147 )
148 }
149 }
150
151 fn convert_interface(
152 &self,
153 package_id: PackageId,
154 interface: &wit_parser::Interface,
155 inlined_name: Option<Ident>,
156 owner: wit_parser::TypeOwner,
157 ) -> Interface {
158 let mut output =
159 Interface::new(interface.name.clone().map(Ident::new).unwrap_or_else(|| {
160 inlined_name
161 .clone()
162 .expect("inlined interface must pass in inlined_name")
163 }));
164
165 for (_, func) in &interface.functions {
166 if let Some(func) = self.standalone_func_convert(func) {
167 output.items.push(InterfaceItem::Function(func));
168 }
169 }
170 for (_, type_id) in &interface.types {
171 let type_def = self.resolve.types.get(*type_id).unwrap();
172 let underlying_type_def = self.underlying_type_def(&type_def);
173
174 if underlying_type_def.owner == owner {
175 if let Some(type_def) = self.convert_type_def(type_def, *type_id) {
176 output.item(InterfaceItem::TypeDef(type_def));
177 }
178 } else {
179 let interface_ident = self
180 .type_def_owner_interface_ident(package_id, underlying_type_def)
181 .expect("Type not part of an interface");
182 let local_type_name = type_def.name.clone().unwrap();
183 let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
184 if underlying_local_type_name == local_type_name {
185 output.use_type(interface_ident, local_type_name, None);
186 } else {
187 output.use_type(
188 interface_ident,
189 underlying_local_type_name,
190 Some(local_type_name.into()),
191 );
192 }
193 }
194 }
195
196 output.uses_mut().sort();
197 output.items_mut().sort();
198
199 output
200 }
201
202 fn convert_type_def(
203 &self,
204 type_def: &wit_parser::TypeDef,
205 type_def_id: Id<wit_parser::TypeDef>,
206 ) -> Option<TypeDef> {
207 match &type_def.name {
208 None => None,
209 Some(name) => {
210 let kind = match &type_def.kind {
211 wit_parser::TypeDefKind::Record(record) => {
212 let output = self.convert_record(record);
213 TypeDefKind::Record(output)
214 }
215 wit_parser::TypeDefKind::Resource => {
216 let output = self.convert_resource(type_def_id, name, &type_def.owner);
217 TypeDefKind::Resource(output)
218 }
219 wit_parser::TypeDefKind::Flags(flags) => {
220 let output = self.convert_flags(flags);
221 TypeDefKind::Flags(output)
222 }
223 wit_parser::TypeDefKind::Variant(variant) => {
224 let output = self.convert_variant(variant);
225 TypeDefKind::Variant(output)
226 }
227 wit_parser::TypeDefKind::Enum(enum_) => {
228 let output = self.convert_enum(enum_);
229 TypeDefKind::Enum(output)
230 }
231 wit_parser::TypeDefKind::Future(ty) => {
232 TypeDefKind::Type(Type::future(self.convert_option_type(ty)))
233 }
234 wit_parser::TypeDefKind::Stream(ty) => {
235 TypeDefKind::Type(Type::stream(self.convert_option_type(ty)))
236 }
237 wit_parser::TypeDefKind::Option(ty) => {
239 let output = Type::option(self.convert_type(ty));
240 TypeDefKind::Type(output)
241 }
242 wit_parser::TypeDefKind::List(ty) => {
243 let output = Type::list(self.convert_type(ty));
244 TypeDefKind::Type(output)
245 }
246 wit_parser::TypeDefKind::Map(key, value) => {
247 let output = Type::map(self.convert_type(key), self.convert_type(value));
248 TypeDefKind::Type(output)
249 }
250 wit_parser::TypeDefKind::FixedLengthList(ty, size) => {
251 let output = Type::fixed_length_list(self.convert_type(ty), *size);
252 TypeDefKind::Type(output)
253 }
254 wit_parser::TypeDefKind::Handle(handle) => {
255 let output = self.handle_to_type(handle);
256 TypeDefKind::Type(output)
257 }
258 wit_parser::TypeDefKind::Result(result) => {
259 let output = Type::result(self.convert_result(result));
260 TypeDefKind::Type(output)
261 }
262 wit_parser::TypeDefKind::Tuple(tuple) => {
263 let output = Type::Tuple(self.convert_tuple(tuple));
264 TypeDefKind::Type(output)
265 }
266 wit_parser::TypeDefKind::Type(ty) => {
267 let output = self.convert_type(ty);
268 TypeDefKind::Type(output)
269 }
270 wit_parser::TypeDefKind::Unknown => unreachable!(),
271 };
272
273 Some(TypeDef::new(name.clone(), kind))
274 }
275 }
276 }
277
278 fn convert_option_type(&self, ty: &Option<wit_parser::Type>) -> Option<Type> {
279 ty.as_ref().map(|ty| self.convert_type(ty))
280 }
281
282 fn convert_type(&self, type_: &wit_parser::Type) -> Type {
283 match type_ {
284 wit_parser::Type::Bool => Type::Bool,
285 wit_parser::Type::U8 => Type::U8,
286 wit_parser::Type::U16 => Type::U16,
287 wit_parser::Type::U32 => Type::U32,
288 wit_parser::Type::U64 => Type::U64,
289 wit_parser::Type::S8 => Type::S8,
290 wit_parser::Type::S16 => Type::S16,
291 wit_parser::Type::S32 => Type::S32,
292 wit_parser::Type::S64 => Type::S64,
293 wit_parser::Type::F32 => Type::F32,
294 wit_parser::Type::F64 => Type::F64,
295 wit_parser::Type::Char => Type::Char,
296 wit_parser::Type::String => Type::String,
297 wit_parser::Type::ErrorContext => Type::ErrorContext,
298 wit_parser::Type::Id(id) => {
299 let type_def = self.resolve.types.get(*id).expect("Type not found");
300 match &type_def.name {
301 Some(name) => Type::named(name.clone()),
302 None => match &type_def.kind {
303 wit_parser::TypeDefKind::Tuple(tuple) => {
304 Type::Tuple(self.convert_tuple(tuple))
305 }
306 wit_parser::TypeDefKind::Option(type_) => {
307 Type::option(self.convert_type(type_))
308 }
309 wit_parser::TypeDefKind::Result(result) => {
310 Type::result(self.convert_result(result))
311 }
312 wit_parser::TypeDefKind::List(type_) => {
313 Type::list(self.convert_type(type_))
314 }
315 wit_parser::TypeDefKind::Map(key, value) => {
316 Type::map(self.convert_type(key), self.convert_type(value))
317 }
318 wit_parser::TypeDefKind::FixedLengthList(type_, size) => {
319 Type::fixed_length_list(self.convert_type(type_), *size)
320 }
321 wit_parser::TypeDefKind::Handle(handle) => self.handle_to_type(handle),
322 wit_parser::TypeDefKind::Future(type_) => {
323 Type::future(self.convert_option_type(type_))
324 }
325 wit_parser::TypeDefKind::Stream(type_) => {
326 Type::stream(self.convert_option_type(type_))
327 }
328 wit_parser::TypeDefKind::Record(_)
329 | wit_parser::TypeDefKind::Resource
330 | wit_parser::TypeDefKind::Flags(_)
331 | wit_parser::TypeDefKind::Variant(_)
332 | wit_parser::TypeDefKind::Enum(_)
333 | wit_parser::TypeDefKind::Type(_) => {
334 panic!("type doesn't have a name, and can't be inlined")
335 }
336 wit_parser::TypeDefKind::Unknown => unreachable!(),
337 },
338 }
339 }
340 }
341 }
342
343 fn convert_enum(&self, enum_: &wit_parser::Enum) -> Enum {
344 let mut output = Enum::empty();
345 for case in &enum_.cases {
346 output.case(case.name.clone())
347 }
348 output
349 }
350 fn convert_record(&self, record: &wit_parser::Record) -> Record {
351 Record::new(record.fields.iter().map(|field| {
352 let name = field.name.clone();
353 let type_ = self.convert_type(&field.ty);
354 (name, type_)
355 }))
356 }
357 fn convert_variant(&self, variant: &wit_parser::Variant) -> Variant {
358 let mut output = Variant::empty();
359 for case in &variant.cases {
360 match &case.ty {
361 Some(ty) => {
362 let ty = self.convert_type(ty);
363 output.case((case.name.clone(), ty))
364 }
365 None => output.case((case.name.clone(),)),
366 }
367 }
368 output
369 }
370 fn convert_flags(&self, flags: &wit_parser::Flags) -> Flags {
371 Flags::new(flags.flags.iter().map(|flag| (flag.name.clone(),)))
372 }
373
374 fn convert_resource(
375 &self,
376 resource_id: Id<wit_parser::TypeDef>,
377 name: &str,
378 owner: &wit_parser::TypeOwner,
379 ) -> Resource {
380 let functions = match owner {
381 wit_parser::TypeOwner::World(_) => {
382 todo!("Enable once win-encoder supports `include`")
383 }
384 wit_parser::TypeOwner::Interface(id) => {
385 &self.resolve.interfaces.get(*id).unwrap().functions
386 }
387 wit_parser::TypeOwner::None => panic!("Resource has to have an owner"),
388 };
389
390 let mut output = Resource::empty();
391 for (_, func) in functions {
392 if let Some(method) = self.convert_resource_func(resource_id, name, func) {
393 output.func(method);
394 }
395 }
396 output
397 }
398
399 fn convert_resource_func(
400 &self,
401 resource_id: Id<wit_parser::TypeDef>,
402 resource_name: &str,
403 func: &wit_parser::Function,
404 ) -> Option<ResourceFunc> {
405 let mut skip_first_param = false;
407 let mut with_returns = true;
408 let mut method = match func.kind {
409 wit_parser::FunctionKind::Freestanding
410 | wit_parser::FunctionKind::AsyncFreestanding => return None,
411 wit_parser::FunctionKind::Method(id) | wit_parser::FunctionKind::AsyncMethod(id) => {
412 if id != resource_id {
413 return None;
414 }
415 skip_first_param = true;
416 let name = clean_func_name(resource_name, &func.name);
417 let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncMethod(_));
418 ResourceFunc::method(name, async_)
419 }
420 wit_parser::FunctionKind::Static(id) | wit_parser::FunctionKind::AsyncStatic(id) => {
421 if id != resource_id {
422 return None;
423 }
424 let name = clean_func_name(resource_name, &func.name);
425 let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncStatic(_));
426 ResourceFunc::static_(name, async_)
427 }
428 wit_parser::FunctionKind::Constructor(id) => {
429 if id != resource_id {
430 return None;
431 }
432 with_returns = !func.is_constructor_shorthand(self.resolve);
433 ResourceFunc::constructor()
434 }
435 };
436
437 method.set_params(self.convert_params(&func.params));
438 if skip_first_param {
439 method.params_mut().items_mut().remove(0);
440 }
441
442 if with_returns {
443 method.set_result(func.result.as_ref().map(|ty| self.convert_type(ty)));
444 }
445
446 Some(method)
447 }
448
449 fn standalone_func_convert(&self, func: &wit_parser::Function) -> Option<StandaloneFunc> {
450 match func.kind {
451 wit_parser::FunctionKind::Method(_)
452 | wit_parser::FunctionKind::AsyncMethod(_)
453 | wit_parser::FunctionKind::Static(_)
454 | wit_parser::FunctionKind::AsyncStatic(_)
455 | wit_parser::FunctionKind::Constructor(_) => None,
456 wit_parser::FunctionKind::Freestanding
457 | wit_parser::FunctionKind::AsyncFreestanding => {
458 let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncFreestanding);
459 let mut output = StandaloneFunc::new(func.name.clone(), async_);
460
461 output.set_params(self.convert_params(&func.params));
462 output.set_result(func.result.map(|ty| self.convert_type(&ty)));
463
464 Some(output)
465 }
466 }
467 }
468
469 fn convert_params(&self, params: &[wit_parser::Param]) -> Params {
470 let mut output = Params::empty();
471 for param in params.iter() {
472 let name = param.name.to_string();
473 let ty = self.convert_type(¶m.ty);
474 output.push(name, ty);
475 }
476 output
477 }
478
479 fn handle_to_type(&self, handle: &wit_parser::Handle) -> Type {
480 let id = match handle {
481 wit_parser::Handle::Own(id) => id,
482 wit_parser::Handle::Borrow(id) => id,
483 };
484 let type_def = self.resolve.types.get(*id).expect("Type not found");
485 let name = type_def
486 .name
487 .clone()
488 .expect("Handles should only be for resources, and resources should have names");
489 match handle {
490 wit_parser::Handle::Own(_) => Type::named(name),
491 wit_parser::Handle::Borrow(_) => Type::borrow(name),
492 }
493 }
494
495 fn convert_result(&self, result: &wit_parser::Result_) -> Result_ {
496 match (&result.ok, &result.err) {
497 (None, None) => Result_::empty(),
498 (Some(ok), None) => Result_::ok(self.convert_type(ok)),
499 (None, Some(err)) => Result_::err(self.convert_type(err)),
500 (Some(ok), Some(err)) => Result_::both(self.convert_type(ok), self.convert_type(err)),
501 }
502 }
503
504 fn convert_tuple(&self, tuple: &wit_parser::Tuple) -> Tuple {
505 let mut output = Tuple::empty();
506 for ty in tuple.types.iter() {
507 output.types_mut().push(self.convert_type(ty));
508 }
509 output
510 }
511
512 fn interface_ident(
513 &self,
514 package_id: PackageId,
515 world_key: Option<&wit_parser::WorldKey>,
516 interface: &wit_parser::Interface,
517 ) -> Ident {
518 match &interface.name {
519 Some(name) => {
520 if interface.package == Some(package_id) {
522 Ident::new(name.clone())
523 } else {
524 let package = interface
525 .package
526 .map(|package_id| self.resolve.packages.get(package_id).unwrap());
527
528 match package {
529 Some(package) => Ident::new(format!(
530 "{}:{}/{}{}",
531 package.name.namespace,
532 package.name.name,
533 name,
534 package
535 .name
536 .version
537 .as_ref()
538 .map(|version| format!("@{version}"))
539 .unwrap_or_else(|| "".to_string())
540 )),
541 None => Ident::new(name.clone()),
542 }
543 }
544 }
545 None => match world_key {
546 Some(world_key) => match world_key {
547 wit_parser::WorldKey::Name(name) => Ident::new(name.clone()),
548 wit_parser::WorldKey::Interface(_) => {
549 unreachable!("inlined interface must have a world key name")
550 }
551 },
552 None => panic!("inlined interface requires a world key"),
553 },
554 }
555 }
556
557 fn underlying_type_def(&'a self, type_def: &'a wit_parser::TypeDef) -> &'a wit_parser::TypeDef {
558 match &type_def.kind {
559 wit_parser::TypeDefKind::Type(type_) => match &type_ {
560 wit_parser::Type::Id(type_id) => {
561 let type_def = self.resolve.types.get(*type_id).unwrap();
562 type_def
563 }
564 _ => type_def,
565 },
566 _ => type_def,
567 }
568 }
569
570 fn type_def_owner_interface_ident(
571 &self,
572 package_id: PackageId,
573 type_def: &wit_parser::TypeDef,
574 ) -> Option<Ident> {
575 if let wit_parser::TypeOwner::Interface(id) = type_def.owner {
576 Some(self.interface_ident(package_id, None, self.resolve.interfaces.get(id).unwrap()))
577 } else {
578 None
579 }
580 }
581}
582
583fn clean_func_name(resource_name: &str, method_name: &str) -> String {
584 const METHOD_PREFIX: &str = "[method]";
585 const STATIC_PREFIX: &str = "[static]";
586
587 let method_name = method_name
588 .strip_prefix(METHOD_PREFIX)
589 .unwrap_or(method_name);
590 let method_name = method_name
591 .strip_prefix(STATIC_PREFIX)
592 .unwrap_or(method_name);
593 let method_name = method_name.strip_prefix(resource_name).unwrap();
594 let method_name = method_name.strip_prefix(".").unwrap();
595 method_name.to_string()
596}