linera_wit_bindgen_gen_rust_lib/
lib.rs

1use heck::*;
2use std::collections::HashMap;
3use std::fmt::{self, Write};
4use std::iter::zip;
5use wit_bindgen_core::wit_parser::abi::{Bitcast, LiftLower, WasmType};
6use wit_bindgen_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<String>;
31    fn handle_in_super(&self) -> bool {
32        false
33    }
34
35    fn handle_is_self(&self, _resource: &ResourceId) -> bool {
36        false
37    }
38
39    fn rustdoc(&mut self, docs: &Docs) {
40        let docs = match &docs.contents {
41            Some(docs) => docs,
42            None => return,
43        };
44        for line in docs.trim().lines() {
45            self.push_str("/// ");
46            self.push_str(line);
47            self.push_str("\n");
48        }
49    }
50
51    fn rustdoc_params(&mut self, docs: &[(String, Type)], header: &str) {
52        drop((docs, header));
53        // let docs = docs
54        //     .iter()
55        //     .filter(|param| param.docs.trim().len() > 0)
56        //     .collect::<Vec<_>>();
57        // if docs.len() == 0 {
58        //     return;
59        // }
60
61        // self.push_str("///\n");
62        // self.push_str("/// ## ");
63        // self.push_str(header);
64        // self.push_str("\n");
65        // self.push_str("///\n");
66
67        // for param in docs {
68        //     for (i, line) in param.docs.lines().enumerate() {
69        //         self.push_str("/// ");
70        //         // Currently wasi only has at most one return value, so there's no
71        //         // need to indent it or name it.
72        //         if header != "Return" {
73        //             if i == 0 {
74        //                 self.push_str("* `");
75        //                 self.push_str(to_rust_ident(param.name.as_str()));
76        //                 self.push_str("` - ");
77        //             } else {
78        //                 self.push_str("  ");
79        //             }
80        //         }
81        //         self.push_str(line);
82        //         self.push_str("\n");
83        //     }
84        // }
85    }
86
87    fn print_signature(
88        &mut self,
89        iface: &Interface,
90        func: &Function,
91        param_mode: TypeMode,
92        sig: &FnSig,
93    ) -> Vec<String> {
94        let params = self.print_docs_and_params(iface, func, param_mode, &sig);
95        self.push_str(" -> ");
96        self.print_ty(iface, &func.result, TypeMode::Owned);
97        params
98    }
99
100    fn print_docs_and_params(
101        &mut self,
102        iface: &Interface,
103        func: &Function,
104        param_mode: TypeMode,
105        sig: &FnSig,
106    ) -> Vec<String> {
107        self.rustdoc(&func.docs);
108        self.rustdoc_params(&func.params, "Parameters");
109        // TODO: re-add this when docs are back
110        // self.rustdoc_params(&func.results, "Return");
111
112        if !sig.private {
113            self.push_str("pub ");
114        }
115        if sig.unsafe_ {
116            self.push_str("unsafe ");
117        }
118        if sig.async_ {
119            self.push_str("async ");
120        }
121        self.push_str("fn ");
122        let func_name = if sig.use_item_name {
123            func.item_name()
124        } else {
125            &func.name
126        };
127        self.push_str(&to_rust_ident(&func_name));
128        if let Some(generics) = &sig.generics {
129            self.push_str(generics);
130        }
131        self.push_str("(");
132        if let Some(arg) = &sig.self_arg {
133            self.push_str(arg);
134            self.push_str(",");
135        }
136        let mut params = Vec::new();
137        for (i, (name, param)) in func.params.iter().enumerate() {
138            if i == 0 && sig.self_is_first_param {
139                params.push("self".to_string());
140                continue;
141            }
142            let name = to_rust_ident(name);
143            self.push_str(&name);
144            params.push(name);
145            self.push_str(": ");
146            self.print_ty(iface, param, param_mode);
147            self.push_str(",");
148        }
149        self.push_str(")");
150        params
151    }
152
153    fn print_ty(&mut self, iface: &Interface, ty: &Type, mode: TypeMode) {
154        match ty {
155            Type::Id(t) => self.print_tyid(iface, *t, mode),
156            Type::Handle(r) => {
157                let mut info = TypeInfo::default();
158                info.has_handle = true;
159                let lt = self.lifetime_for(&info, mode);
160                // Borrowed handles are always behind a reference since
161                // in that case we never take ownership of the handle.
162                if let Some(lt) = lt {
163                    self.push_str("&");
164                    if lt != "'_" {
165                        self.push_str(lt);
166                    }
167                    self.push_str(" ");
168                }
169
170                let suffix = match self.handle_wrapper() {
171                    Some(wrapper) => {
172                        self.push_str(&wrapper);
173                        self.push_str("<");
174                        ">"
175                    }
176                    None => "",
177                };
178                if self.handle_is_self(r) {
179                    self.push_str("Self");
180                } else {
181                    if self.handle_in_super() {
182                        self.push_str("super::");
183                    }
184                    if let Some((proj, _)) = self.handle_projection() {
185                        self.push_str(proj);
186                        self.push_str("::");
187                    }
188                    self.push_str(&iface.resources[*r].name.to_camel_case());
189                }
190                self.push_str(suffix);
191            }
192
193            Type::Unit => self.push_str("()"),
194            Type::Bool => self.push_str("bool"),
195            Type::U8 => self.push_str("u8"),
196            Type::U16 => self.push_str("u16"),
197            Type::U32 => self.push_str("u32"),
198            Type::U64 => self.push_str("u64"),
199            Type::S8 => self.push_str("i8"),
200            Type::S16 => self.push_str("i16"),
201            Type::S32 => self.push_str("i32"),
202            Type::S64 => self.push_str("i64"),
203            Type::Float32 => self.push_str("f32"),
204            Type::Float64 => self.push_str("f64"),
205            Type::Char => self.push_str("char"),
206            Type::String => match mode {
207                TypeMode::AllBorrowed(lt) | TypeMode::LeafBorrowed(lt) => {
208                    self.print_borrowed_str(lt)
209                }
210                TypeMode::Owned | TypeMode::HandlesBorrowed(_) => self.push_str("String"),
211            },
212        }
213    }
214
215    fn print_tyid(&mut self, iface: &Interface, id: TypeId, mode: TypeMode) {
216        let info = self.info(id);
217        let lt = self.lifetime_for(&info, mode);
218        let ty = &iface.types[id];
219        if ty.name.is_some() {
220            let name = if lt.is_some() {
221                self.param_name(iface, id)
222            } else {
223                self.result_name(iface, id)
224            };
225            self.push_str(&name);
226
227            // If the type recursively owns data and it's a
228            // variant/record/list, then we need to place the
229            // lifetime parameter on the type as well.
230            if info.owns_data() && needs_generics(iface, &ty.kind) {
231                self.print_generics(&info, lt, false);
232            }
233
234            return;
235
236            fn needs_generics(iface: &Interface, ty: &TypeDefKind) -> bool {
237                match ty {
238                    TypeDefKind::Variant(_)
239                    | TypeDefKind::Record(_)
240                    | TypeDefKind::Option(_)
241                    | TypeDefKind::Result(_)
242                    | TypeDefKind::Future(_)
243                    | TypeDefKind::Stream(_)
244                    | TypeDefKind::List(_)
245                    | TypeDefKind::Flags(_)
246                    | TypeDefKind::Enum(_)
247                    | TypeDefKind::Tuple(_)
248                    | TypeDefKind::Union(_) => true,
249                    TypeDefKind::Type(Type::Id(t)) => needs_generics(iface, &iface.types[*t].kind),
250                    TypeDefKind::Type(Type::String) => true,
251                    TypeDefKind::Type(Type::Handle(_)) => true,
252                    TypeDefKind::Type(_) => false,
253                }
254            }
255        }
256
257        match &ty.kind {
258            TypeDefKind::List(t) => self.print_list(iface, t, mode),
259
260            TypeDefKind::Option(t) => {
261                self.push_str("Option<");
262                self.print_ty(iface, t, mode);
263                self.push_str(">");
264            }
265
266            TypeDefKind::Result(r) => {
267                self.push_str("Result<");
268                self.print_ty(iface, &r.ok, mode);
269                self.push_str(",");
270                self.print_ty(iface, &r.err, mode);
271                self.push_str(">");
272            }
273
274            TypeDefKind::Variant(_) => panic!("unsupported anonymous variant"),
275
276            // Tuple-like records are mapped directly to Rust tuples of
277            // types. Note the trailing comma after each member to
278            // appropriately handle 1-tuples.
279            TypeDefKind::Tuple(t) => {
280                self.push_str("(");
281                for ty in t.types.iter() {
282                    self.print_ty(iface, ty, mode);
283                    self.push_str(",");
284                }
285                self.push_str(")");
286            }
287            TypeDefKind::Record(_) => {
288                panic!("unsupported anonymous type reference: record")
289            }
290            TypeDefKind::Flags(_) => {
291                panic!("unsupported anonymous type reference: flags")
292            }
293            TypeDefKind::Enum(_) => {
294                panic!("unsupported anonymous type reference: enum")
295            }
296            TypeDefKind::Union(_) => {
297                panic!("unsupported anonymous type reference: union")
298            }
299            TypeDefKind::Future(ty) => {
300                self.push_str("Future<");
301                self.print_ty(iface, ty, mode);
302                self.push_str(">");
303            }
304            TypeDefKind::Stream(stream) => {
305                self.push_str("Stream<");
306                self.print_ty(iface, &stream.element, mode);
307                self.push_str(",");
308                self.print_ty(iface, &stream.end, mode);
309                self.push_str(">");
310            }
311
312            TypeDefKind::Type(t) => self.print_ty(iface, t, mode),
313        }
314    }
315
316    fn print_list(&mut self, iface: &Interface, ty: &Type, mode: TypeMode) {
317        match mode {
318            TypeMode::AllBorrowed(lt) => {
319                self.print_borrowed_slice(iface, false, ty, lt);
320            }
321            TypeMode::LeafBorrowed(lt) => {
322                if iface.all_bits_valid(ty) {
323                    self.print_borrowed_slice(iface, false, ty, lt);
324                } else {
325                    self.push_str("Vec<");
326                    self.print_ty(iface, ty, mode);
327                    self.push_str(">");
328                }
329            }
330            TypeMode::HandlesBorrowed(_) | TypeMode::Owned => {
331                self.push_str("Vec<");
332                self.print_ty(iface, ty, mode);
333                self.push_str(">");
334            }
335        }
336    }
337
338    fn print_rust_slice(
339        &mut self,
340        iface: &Interface,
341        mutbl: bool,
342        ty: &Type,
343        lifetime: &'static str,
344    ) {
345        self.push_str("&");
346        if lifetime != "'_" {
347            self.push_str(lifetime);
348            self.push_str(" ");
349        }
350        if mutbl {
351            self.push_str(" mut ");
352        }
353        self.push_str("[");
354        self.print_ty(iface, ty, TypeMode::AllBorrowed(lifetime));
355        self.push_str("]");
356    }
357
358    fn print_generics(&mut self, info: &TypeInfo, lifetime: Option<&str>, bound: bool) {
359        let proj = if info.has_handle {
360            self.handle_projection()
361        } else {
362            None
363        };
364        if lifetime.is_none() && proj.is_none() {
365            return;
366        }
367        self.push_str("<");
368        if let Some(lt) = lifetime {
369            self.push_str(lt);
370            self.push_str(",");
371        }
372        if let Some((proj, trait_bound)) = proj {
373            self.push_str(proj);
374            if bound {
375                self.push_str(": ");
376                self.push_str(&trait_bound);
377            }
378        }
379        self.push_str(">");
380    }
381
382    fn int_repr(&mut self, repr: Int) {
383        self.push_str(int_repr(repr));
384    }
385
386    fn wasm_type(&mut self, ty: WasmType) {
387        self.push_str(wasm_type(ty));
388    }
389
390    fn modes_of(&self, iface: &Interface, ty: TypeId) -> Vec<(String, TypeMode)> {
391        let info = self.info(ty);
392        let mut result = Vec::new();
393        if info.param {
394            result.push((self.param_name(iface, ty), self.default_param_mode()));
395        }
396        if info.result && (!info.param || self.uses_two_names(&info)) {
397            result.push((self.result_name(iface, ty), TypeMode::Owned));
398        }
399        return 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::Result(_) => 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_result(
710        &mut self,
711        iface: &Interface,
712        id: TypeId,
713        result: &Result_,
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, &result.ok, mode);
725            self.push_str(",");
726            self.print_ty(iface, &result.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 wit 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_str("{");
977        for (field, val) in ty.fields.iter().zip(operands) {
978            result.push_str(&to_rust_ident(&field.name));
979            result.push_str(":");
980            result.push_str(&val);
981            result.push_str(", ");
982        }
983        result.push_str("}");
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}