wai_bindgen_gen_rust/
lib.rs

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