wasmer_wit_bindgen_gen_rust/
lib.rs

1use heck::*;
2use std::collections::HashMap;
3use std::fmt::{self, Write};
4use std::iter::zip;
5use wasmer_wit_bindgen_gen_core::wit_parser::abi::{Bitcast, LiftLower, WasmType};
6use wasmer_wit_bindgen_gen_core::{wit_parser::*, TypeInfo, Types};
7
8#[derive(Debug, Copy, Clone, PartialEq)]
9pub enum TypeMode {
10    Owned,
11    AllBorrowed(&'static str),
12    LeafBorrowed(&'static str),
13    HandlesBorrowed(&'static str),
14}
15
16pub trait RustGenerator {
17    fn push_str(&mut self, s: &str);
18    fn info(&self, ty: TypeId) -> TypeInfo;
19    fn types_mut(&mut self) -> &mut Types;
20    fn print_borrowed_slice(
21        &mut self,
22        iface: &Interface,
23        mutbl: bool,
24        ty: &Type,
25        lifetime: &'static str,
26    );
27    fn print_borrowed_str(&mut self, lifetime: &'static str);
28    fn default_param_mode(&self) -> TypeMode;
29    fn handle_projection(&self) -> Option<(&'static str, String)>;
30    fn handle_wrapper(&self) -> Option<&'static str>;
31    fn handle_in_super(&self) -> bool {
32        false
33    }
34
35    fn rustdoc(&mut self, docs: &Docs) {
36        let docs = match &docs.contents {
37            Some(docs) => docs,
38            None => return,
39        };
40        for line in docs.trim().lines() {
41            self.push_str("/// ");
42            self.push_str(line);
43            self.push_str("\n");
44        }
45    }
46
47    fn rustdoc_params(&mut self, docs: &[(String, Type)], header: &str) {
48        drop((docs, header));
49        // let docs = docs
50        //     .iter()
51        //     .filter(|param| param.docs.trim().len() > 0)
52        //     .collect::<Vec<_>>();
53        // if docs.len() == 0 {
54        //     return;
55        // }
56
57        // self.push_str("///\n");
58        // self.push_str("/// ## ");
59        // self.push_str(header);
60        // self.push_str("\n");
61        // self.push_str("///\n");
62
63        // for param in docs {
64        //     for (i, line) in param.docs.lines().enumerate() {
65        //         self.push_str("/// ");
66        //         // Currently wasi only has at most one return value, so there's no
67        //         // need to indent it or name it.
68        //         if header != "Return" {
69        //             if i == 0 {
70        //                 self.push_str("* `");
71        //                 self.push_str(to_rust_ident(param.name.as_str()));
72        //                 self.push_str("` - ");
73        //             } else {
74        //                 self.push_str("  ");
75        //             }
76        //         }
77        //         self.push_str(line);
78        //         self.push_str("\n");
79        //     }
80        // }
81    }
82
83    fn print_signature(
84        &mut self,
85        iface: &Interface,
86        func: &Function,
87        param_mode: TypeMode,
88        sig: &FnSig,
89    ) -> Vec<String> {
90        let params = self.print_docs_and_params(iface, func, param_mode, &sig);
91        self.push_str(" -> ");
92        self.print_ty(iface, &func.result, TypeMode::Owned);
93        params
94    }
95
96    fn print_docs_and_params(
97        &mut self,
98        iface: &Interface,
99        func: &Function,
100        param_mode: TypeMode,
101        sig: &FnSig,
102    ) -> Vec<String> {
103        self.rustdoc(&func.docs);
104        self.rustdoc_params(&func.params, "Parameters");
105        // TODO: re-add this when docs are back
106        // self.rustdoc_params(&func.results, "Return");
107
108        if !sig.private {
109            self.push_str("pub ");
110        }
111        if sig.unsafe_ {
112            self.push_str("unsafe ");
113        }
114        if sig.async_ {
115            self.push_str("async ");
116        }
117        self.push_str("fn ");
118        let func_name = if sig.use_item_name {
119            func.item_name()
120        } else {
121            &func.name
122        };
123        self.push_str(&to_rust_ident(&func_name));
124        if let Some(generics) = &sig.generics {
125            self.push_str(generics);
126        }
127        self.push_str("(");
128        if let Some(arg) = &sig.self_arg {
129            self.push_str(arg);
130            self.push_str(",");
131        }
132        let mut params = Vec::new();
133        for (i, (name, param)) in func.params.iter().enumerate() {
134            if i == 0 && sig.self_is_first_param {
135                params.push("self".to_string());
136                continue;
137            }
138            let name = to_rust_ident(name);
139            self.push_str(&name);
140            params.push(name);
141            self.push_str(": ");
142            self.print_ty(iface, param, param_mode);
143            self.push_str(",");
144        }
145        self.push_str(")");
146        params
147    }
148
149    fn print_ty(&mut self, iface: &Interface, ty: &Type, mode: TypeMode) {
150        match ty {
151            Type::Id(t) => self.print_tyid(iface, *t, mode),
152            Type::Handle(r) => {
153                let mut info = TypeInfo::default();
154                info.has_handle = true;
155                let lt = self.lifetime_for(&info, mode);
156                // Borrowed handles are always behind a reference since
157                // in that case we never take ownership of the handle.
158                if let Some(lt) = lt {
159                    self.push_str("&");
160                    if lt != "'_" {
161                        self.push_str(lt);
162                    }
163                    self.push_str(" ");
164                }
165
166                let suffix = match self.handle_wrapper() {
167                    Some(wrapper) => {
168                        self.push_str(wrapper);
169                        self.push_str("<");
170                        ">"
171                    }
172                    None => "",
173                };
174                if self.handle_in_super() {
175                    self.push_str("super::");
176                }
177                if let Some((proj, _)) = self.handle_projection() {
178                    self.push_str(proj);
179                    self.push_str("::");
180                }
181                self.push_str(&iface.resources[*r].name.to_camel_case());
182                self.push_str(suffix);
183            }
184
185            Type::Unit => self.push_str("()"),
186            Type::Bool => self.push_str("bool"),
187            Type::U8 => self.push_str("u8"),
188            Type::U16 => self.push_str("u16"),
189            Type::U32 => self.push_str("u32"),
190            Type::U64 => self.push_str("u64"),
191            Type::S8 => self.push_str("i8"),
192            Type::S16 => self.push_str("i16"),
193            Type::S32 => self.push_str("i32"),
194            Type::S64 => self.push_str("i64"),
195            Type::Float32 => self.push_str("f32"),
196            Type::Float64 => self.push_str("f64"),
197            Type::Char => self.push_str("char"),
198            Type::String => match mode {
199                TypeMode::AllBorrowed(lt) | TypeMode::LeafBorrowed(lt) => {
200                    self.print_borrowed_str(lt)
201                }
202                TypeMode::Owned | TypeMode::HandlesBorrowed(_) => self.push_str("String"),
203            },
204        }
205    }
206
207    fn print_tyid(&mut self, iface: &Interface, id: TypeId, mode: TypeMode) {
208        let info = self.info(id);
209        let lt = self.lifetime_for(&info, mode);
210        let ty = &iface.types[id];
211        if ty.name.is_some() {
212            let name = if lt.is_some() {
213                self.param_name(iface, id)
214            } else {
215                self.result_name(iface, id)
216            };
217            self.push_str(&name);
218
219            // If the type recursively owns data and it's a
220            // variant/record/list, then we need to place the
221            // lifetime parameter on the type as well.
222            if info.owns_data() && needs_generics(iface, &ty.kind) {
223                self.print_generics(&info, lt, false);
224            }
225
226            return;
227
228            fn needs_generics(iface: &Interface, ty: &TypeDefKind) -> bool {
229                match ty {
230                    TypeDefKind::Variant(_)
231                    | TypeDefKind::Record(_)
232                    | TypeDefKind::Option(_)
233                    | TypeDefKind::Expected(_)
234                    | TypeDefKind::Future(_)
235                    | TypeDefKind::Stream(_)
236                    | TypeDefKind::List(_)
237                    | TypeDefKind::Flags(_)
238                    | TypeDefKind::Enum(_)
239                    | TypeDefKind::Tuple(_)
240                    | TypeDefKind::Union(_) => true,
241                    TypeDefKind::Type(Type::Id(t)) => needs_generics(iface, &iface.types[*t].kind),
242                    TypeDefKind::Type(Type::String) => true,
243                    TypeDefKind::Type(Type::Handle(_)) => true,
244                    TypeDefKind::Type(_) => false,
245                }
246            }
247        }
248
249        match &ty.kind {
250            TypeDefKind::List(t) => self.print_list(iface, t, mode),
251
252            TypeDefKind::Option(t) => {
253                self.push_str("Option<");
254                self.print_ty(iface, t, mode);
255                self.push_str(">");
256            }
257
258            TypeDefKind::Expected(e) => {
259                self.push_str("Result<");
260                self.print_ty(iface, &e.ok, mode);
261                self.push_str(",");
262                self.print_ty(iface, &e.err, mode);
263                self.push_str(">");
264            }
265
266            TypeDefKind::Variant(_) => panic!("unsupported anonymous variant"),
267
268            // Tuple-like records are mapped directly to Rust tuples of
269            // types. Note the trailing comma after each member to
270            // appropriately handle 1-tuples.
271            TypeDefKind::Tuple(t) => {
272                self.push_str("(");
273                for ty in t.types.iter() {
274                    self.print_ty(iface, ty, mode);
275                    self.push_str(",");
276                }
277                self.push_str(")");
278            }
279            TypeDefKind::Record(_) => {
280                panic!("unsupported anonymous type reference: record")
281            }
282            TypeDefKind::Flags(_) => {
283                panic!("unsupported anonymous type reference: flags")
284            }
285            TypeDefKind::Enum(_) => {
286                panic!("unsupported anonymous type reference: enum")
287            }
288            TypeDefKind::Union(_) => {
289                panic!("unsupported anonymous type reference: union")
290            }
291            TypeDefKind::Future(ty) => {
292                self.push_str("Future<");
293                self.print_ty(iface, ty, mode);
294                self.push_str(">");
295            }
296            TypeDefKind::Stream(stream) => {
297                self.push_str("Stream<");
298                self.print_ty(iface, &stream.element, mode);
299                self.push_str(",");
300                self.print_ty(iface, &stream.end, mode);
301                self.push_str(">");
302            }
303
304            TypeDefKind::Type(t) => self.print_ty(iface, t, mode),
305        }
306    }
307
308    fn print_list(&mut self, iface: &Interface, ty: &Type, mode: TypeMode) {
309        match mode {
310            TypeMode::AllBorrowed(lt) => {
311                self.print_borrowed_slice(iface, false, ty, lt);
312            }
313            TypeMode::LeafBorrowed(lt) => {
314                if iface.all_bits_valid(ty) {
315                    self.print_borrowed_slice(iface, false, ty, lt);
316                } else {
317                    self.push_str("Vec<");
318                    self.print_ty(iface, ty, mode);
319                    self.push_str(">");
320                }
321            }
322            TypeMode::HandlesBorrowed(_) | TypeMode::Owned => {
323                self.push_str("Vec<");
324                self.print_ty(iface, ty, mode);
325                self.push_str(">");
326            }
327        }
328    }
329
330    fn print_rust_slice(
331        &mut self,
332        iface: &Interface,
333        mutbl: bool,
334        ty: &Type,
335        lifetime: &'static str,
336    ) {
337        self.push_str("&");
338        if lifetime != "'_" {
339            self.push_str(lifetime);
340            self.push_str(" ");
341        }
342        if mutbl {
343            self.push_str(" mut ");
344        }
345        self.push_str("[");
346        self.print_ty(iface, ty, TypeMode::AllBorrowed(lifetime));
347        self.push_str("]");
348    }
349
350    fn print_generics(&mut self, info: &TypeInfo, lifetime: Option<&str>, bound: bool) {
351        let proj = if info.has_handle {
352            self.handle_projection()
353        } else {
354            None
355        };
356        if lifetime.is_none() && proj.is_none() {
357            return;
358        }
359        self.push_str("<");
360        if let Some(lt) = lifetime {
361            self.push_str(lt);
362            self.push_str(",");
363        }
364        if let Some((proj, trait_bound)) = proj {
365            self.push_str(proj);
366            if bound {
367                self.push_str(": ");
368                self.push_str(&trait_bound);
369            }
370        }
371        self.push_str(">");
372    }
373
374    fn int_repr(&mut self, repr: Int) {
375        self.push_str(int_repr(repr));
376    }
377
378    fn wasm_type(&mut self, ty: WasmType) {
379        self.push_str(wasm_type(ty));
380    }
381
382    fn modes_of(
383        &self,
384        iface: &Interface,
385        ty: TypeId,
386        generate_struct_always: bool,
387    ) -> Vec<(String, TypeMode)> {
388        let info = self.info(ty);
389        let mut result = Vec::new();
390        if info.param || generate_struct_always {
391            result.push((self.param_name(iface, ty), self.default_param_mode()));
392        }
393        if info.result && (!(info.param || generate_struct_always) || self.uses_two_names(&info)) {
394            result.push((self.result_name(iface, ty), TypeMode::Owned));
395        }
396        return result;
397    }
398
399    /// Writes the camel-cased 'name' of the passed type to `out`, as used to name union variants.
400    fn write_name(&self, iface: &Interface, ty: &Type, out: &mut String) {
401        match ty {
402            Type::Unit => out.push_str("Unit"),
403            Type::Bool => out.push_str("Bool"),
404            Type::U8 => out.push_str("U8"),
405            Type::U16 => out.push_str("U16"),
406            Type::U32 => out.push_str("U32"),
407            Type::U64 => out.push_str("U64"),
408            Type::S8 => out.push_str("I8"),
409            Type::S16 => out.push_str("I16"),
410            Type::S32 => out.push_str("I32"),
411            Type::S64 => out.push_str("I64"),
412            Type::Float32 => out.push_str("F32"),
413            Type::Float64 => out.push_str("F64"),
414            Type::Char => out.push_str("Char"),
415            Type::String => out.push_str("String"),
416            Type::Handle(id) => out.push_str(&iface.resources[*id].name.to_camel_case()),
417            Type::Id(id) => {
418                let ty = &iface.types[*id];
419                match &ty.name {
420                    Some(name) => out.push_str(&name.to_camel_case()),
421                    None => match &ty.kind {
422                        TypeDefKind::Option(ty) => {
423                            out.push_str("Optional");
424                            self.write_name(iface, ty, out);
425                        }
426                        TypeDefKind::Expected(_) => out.push_str("Result"),
427                        TypeDefKind::Tuple(_) => out.push_str("Tuple"),
428                        TypeDefKind::List(ty) => {
429                            self.write_name(iface, ty, out);
430                            out.push_str("List")
431                        }
432                        TypeDefKind::Future(ty) => {
433                            self.write_name(iface, ty, out);
434                            out.push_str("Future");
435                        }
436                        TypeDefKind::Stream(s) => {
437                            self.write_name(iface, &s.element, out);
438                            self.write_name(iface, &s.end, out);
439                            out.push_str("Stream");
440                        }
441
442                        TypeDefKind::Type(ty) => self.write_name(iface, ty, out),
443                        TypeDefKind::Record(_) => out.push_str("Record"),
444                        TypeDefKind::Flags(_) => out.push_str("Flags"),
445                        TypeDefKind::Variant(_) => out.push_str("Variant"),
446                        TypeDefKind::Enum(_) => out.push_str("Enum"),
447                        TypeDefKind::Union(_) => out.push_str("Union"),
448                    },
449                }
450            }
451        }
452    }
453
454    /// Returns the names for the cases of the passed union.
455    fn union_case_names(&self, iface: &Interface, union: &Union) -> Vec<String> {
456        enum UsedState<'a> {
457            /// This name has been used once before.
458            ///
459            /// Contains a reference to the name given to the first usage so that a suffix can be added to it.
460            Once(&'a mut String),
461            /// This name has already been used multiple times.
462            ///
463            /// Contains the number of times this has already been used.
464            Multiple(usize),
465        }
466
467        // A `Vec` of the names we're assigning each of the union's cases in order.
468        let mut case_names = vec![String::new(); union.cases.len()];
469        // A map from case names to their `UsedState`.
470        let mut used = HashMap::new();
471        for (case, name) in union.cases.iter().zip(case_names.iter_mut()) {
472            self.write_name(iface, &case.ty, name);
473
474            match used.get_mut(name.as_str()) {
475                None => {
476                    // Initialise this name's `UsedState`, with a mutable reference to this name
477                    // in case we have to add a suffix to it later.
478                    used.insert(name.clone(), UsedState::Once(name));
479                    // Since this is the first (and potentially only) usage of this name,
480                    // we don't need to add a suffix here.
481                }
482                Some(state) => match state {
483                    UsedState::Multiple(n) => {
484                        // Add a suffix of the index of this usage.
485                        write!(name, "{n}").unwrap();
486                        // Add one to the number of times this type has been used.
487                        *n += 1;
488                    }
489                    UsedState::Once(first) => {
490                        // Add a suffix of 0 to the first usage.
491                        first.push('0');
492                        // We now get a suffix of 1.
493                        name.push('1');
494                        // Then update the state.
495                        *state = UsedState::Multiple(2);
496                    }
497                },
498            }
499        }
500
501        case_names
502    }
503
504    fn print_typedef_record(
505        &mut self,
506        iface: &Interface,
507        id: TypeId,
508        record: &Record,
509        docs: &Docs,
510        generate_structs: bool,
511    ) {
512        let info = self.info(id);
513        for (name, mode) in self.modes_of(iface, id, generate_structs) {
514            let lt = self.lifetime_for(&info, mode);
515            self.rustdoc(docs);
516            if !info.owns_data() {
517                self.push_str("#[repr(C)]\n");
518                self.push_str("#[derive(Copy, Clone)]\n");
519            } else if !info.has_handle {
520                self.push_str("#[derive(Clone)]\n");
521            }
522            self.push_str(&format!("pub struct {}", name));
523            self.print_generics(&info, lt, true);
524            self.push_str(" {\n");
525            for field in record.fields.iter() {
526                self.rustdoc(&field.docs);
527                self.push_str("pub ");
528                self.push_str(&to_rust_ident(&field.name));
529                self.push_str(": ");
530                self.print_ty(iface, &field.ty, mode);
531                self.push_str(",\n");
532            }
533            self.push_str("}\n");
534
535            self.push_str("impl");
536            self.print_generics(&info, lt, true);
537            self.push_str(" core::fmt::Debug for ");
538            self.push_str(&name);
539            self.print_generics(&info, lt, false);
540            self.push_str(" {\n");
541            self.push_str(
542                "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
543            );
544            self.push_str(&format!("f.debug_struct(\"{}\")", name));
545            for field in record.fields.iter() {
546                self.push_str(&format!(
547                    ".field(\"{}\", &self.{})",
548                    field.name,
549                    to_rust_ident(&field.name)
550                ));
551            }
552            self.push_str(".finish()");
553            self.push_str("}\n");
554            self.push_str("}\n");
555        }
556    }
557
558    fn print_typedef_tuple(
559        &mut self,
560        iface: &Interface,
561        id: TypeId,
562        tuple: &Tuple,
563        docs: &Docs,
564        generate_structs: bool,
565    ) {
566        let info = self.info(id);
567        for (name, mode) in self.modes_of(iface, id, generate_structs) {
568            let lt = self.lifetime_for(&info, mode);
569            self.rustdoc(docs);
570            self.push_str(&format!("pub type {}", name));
571            self.print_generics(&info, lt, true);
572            self.push_str(" = (");
573            for ty in tuple.types.iter() {
574                self.print_ty(iface, ty, mode);
575                self.push_str(",");
576            }
577            self.push_str(");\n");
578        }
579    }
580
581    fn print_typedef_variant(
582        &mut self,
583        iface: &Interface,
584        id: TypeId,
585        variant: &Variant,
586        docs: &Docs,
587        generate_structs: bool,
588    ) where
589        Self: Sized,
590    {
591        self.print_rust_enum(
592            iface,
593            id,
594            variant
595                .cases
596                .iter()
597                .map(|c| (c.name.to_camel_case(), &c.docs, &c.ty)),
598            docs,
599            generate_structs,
600        );
601    }
602
603    fn print_typedef_union(
604        &mut self,
605        iface: &Interface,
606        id: TypeId,
607        union: &Union,
608        docs: &Docs,
609        generate_structs: bool,
610    ) where
611        Self: Sized,
612    {
613        self.print_rust_enum(
614            iface,
615            id,
616            zip(self.union_case_names(iface, union), &union.cases)
617                .map(|(name, case)| (name, &case.docs, &case.ty)),
618            docs,
619            generate_structs,
620        );
621    }
622
623    fn print_rust_enum<'a>(
624        &mut self,
625        iface: &Interface,
626        id: TypeId,
627        cases: impl IntoIterator<Item = (String, &'a Docs, &'a Type)> + Clone,
628        docs: &Docs,
629        generate_structs: bool,
630    ) where
631        Self: Sized,
632    {
633        let info = self.info(id);
634
635        for (name, mode) in self.modes_of(iface, id, generate_structs) {
636            let name = name.to_camel_case();
637            self.rustdoc(docs);
638            let lt = self.lifetime_for(&info, mode);
639            if !info.owns_data() {
640                self.push_str("#[derive(Clone, Copy)]\n");
641            } else if !info.has_handle {
642                self.push_str("#[derive(Clone)]\n");
643            }
644            self.push_str(&format!("pub enum {name}"));
645            self.print_generics(&info, lt, true);
646            self.push_str("{\n");
647            for (case_name, docs, payload) in cases.clone() {
648                self.rustdoc(docs);
649                self.push_str(&case_name);
650                if *payload != Type::Unit {
651                    self.push_str("(");
652                    self.print_ty(iface, payload, mode);
653                    self.push_str(")")
654                }
655                self.push_str(",\n");
656            }
657            self.push_str("}\n");
658
659            self.print_rust_enum_debug(
660                id,
661                mode,
662                &name,
663                cases
664                    .clone()
665                    .into_iter()
666                    .map(|(name, _docs, ty)| (name, ty)),
667            );
668        }
669    }
670
671    fn print_rust_enum_debug<'a>(
672        &mut self,
673        id: TypeId,
674        mode: TypeMode,
675        name: &str,
676        cases: impl IntoIterator<Item = (String, &'a Type)>,
677    ) where
678        Self: Sized,
679    {
680        let info = self.info(id);
681        let lt = self.lifetime_for(&info, mode);
682        self.push_str("impl");
683        self.print_generics(&info, lt, true);
684        self.push_str(" core::fmt::Debug for ");
685        self.push_str(name);
686        self.print_generics(&info, lt, false);
687        self.push_str(" {\n");
688        self.push_str("fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n");
689        self.push_str("match self {\n");
690        for (case_name, payload) in cases {
691            self.push_str(name);
692            self.push_str("::");
693            self.push_str(&case_name);
694            if *payload != Type::Unit {
695                self.push_str("(e)");
696            }
697            self.push_str(" => {\n");
698            self.push_str(&format!("f.debug_tuple(\"{}::{}\")", name, case_name));
699            if *payload != Type::Unit {
700                self.push_str(".field(e)");
701            }
702            self.push_str(".finish()\n");
703            self.push_str("}\n");
704        }
705        self.push_str("}\n");
706        self.push_str("}\n");
707        self.push_str("}\n");
708    }
709
710    fn print_typedef_option(
711        &mut self,
712        iface: &Interface,
713        id: TypeId,
714        payload: &Type,
715        docs: &Docs,
716        generate_structs: bool,
717    ) {
718        let info = self.info(id);
719
720        for (name, mode) in self.modes_of(iface, id, generate_structs) {
721            self.rustdoc(docs);
722            let lt = self.lifetime_for(&info, mode);
723            self.push_str(&format!("pub type {}", name));
724            self.print_generics(&info, lt, true);
725            self.push_str("= Option<");
726            self.print_ty(iface, payload, mode);
727            self.push_str(">;\n");
728        }
729    }
730
731    fn print_typedef_expected(
732        &mut self,
733        iface: &Interface,
734        id: TypeId,
735        expected: &Expected,
736        docs: &Docs,
737        generate_structs: bool,
738    ) {
739        let info = self.info(id);
740
741        for (name, mode) in self.modes_of(iface, id, generate_structs) {
742            self.rustdoc(docs);
743            let lt = self.lifetime_for(&info, mode);
744            self.push_str(&format!("pub type {}", name));
745            self.print_generics(&info, lt, true);
746            self.push_str("= Result<");
747            self.print_ty(iface, &expected.ok, mode);
748            self.push_str(",");
749            self.print_ty(iface, &expected.err, mode);
750            self.push_str(">;\n");
751        }
752    }
753
754    fn print_typedef_enum(
755        &mut self,
756        id: TypeId,
757        name: &str,
758        enum_: &Enum,
759        docs: &Docs,
760        generate_structs: bool,
761    ) where
762        Self: Sized,
763    {
764        // TODO: should this perhaps be an attribute in the wit file?
765        let is_error = name.contains("errno");
766
767        let name = name.to_camel_case();
768        self.rustdoc(docs);
769        self.push_str("#[repr(");
770        self.int_repr(enum_.tag());
771        self.push_str(")]\n#[derive(Clone, Copy, PartialEq, Eq)]\n");
772        self.push_str(&format!("pub enum {} {{\n", name.to_camel_case()));
773        for case in enum_.cases.iter() {
774            self.rustdoc(&case.docs);
775            self.push_str(&case.name.to_camel_case());
776            self.push_str(",\n");
777        }
778        self.push_str("}\n");
779
780        // Auto-synthesize an implementation of the standard `Error` trait for
781        // error-looking types based on their name.
782        if is_error {
783            self.push_str("impl ");
784            self.push_str(&name);
785            self.push_str("{\n");
786
787            self.push_str("pub fn name(&self) -> &'static str {\n");
788            self.push_str("match self {\n");
789            for case in enum_.cases.iter() {
790                self.push_str(&name);
791                self.push_str("::");
792                self.push_str(&case.name.to_camel_case());
793                self.push_str(" => \"");
794                self.push_str(case.name.as_str());
795                self.push_str("\",\n");
796            }
797            self.push_str("}\n");
798            self.push_str("}\n");
799
800            self.push_str("pub fn message(&self) -> &'static str {\n");
801            self.push_str("match self {\n");
802            for case in enum_.cases.iter() {
803                self.push_str(&name);
804                self.push_str("::");
805                self.push_str(&case.name.to_camel_case());
806                self.push_str(" => \"");
807                if let Some(contents) = &case.docs.contents {
808                    self.push_str(contents.trim());
809                }
810                self.push_str("\",\n");
811            }
812            self.push_str("}\n");
813            self.push_str("}\n");
814
815            self.push_str("}\n");
816
817            self.push_str("impl core::fmt::Debug for ");
818            self.push_str(&name);
819            self.push_str(
820                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
821            );
822            self.push_str("f.debug_struct(\"");
823            self.push_str(&name);
824            self.push_str("\")\n");
825            self.push_str(".field(\"code\", &(*self as i32))\n");
826            self.push_str(".field(\"name\", &self.name())\n");
827            self.push_str(".field(\"message\", &self.message())\n");
828            self.push_str(".finish()\n");
829            self.push_str("}\n");
830            self.push_str("}\n");
831
832            self.push_str("impl core::fmt::Display for ");
833            self.push_str(&name);
834            self.push_str(
835                "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
836            );
837            self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)");
838            self.push_str("}\n");
839            self.push_str("}\n");
840            self.push_str("\n");
841            self.push_str("impl std::error::Error for ");
842            self.push_str(&name);
843            self.push_str("{}\n");
844        } else {
845            self.print_rust_enum_debug(
846                id,
847                TypeMode::Owned,
848                &name,
849                enum_
850                    .cases
851                    .iter()
852                    .map(|c| (c.name.to_camel_case(), &Type::Unit)),
853            )
854        }
855    }
856
857    fn print_typedef_alias(
858        &mut self,
859        iface: &Interface,
860        id: TypeId,
861        ty: &Type,
862        docs: &Docs,
863        generate_structs: bool,
864    ) {
865        let info = self.info(id);
866        for (name, mode) in self.modes_of(iface, id, generate_structs) {
867            self.rustdoc(docs);
868            self.push_str(&format!("pub type {}", name));
869            let lt = self.lifetime_for(&info, mode);
870            self.print_generics(&info, lt, true);
871            self.push_str(" = ");
872            self.print_ty(iface, ty, mode);
873            self.push_str(";\n");
874        }
875    }
876
877    fn print_type_list(
878        &mut self,
879        iface: &Interface,
880        id: TypeId,
881        ty: &Type,
882        docs: &Docs,
883        generate_structs: bool,
884    ) {
885        let info = self.info(id);
886        for (name, mode) in self.modes_of(iface, id, generate_structs) {
887            let lt = self.lifetime_for(&info, mode);
888            self.rustdoc(docs);
889            self.push_str(&format!("pub type {}", name));
890            self.print_generics(&info, lt, true);
891            self.push_str(" = ");
892            self.print_list(iface, ty, mode);
893            self.push_str(";\n");
894        }
895    }
896
897    fn param_name(&self, iface: &Interface, ty: TypeId) -> String {
898        let info = self.info(ty);
899        let name = iface.types[ty].name.as_ref().unwrap().to_camel_case();
900        if self.uses_two_names(&info) {
901            format!("{}Param", name)
902        } else {
903            name
904        }
905    }
906
907    fn result_name(&self, iface: &Interface, ty: TypeId) -> String {
908        let info = self.info(ty);
909        let name = iface.types[ty].name.as_ref().unwrap().to_camel_case();
910        if self.uses_two_names(&info) {
911            format!("{}Result", name)
912        } else {
913            name
914        }
915    }
916
917    fn uses_two_names(&self, info: &TypeInfo) -> bool {
918        info.owns_data()
919            && info.param
920            && info.result
921            && match self.default_param_mode() {
922                TypeMode::AllBorrowed(_) | TypeMode::LeafBorrowed(_) => true,
923                TypeMode::HandlesBorrowed(_) => info.has_handle,
924                TypeMode::Owned => false,
925            }
926    }
927
928    fn lifetime_for(&self, info: &TypeInfo, mode: TypeMode) -> Option<&'static str> {
929        match mode {
930            TypeMode::AllBorrowed(s) | TypeMode::LeafBorrowed(s)
931                if info.has_list || info.has_handle =>
932            {
933                Some(s)
934            }
935            TypeMode::HandlesBorrowed(s) if info.has_handle => Some(s),
936            _ => None,
937        }
938    }
939}
940
941#[derive(Default)]
942pub struct FnSig {
943    pub async_: bool,
944    pub unsafe_: bool,
945    pub private: bool,
946    pub use_item_name: bool,
947    pub generics: Option<String>,
948    pub self_arg: Option<String>,
949    pub self_is_first_param: bool,
950}
951
952pub trait RustFunctionGenerator {
953    fn push_str(&mut self, s: &str);
954    fn tmp(&mut self) -> usize;
955    fn rust_gen(&self) -> &dyn RustGenerator;
956    fn lift_lower(&self) -> LiftLower;
957
958    fn let_results(&mut self, amt: usize, results: &mut Vec<String>) {
959        match amt {
960            0 => {}
961            1 => {
962                let tmp = self.tmp();
963                let res = format!("result{}", tmp);
964                self.push_str("let ");
965                self.push_str(&res);
966                results.push(res);
967                self.push_str(" = ");
968            }
969            n => {
970                let tmp = self.tmp();
971                self.push_str("let (");
972                for i in 0..n {
973                    let arg = format!("result{}_{}", tmp, i);
974                    self.push_str(&arg);
975                    self.push_str(",");
976                    results.push(arg);
977                }
978                self.push_str(") = ");
979            }
980        }
981    }
982
983    fn record_lower(
984        &mut self,
985        iface: &Interface,
986        id: TypeId,
987        record: &Record,
988        operand: &str,
989        results: &mut Vec<String>,
990    ) {
991        let tmp = self.tmp();
992        self.push_str("let ");
993        let name = self.typename_lower(iface, id);
994        self.push_str(&name);
995        self.push_str("{ ");
996        for field in record.fields.iter() {
997            let name = to_rust_ident(&field.name);
998            let arg = format!("{}{}", name, tmp);
999            self.push_str(&name);
1000            self.push_str(":");
1001            self.push_str(&arg);
1002            self.push_str(", ");
1003            results.push(arg);
1004        }
1005        self.push_str("} = ");
1006        self.push_str(operand);
1007        self.push_str(";\n");
1008    }
1009
1010    fn record_lift(
1011        &mut self,
1012        iface: &Interface,
1013        id: TypeId,
1014        ty: &Record,
1015        operands: &[String],
1016        results: &mut Vec<String>,
1017    ) {
1018        let mut result = self.typename_lift(iface, id);
1019        result.push_str("{");
1020        for (field, val) in ty.fields.iter().zip(operands) {
1021            result.push_str(&to_rust_ident(&field.name));
1022            result.push_str(":");
1023            result.push_str(&val);
1024            result.push_str(", ");
1025        }
1026        result.push_str("}");
1027        results.push(result);
1028    }
1029
1030    fn tuple_lower(&mut self, tuple: &Tuple, operand: &str, results: &mut Vec<String>) {
1031        let tmp = self.tmp();
1032        self.push_str("let (");
1033        for i in 0..tuple.types.len() {
1034            let arg = format!("t{}_{}", tmp, i);
1035            self.push_str(&arg);
1036            self.push_str(", ");
1037            results.push(arg);
1038        }
1039        self.push_str(") = ");
1040        self.push_str(operand);
1041        self.push_str(";\n");
1042    }
1043
1044    fn tuple_lift(&mut self, operands: &[String], results: &mut Vec<String>) {
1045        if operands.len() == 1 {
1046            results.push(format!("({},)", operands[0]));
1047        } else {
1048            results.push(format!("({})", operands.join(", ")));
1049        }
1050    }
1051
1052    fn typename_lower(&self, iface: &Interface, id: TypeId) -> String {
1053        match self.lift_lower() {
1054            LiftLower::LowerArgsLiftResults => self.rust_gen().param_name(iface, id),
1055            LiftLower::LiftArgsLowerResults => self.rust_gen().result_name(iface, id),
1056        }
1057    }
1058
1059    fn typename_lift(&self, iface: &Interface, id: TypeId) -> String {
1060        match self.lift_lower() {
1061            LiftLower::LiftArgsLowerResults => self.rust_gen().param_name(iface, id),
1062            LiftLower::LowerArgsLiftResults => self.rust_gen().result_name(iface, id),
1063        }
1064    }
1065}
1066
1067pub fn to_rust_ident(name: &str) -> String {
1068    match name {
1069        // Escape Rust keywords.
1070        // Source: https://doc.rust-lang.org/reference/keywords.html
1071        "as" => "as_".into(),
1072        "break" => "break_".into(),
1073        "const" => "const_".into(),
1074        "continue" => "continue_".into(),
1075        "crate" => "crate_".into(),
1076        "else" => "else_".into(),
1077        "enum" => "enum_".into(),
1078        "extern" => "extern_".into(),
1079        "false" => "false_".into(),
1080        "fn" => "fn_".into(),
1081        "for" => "for_".into(),
1082        "if" => "if_".into(),
1083        "impl" => "impl_".into(),
1084        "in" => "in_".into(),
1085        "let" => "let_".into(),
1086        "loop" => "loop_".into(),
1087        "match" => "match_".into(),
1088        "mod" => "mod_".into(),
1089        "move" => "move_".into(),
1090        "mut" => "mut_".into(),
1091        "pub" => "pub_".into(),
1092        "ref" => "ref_".into(),
1093        "return" => "return_".into(),
1094        "self" => "self_".into(),
1095        "static" => "static_".into(),
1096        "struct" => "struct_".into(),
1097        "super" => "super_".into(),
1098        "trait" => "trait_".into(),
1099        "true" => "true_".into(),
1100        "type" => "type_".into(),
1101        "unsafe" => "unsafe_".into(),
1102        "use" => "use_".into(),
1103        "where" => "where_".into(),
1104        "while" => "while_".into(),
1105        "async" => "async_".into(),
1106        "await" => "await_".into(),
1107        "dyn" => "dyn_".into(),
1108        "abstract" => "abstract_".into(),
1109        "become" => "become_".into(),
1110        "box" => "box_".into(),
1111        "do" => "do_".into(),
1112        "final" => "final_".into(),
1113        "macro" => "macro_".into(),
1114        "override" => "override_".into(),
1115        "priv" => "priv_".into(),
1116        "typeof" => "typeof_".into(),
1117        "unsized" => "unsized_".into(),
1118        "virtual" => "virtual_".into(),
1119        "yield" => "yield_".into(),
1120        "try" => "try_".into(),
1121        s => s.to_snake_case(),
1122    }
1123}
1124
1125pub fn wasm_type(ty: WasmType) -> &'static str {
1126    match ty {
1127        WasmType::I32 => "i32",
1128        WasmType::I64 => "i64",
1129        WasmType::F32 => "f32",
1130        WasmType::F64 => "f64",
1131    }
1132}
1133
1134pub fn int_repr(repr: Int) -> &'static str {
1135    match repr {
1136        Int::U8 => "u8",
1137        Int::U16 => "u16",
1138        Int::U32 => "u32",
1139        Int::U64 => "u64",
1140    }
1141}
1142
1143trait TypeInfoExt {
1144    fn owns_data(&self) -> bool;
1145}
1146
1147impl TypeInfoExt for TypeInfo {
1148    fn owns_data(&self) -> bool {
1149        self.has_list || self.has_handle
1150    }
1151}
1152
1153pub fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1154    for (cast, operand) in casts.iter().zip(operands) {
1155        results.push(match cast {
1156            Bitcast::None => operand.clone(),
1157            Bitcast::I32ToI64 => format!("i64::from({})", operand),
1158            Bitcast::F32ToI32 => format!("({}).to_bits() as i32", operand),
1159            Bitcast::F64ToI64 => format!("({}).to_bits() as i64", operand),
1160            Bitcast::I64ToI32 => format!("{} as i32", operand),
1161            Bitcast::I32ToF32 => format!("f32::from_bits({} as u32)", operand),
1162            Bitcast::I64ToF64 => format!("f64::from_bits({} as u64)", operand),
1163            Bitcast::F32ToI64 => format!("i64::from(({}).to_bits())", operand),
1164            Bitcast::I64ToF32 => format!("f32::from_bits({} as u32)", operand),
1165        });
1166    }
1167}
1168
1169pub enum RustFlagsRepr {
1170    U8,
1171    U16,
1172    U32,
1173    U64,
1174    U128,
1175}
1176
1177impl RustFlagsRepr {
1178    pub fn new(f: &Flags) -> RustFlagsRepr {
1179        match f.repr() {
1180            FlagsRepr::U8 => RustFlagsRepr::U8,
1181            FlagsRepr::U16 => RustFlagsRepr::U16,
1182            FlagsRepr::U32(1) => RustFlagsRepr::U32,
1183            FlagsRepr::U32(2) => RustFlagsRepr::U64,
1184            FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
1185            FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
1186        }
1187    }
1188}
1189
1190impl fmt::Display for RustFlagsRepr {
1191    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1192        match self {
1193            RustFlagsRepr::U8 => "u8".fmt(f),
1194            RustFlagsRepr::U16 => "u16".fmt(f),
1195            RustFlagsRepr::U32 => "u32".fmt(f),
1196            RustFlagsRepr::U64 => "u64".fmt(f),
1197            RustFlagsRepr::U128 => "u128".fmt(f),
1198        }
1199    }
1200}