wit_encoder/
from_parser.rs

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(type_id) => {
88                    let (target, item, rename) = self.convert_world_item_type(package_id, *type_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(type_id) => {
116                    let (target, item, rename) = self.convert_world_item_type(package_id, *type_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                    // all the following are just `type` declarations
238                    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::FixedSizeList(ty, size) => {
247                        let output = Type::fixed_size_list(self.convert_type(ty), *size);
248                        TypeDefKind::Type(output)
249                    }
250                    wit_parser::TypeDefKind::Handle(handle) => {
251                        let output = self.handle_to_type(handle);
252                        TypeDefKind::Type(output)
253                    }
254                    wit_parser::TypeDefKind::Result(result) => {
255                        let output = Type::result(self.convert_result(result));
256                        TypeDefKind::Type(output)
257                    }
258                    wit_parser::TypeDefKind::Tuple(tuple) => {
259                        let output = Type::Tuple(self.convert_tuple(tuple));
260                        TypeDefKind::Type(output)
261                    }
262                    wit_parser::TypeDefKind::Type(ty) => {
263                        let output = self.convert_type(ty);
264                        TypeDefKind::Type(output)
265                    }
266                    wit_parser::TypeDefKind::Unknown => unreachable!(),
267                };
268
269                Some(TypeDef::new(name.clone(), kind))
270            }
271        }
272    }
273
274    fn convert_option_type(&self, ty: &Option<wit_parser::Type>) -> Option<Type> {
275        ty.as_ref().map(|ty| self.convert_type(ty))
276    }
277
278    fn convert_type(&self, type_: &wit_parser::Type) -> Type {
279        match type_ {
280            wit_parser::Type::Bool => Type::Bool,
281            wit_parser::Type::U8 => Type::U8,
282            wit_parser::Type::U16 => Type::U16,
283            wit_parser::Type::U32 => Type::U32,
284            wit_parser::Type::U64 => Type::U64,
285            wit_parser::Type::S8 => Type::S8,
286            wit_parser::Type::S16 => Type::S16,
287            wit_parser::Type::S32 => Type::S32,
288            wit_parser::Type::S64 => Type::S64,
289            wit_parser::Type::F32 => Type::F32,
290            wit_parser::Type::F64 => Type::F64,
291            wit_parser::Type::Char => Type::Char,
292            wit_parser::Type::String => Type::String,
293            wit_parser::Type::ErrorContext => Type::ErrorContext,
294            wit_parser::Type::Id(id) => {
295                let type_def = self.resolve.types.get(*id).expect("Type not found");
296                match &type_def.name {
297                    Some(name) => Type::named(name.clone()),
298                    None => match &type_def.kind {
299                        wit_parser::TypeDefKind::Tuple(tuple) => {
300                            Type::Tuple(self.convert_tuple(tuple))
301                        }
302                        wit_parser::TypeDefKind::Option(type_) => {
303                            Type::option(self.convert_type(type_))
304                        }
305                        wit_parser::TypeDefKind::Result(result) => {
306                            Type::result(self.convert_result(result))
307                        }
308                        wit_parser::TypeDefKind::List(type_) => {
309                            Type::list(self.convert_type(type_))
310                        }
311                        wit_parser::TypeDefKind::FixedSizeList(type_, size) => {
312                            Type::fixed_size_list(self.convert_type(type_), *size)
313                        }
314                        wit_parser::TypeDefKind::Handle(handle) => self.handle_to_type(handle),
315                        wit_parser::TypeDefKind::Future(type_) => {
316                            Type::future(self.convert_option_type(type_))
317                        }
318                        wit_parser::TypeDefKind::Stream(type_) => {
319                            Type::stream(self.convert_option_type(type_))
320                        }
321                        wit_parser::TypeDefKind::Record(_)
322                        | wit_parser::TypeDefKind::Resource
323                        | wit_parser::TypeDefKind::Flags(_)
324                        | wit_parser::TypeDefKind::Variant(_)
325                        | wit_parser::TypeDefKind::Enum(_)
326                        | wit_parser::TypeDefKind::Type(_) => {
327                            panic!("type doesn't have a name, and can't be inlined")
328                        }
329                        wit_parser::TypeDefKind::Unknown => unreachable!(),
330                    },
331                }
332            }
333        }
334    }
335
336    fn convert_enum(&self, enum_: &wit_parser::Enum) -> Enum {
337        let mut output = Enum::empty();
338        for case in &enum_.cases {
339            output.case(case.name.clone())
340        }
341        output
342    }
343    fn convert_record(&self, record: &wit_parser::Record) -> Record {
344        Record::new(record.fields.iter().map(|field| {
345            let name = field.name.clone();
346            let type_ = self.convert_type(&field.ty);
347            (name, type_)
348        }))
349    }
350    fn convert_variant(&self, variant: &wit_parser::Variant) -> Variant {
351        let mut output = Variant::empty();
352        for case in &variant.cases {
353            match &case.ty {
354                Some(ty) => {
355                    let ty = self.convert_type(ty);
356                    output.case((case.name.clone(), ty))
357                }
358                None => output.case((case.name.clone(),)),
359            }
360        }
361        output
362    }
363    fn convert_flags(&self, flags: &wit_parser::Flags) -> Flags {
364        Flags::new(flags.flags.iter().map(|flag| (flag.name.clone(),)))
365    }
366
367    fn convert_resource(
368        &self,
369        resource_id: Id<wit_parser::TypeDef>,
370        name: &str,
371        owner: &wit_parser::TypeOwner,
372    ) -> Resource {
373        let functions = match owner {
374            wit_parser::TypeOwner::World(_) => {
375                todo!("Enable once win-encoder supports `include`")
376            }
377            wit_parser::TypeOwner::Interface(id) => {
378                &self.resolve.interfaces.get(*id).unwrap().functions
379            }
380            wit_parser::TypeOwner::None => panic!("Resource has to have an owner"),
381        };
382
383        let mut output = Resource::empty();
384        for (_, func) in functions {
385            if let Some(method) = self.convert_resource_func(resource_id, name, func) {
386                output.func(method);
387            }
388        }
389        output
390    }
391
392    fn convert_resource_func(
393        &self,
394        resource_id: Id<wit_parser::TypeDef>,
395        resource_name: &str,
396        func: &wit_parser::Function,
397    ) -> Option<ResourceFunc> {
398        // skip first argument for methods, as they're just `self`.
399        let mut skip_first_param = false;
400        // constructors can't return anything
401        let mut with_returns = true;
402        let mut method = match func.kind {
403            wit_parser::FunctionKind::Freestanding
404            | wit_parser::FunctionKind::AsyncFreestanding => return None,
405            wit_parser::FunctionKind::Method(id) | wit_parser::FunctionKind::AsyncMethod(id) => {
406                if id != resource_id {
407                    return None;
408                }
409                skip_first_param = true;
410                let name = clean_func_name(resource_name, &func.name);
411                let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncMethod(_));
412                ResourceFunc::method(name, async_)
413            }
414            wit_parser::FunctionKind::Static(id) | wit_parser::FunctionKind::AsyncStatic(id) => {
415                if id != resource_id {
416                    return None;
417                }
418                let name = clean_func_name(resource_name, &func.name);
419                let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncStatic(_));
420                ResourceFunc::static_(name, async_)
421            }
422            wit_parser::FunctionKind::Constructor(id) => {
423                if id != resource_id {
424                    return None;
425                }
426                with_returns = false;
427                ResourceFunc::constructor()
428            }
429        };
430
431        method.set_params(self.convert_params(&func.params));
432        if skip_first_param {
433            method.params_mut().items_mut().remove(0);
434        }
435
436        if with_returns {
437            method.set_result(func.result.as_ref().map(|ty| self.convert_type(ty)));
438        }
439
440        Some(method)
441    }
442
443    fn standalone_func_convert(&self, func: &wit_parser::Function) -> Option<StandaloneFunc> {
444        match func.kind {
445            wit_parser::FunctionKind::Method(_)
446            | wit_parser::FunctionKind::AsyncMethod(_)
447            | wit_parser::FunctionKind::Static(_)
448            | wit_parser::FunctionKind::AsyncStatic(_)
449            | wit_parser::FunctionKind::Constructor(_) => None,
450            wit_parser::FunctionKind::Freestanding
451            | wit_parser::FunctionKind::AsyncFreestanding => {
452                let async_ = matches!(func.kind, wit_parser::FunctionKind::AsyncFreestanding);
453                let mut output = StandaloneFunc::new(func.name.clone(), async_);
454
455                output.set_params(self.convert_params(&func.params));
456                output.set_result(func.result.map(|ty| self.convert_type(&ty)));
457
458                Some(output)
459            }
460        }
461    }
462
463    fn convert_params(&self, params: &[(String, wit_parser::Type)]) -> Params {
464        let mut output = Params::empty();
465        for (name, ty) in params.iter() {
466            let name = name.to_string();
467            let ty = self.convert_type(ty);
468            output.push(name, ty);
469        }
470        output
471    }
472
473    fn handle_to_type(&self, handle: &wit_parser::Handle) -> Type {
474        let id = match handle {
475            wit_parser::Handle::Own(id) => id,
476            wit_parser::Handle::Borrow(id) => id,
477        };
478        let type_def = self.resolve.types.get(*id).expect("Type not found");
479        let name = type_def
480            .name
481            .clone()
482            .expect("Handles should only be for resources, and resources should have names");
483        match handle {
484            wit_parser::Handle::Own(_) => Type::named(name),
485            wit_parser::Handle::Borrow(_) => Type::borrow(name),
486        }
487    }
488
489    fn convert_result(&self, result: &wit_parser::Result_) -> Result_ {
490        match (&result.ok, &result.err) {
491            (None, None) => Result_::empty(),
492            (Some(ok), None) => Result_::ok(self.convert_type(ok)),
493            (None, Some(err)) => Result_::err(self.convert_type(err)),
494            (Some(ok), Some(err)) => Result_::both(self.convert_type(ok), self.convert_type(err)),
495        }
496    }
497
498    fn convert_tuple(&self, tuple: &wit_parser::Tuple) -> Tuple {
499        let mut output = Tuple::empty();
500        for ty in tuple.types.iter() {
501            output.types_mut().push(self.convert_type(ty));
502        }
503        output
504    }
505
506    fn interface_ident(
507        &self,
508        package_id: PackageId,
509        world_key: Option<&wit_parser::WorldKey>,
510        interface: &wit_parser::Interface,
511    ) -> Ident {
512        match &interface.name {
513            Some(name) => {
514                // Standalone
515                if interface.package == Some(package_id) {
516                    Ident::new(name.clone())
517                } else {
518                    let package = interface
519                        .package
520                        .map(|package_id| self.resolve.packages.get(package_id).unwrap());
521
522                    match package {
523                        Some(package) => Ident::new(format!(
524                            "{}:{}/{}{}",
525                            package.name.namespace,
526                            package.name.name,
527                            name,
528                            package
529                                .name
530                                .version
531                                .as_ref()
532                                .map(|version| format!("@{version}"))
533                                .unwrap_or_else(|| "".to_string())
534                        )),
535                        None => Ident::new(name.clone()),
536                    }
537                }
538            }
539            None => match world_key {
540                Some(world_key) => match world_key {
541                    wit_parser::WorldKey::Name(name) => Ident::new(name.clone()),
542                    wit_parser::WorldKey::Interface(_) => {
543                        unreachable!("inlined interface must have a world key name")
544                    }
545                },
546                None => panic!("inlined interface requires a world key"),
547            },
548        }
549    }
550
551    fn underlying_type_def(&'a self, type_def: &'a wit_parser::TypeDef) -> &'a wit_parser::TypeDef {
552        match &type_def.kind {
553            wit_parser::TypeDefKind::Type(type_) => match &type_ {
554                wit_parser::Type::Id(type_id) => {
555                    let type_def = self.resolve.types.get(*type_id).unwrap();
556                    type_def
557                }
558                _ => type_def,
559            },
560            _ => type_def,
561        }
562    }
563
564    fn type_def_owner_interface_ident(
565        &self,
566        package_id: PackageId,
567        type_def: &wit_parser::TypeDef,
568    ) -> Option<Ident> {
569        if let wit_parser::TypeOwner::Interface(id) = type_def.owner {
570            Some(self.interface_ident(package_id, None, self.resolve.interfaces.get(id).unwrap()))
571        } else {
572            None
573        }
574    }
575}
576
577fn clean_func_name(resource_name: &str, method_name: &str) -> String {
578    const METHOD_PREFIX: &str = "[method]";
579    const STATIC_PREFIX: &str = "[static]";
580
581    let method_name = method_name
582        .strip_prefix(METHOD_PREFIX)
583        .unwrap_or(method_name);
584    let method_name = method_name
585        .strip_prefix(STATIC_PREFIX)
586        .unwrap_or(method_name);
587    let method_name = method_name.strip_prefix(resource_name).unwrap();
588    let method_name = method_name.strip_prefix(".").unwrap();
589    method_name.to_string()
590}