1use heck::*;
2use std::fmt;
3use std::str::FromStr;
4use wit_bindgen_core::abi::{Bitcast, LiftLower, WasmType};
5use wit_bindgen_core::{wit_parser::*, TypeInfo, Types};
6
7#[derive(Debug, Copy, Clone, PartialEq)]
8pub enum TypeMode {
9 Owned,
10 AllBorrowed(&'static str),
11 LeafBorrowed(&'static str),
12 HandlesBorrowed(&'static str),
13}
14
15#[derive(Default, Debug, Clone, Copy)]
16pub enum Ownership {
17 #[default]
20 Owning,
21
22 Borrowing {
26 duplicate_if_necessary: bool,
31 },
32}
33
34impl FromStr for Ownership {
35 type Err = String;
36
37 fn from_str(s: &str) -> Result<Self, Self::Err> {
38 match s {
39 "owning" => Ok(Self::Owning),
40 "borrowing" => Ok(Self::Borrowing {
41 duplicate_if_necessary: false,
42 }),
43 "borrowing-duplicate-if-necessary" => Ok(Self::Borrowing {
44 duplicate_if_necessary: true,
45 }),
46 _ => Err(format!(
47 "unrecognized ownership: `{s}`; \
48 expected `owning`, `borrowing`, or `borrowing-duplicate-if-necessary`"
49 )),
50 }
51 }
52}
53
54impl fmt::Display for Ownership {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 f.write_str(match self {
57 Ownership::Owning => "owning",
58 Ownership::Borrowing {
59 duplicate_if_necessary: false,
60 } => "borrowing",
61 Ownership::Borrowing {
62 duplicate_if_necessary: true,
63 } => "borrowing-duplicate-if-necessary",
64 })
65 }
66}
67
68pub trait RustGenerator<'a> {
69 fn resolve(&self) -> &'a Resolve;
70 fn path_to_interface(&self, interface: InterfaceId) -> Option<String>;
71
72 fn ownership(&self) -> Ownership;
74
75 fn std_feature(&self) -> bool {
78 true
79 }
80
81 fn push_vec_name(&mut self);
83
84 fn push_string_name(&mut self);
86
87 fn use_raw_strings(&self) -> bool {
89 false
90 }
91
92 fn is_exported_resource(&self, ty: TypeId) -> bool;
93
94 fn mark_resource_owned(&mut self, resource: TypeId);
95
96 fn push_str(&mut self, s: &str);
97 fn info(&self, ty: TypeId) -> TypeInfo;
98 fn types_mut(&mut self) -> &mut Types;
99 fn print_borrowed_slice(
100 &mut self,
101 mutbl: bool,
102 ty: &Type,
103 lifetime: &'static str,
104 mode: TypeMode,
105 );
106 fn print_borrowed_str(&mut self, lifetime: &'static str);
107
108 fn rustdoc(&mut self, docs: &Docs) {
109 let docs = match &docs.contents {
110 Some(docs) => docs,
111 None => return,
112 };
113 for line in docs.trim().lines() {
114 self.push_str("/// ");
115 self.push_str(line);
116 self.push_str("\n");
117 }
118 }
119
120 fn rustdoc_params(&mut self, docs: &[(String, Type)], header: &str) {
121 let _ = (docs, header);
122 }
155
156 fn print_signature(
157 &mut self,
158 func: &Function,
159 param_mode: TypeMode,
160 sig: &FnSig,
161 ) -> Vec<String> {
162 let params = self.print_docs_and_params(func, param_mode, &sig);
163 if let FunctionKind::Constructor(_) = &func.kind {
164 self.push_str(" -> Self")
165 } else {
166 self.print_results(&func.results, TypeMode::Owned);
167 }
168 params
169 }
170
171 fn print_docs_and_params(
172 &mut self,
173 func: &Function,
174 param_mode: TypeMode,
175 sig: &FnSig,
176 ) -> Vec<String> {
177 self.rustdoc(&func.docs);
178 self.rustdoc_params(&func.params, "Parameters");
179 if !sig.private {
183 self.push_str("pub ");
184 }
185 if sig.unsafe_ {
186 self.push_str("unsafe ");
187 }
188 if sig.async_ {
189 self.push_str("async ");
190 }
191 self.push_str("fn ");
192 let func_name = if sig.use_item_name {
193 if let FunctionKind::Constructor(_) = &func.kind {
194 "new"
195 } else {
196 func.item_name()
197 }
198 } else {
199 &func.name
200 };
201 self.push_str(&to_rust_ident(&func_name));
202 if let Some(generics) = &sig.generics {
203 self.push_str(generics);
204 }
205 self.push_str("(");
206 if let Some(arg) = &sig.self_arg {
207 self.push_str(arg);
208 self.push_str(",");
209 }
210 let mut params = Vec::new();
211 for (i, (name, param)) in func.params.iter().enumerate() {
212 if i == 0 && sig.self_is_first_param {
213 params.push("self".to_string());
214 continue;
215 }
216 let name = to_rust_ident(name);
217 self.push_str(&name);
218 params.push(name);
219 self.push_str(": ");
220 self.print_ty(param, param_mode);
221 self.push_str(",");
222 }
223 self.push_str(")");
224 params
225 }
226
227 fn print_results(&mut self, results: &Results, mode: TypeMode) {
228 match results.len() {
229 0 => {}
230 1 => {
231 self.push_str(" -> ");
232 self.print_ty(results.iter_types().next().unwrap(), mode);
233 }
234 _ => {
235 self.push_str(" -> (");
236 for ty in results.iter_types() {
237 self.print_ty(ty, mode);
238 self.push_str(", ")
239 }
240 self.push_str(")")
241 }
242 }
243 }
244
245 fn print_ty(&mut self, ty: &Type, mode: TypeMode) {
246 match ty {
247 Type::Id(t) => self.print_tyid(*t, mode),
248 Type::Bool => self.push_str("bool"),
249 Type::U8 => self.push_str("u8"),
250 Type::U16 => self.push_str("u16"),
251 Type::U32 => self.push_str("u32"),
252 Type::U64 => self.push_str("u64"),
253 Type::S8 => self.push_str("i8"),
254 Type::S16 => self.push_str("i16"),
255 Type::S32 => self.push_str("i32"),
256 Type::S64 => self.push_str("i64"),
257 Type::Float32 => self.push_str("f32"),
258 Type::Float64 => self.push_str("f64"),
259 Type::Char => self.push_str("char"),
260 Type::String => match mode {
261 TypeMode::AllBorrowed(lt) | TypeMode::LeafBorrowed(lt) => {
262 self.print_borrowed_str(lt)
263 }
264 TypeMode::Owned | TypeMode::HandlesBorrowed(_) => {
265 if self.use_raw_strings() {
266 self.push_vec_name();
267 self.push_str("::<u8>");
268 } else {
269 self.push_string_name();
270 }
271 }
272 },
273 }
274 }
275
276 fn print_optional_ty(&mut self, ty: Option<&Type>, mode: TypeMode) {
277 match ty {
278 Some(ty) => self.print_ty(ty, mode),
279 None => self.push_str("()"),
280 }
281 }
282
283 fn type_path(&self, id: TypeId, owned: bool) -> String {
284 self.type_path_with_name(
285 id,
286 if owned {
287 self.result_name(id)
288 } else {
289 self.param_name(id)
290 },
291 )
292 }
293
294 fn type_path_with_name(&self, id: TypeId, name: String) -> String {
295 if let TypeOwner::Interface(id) = self.resolve().types[id].owner {
296 if let Some(path) = self.path_to_interface(id) {
297 return format!("{path}::{name}");
298 }
299 }
300 name
301 }
302
303 fn print_tyid(&mut self, id: TypeId, mode: TypeMode) {
304 let info = self.info(id);
305 let lt = self.lifetime_for(&info, mode);
306 let ty = &self.resolve().types[id];
307 if ty.name.is_some() {
308 if info.has_list && !info.has_own_handle {
323 if let TypeMode::AllBorrowed(lt)
324 | TypeMode::LeafBorrowed(lt)
325 | TypeMode::HandlesBorrowed(lt) = mode
326 {
327 self.push_str("&");
328 if lt != "'_" {
329 self.push_str(lt);
330 self.push_str(" ");
331 }
332 }
333 }
334 let name = self.type_path(id, lt.is_none());
335 self.push_str(&name);
336
337 if (info.has_list || info.has_borrow_handle)
341 && !info.has_own_handle
342 && needs_generics(self.resolve(), &ty.kind)
343 {
344 self.print_generics(lt);
345 }
346
347 return;
348
349 fn needs_generics(resolve: &Resolve, ty: &TypeDefKind) -> bool {
350 match ty {
351 TypeDefKind::Variant(_)
352 | TypeDefKind::Record(_)
353 | TypeDefKind::Option(_)
354 | TypeDefKind::Result(_)
355 | TypeDefKind::Future(_)
356 | TypeDefKind::Stream(_)
357 | TypeDefKind::List(_)
358 | TypeDefKind::Flags(_)
359 | TypeDefKind::Enum(_)
360 | TypeDefKind::Tuple(_) => true,
361 TypeDefKind::Type(Type::Id(t)) => {
362 needs_generics(resolve, &resolve.types[*t].kind)
363 }
364 TypeDefKind::Type(Type::String) => true,
365 TypeDefKind::Handle(Handle::Borrow(_)) => true,
366 TypeDefKind::Resource | TypeDefKind::Handle(_) | TypeDefKind::Type(_) => false,
367 TypeDefKind::Unknown => unreachable!(),
368 }
369 }
370 }
371
372 match &ty.kind {
373 TypeDefKind::List(t) => self.print_list(t, mode),
374
375 TypeDefKind::Option(t) => {
376 self.push_str("Option<");
377 self.print_ty(t, mode);
378 self.push_str(">");
379 }
380
381 TypeDefKind::Result(r) => {
382 self.push_str("Result<");
383 self.print_optional_ty(r.ok.as_ref(), mode);
384 self.push_str(",");
385 self.print_optional_ty(r.err.as_ref(), mode);
386 self.push_str(">");
387 }
388
389 TypeDefKind::Variant(_) => panic!("unsupported anonymous variant"),
390
391 TypeDefKind::Tuple(t) => {
395 self.push_str("(");
396 for ty in t.types.iter() {
397 self.print_ty(ty, mode);
398 self.push_str(",");
399 }
400 self.push_str(")");
401 }
402 TypeDefKind::Resource => {
403 panic!("unsupported anonymous type reference: resource")
404 }
405 TypeDefKind::Record(_) => {
406 panic!("unsupported anonymous type reference: record")
407 }
408 TypeDefKind::Flags(_) => {
409 panic!("unsupported anonymous type reference: flags")
410 }
411 TypeDefKind::Enum(_) => {
412 panic!("unsupported anonymous type reference: enum")
413 }
414 TypeDefKind::Future(ty) => {
415 self.push_str("Future<");
416 self.print_optional_ty(ty.as_ref(), mode);
417 self.push_str(">");
418 }
419 TypeDefKind::Stream(stream) => {
420 self.push_str("Stream<");
421 self.print_optional_ty(stream.element.as_ref(), mode);
422 self.push_str(",");
423 self.print_optional_ty(stream.end.as_ref(), mode);
424 self.push_str(">");
425 }
426
427 TypeDefKind::Handle(Handle::Own(ty)) => {
428 self.mark_resource_owned(*ty);
429 self.print_ty(&Type::Id(*ty), mode);
430 }
431
432 TypeDefKind::Handle(Handle::Borrow(ty)) => {
433 self.push_str("&");
434 if let TypeMode::AllBorrowed(lt)
435 | TypeMode::LeafBorrowed(lt)
436 | TypeMode::HandlesBorrowed(lt) = mode
437 {
438 if lt != "'_" {
439 self.push_str(lt);
440 self.push_str(" ");
441 }
442 }
443 if self.is_exported_resource(*ty) {
444 self.push_str(
445 &self.type_path_with_name(
446 *ty,
447 self.resolve().types[*ty]
448 .name
449 .as_deref()
450 .unwrap()
451 .to_upper_camel_case(),
452 ),
453 );
454 } else {
455 self.print_ty(&Type::Id(*ty), mode);
456 }
457 }
458
459 TypeDefKind::Type(t) => self.print_ty(t, mode),
460
461 TypeDefKind::Unknown => unreachable!(),
462 }
463 }
464
465 fn print_list(&mut self, ty: &Type, mode: TypeMode) {
466 let next_mode = if matches!(self.ownership(), Ownership::Owning) {
467 if let TypeMode::HandlesBorrowed(_) = mode {
468 mode
469 } else {
470 TypeMode::Owned
471 }
472 } else {
473 mode
474 };
475 let mode = match *ty {
477 Type::Id(id) if self.info(id).has_own_handle => TypeMode::Owned,
478 _ => mode,
479 };
480 match mode {
481 TypeMode::AllBorrowed(lt) => {
482 self.print_borrowed_slice(false, ty, lt, next_mode);
483 }
484 TypeMode::LeafBorrowed(lt) => {
485 if self.resolve().all_bits_valid(ty) {
486 self.print_borrowed_slice(false, ty, lt, next_mode);
487 } else {
488 self.push_vec_name();
489 self.push_str("::<");
490 self.print_ty(ty, next_mode);
491 self.push_str(">");
492 }
493 }
494 TypeMode::Owned | TypeMode::HandlesBorrowed(_) => {
495 self.push_vec_name();
496 self.push_str("::<");
497 self.print_ty(ty, next_mode);
498 self.push_str(">");
499 }
500 }
501 }
502
503 fn print_rust_slice(&mut self, mutbl: bool, ty: &Type, lifetime: &'static str, mode: TypeMode) {
504 self.push_str("&");
505 if lifetime != "'_" {
506 self.push_str(lifetime);
507 self.push_str(" ");
508 }
509 if mutbl {
510 self.push_str(" mut ");
511 }
512 self.push_str("[");
513 self.print_ty(ty, mode);
514 self.push_str("]");
515 }
516
517 fn print_generics(&mut self, lifetime: Option<&str>) {
518 if lifetime.is_none() {
519 return;
520 }
521 self.push_str("<");
522 if let Some(lt) = lifetime {
523 self.push_str(lt);
524 self.push_str(",");
525 }
526 self.push_str(">");
527 }
528
529 fn int_repr(&mut self, repr: Int) {
530 self.push_str(int_repr(repr));
531 }
532
533 fn wasm_type(&mut self, ty: WasmType) {
534 self.push_str(wasm_type(ty));
535 }
536
537 fn modes_of(&self, ty: TypeId) -> Vec<(String, TypeMode)> {
538 let info = self.info(ty);
539 if !info.owned && !info.borrowed {
541 return Vec::new();
542 }
543 let mut result = Vec::new();
544
545 let first_mode = if info.owned
549 || !info.borrowed
550 || matches!(self.ownership(), Ownership::Owning)
551 || info.has_own_handle
552 {
553 if info.has_borrow_handle {
554 TypeMode::HandlesBorrowed("'a")
555 } else {
556 TypeMode::Owned
557 }
558 } else {
559 assert!(!self.uses_two_names(&info));
560 TypeMode::AllBorrowed("'a")
561 };
562 result.push((self.result_name(ty), first_mode));
563 if self.uses_two_names(&info) {
564 result.push((self.param_name(ty), TypeMode::AllBorrowed("'a")));
565 }
566 return result;
567 }
568
569 fn print_typedef_record(
570 &mut self,
571 id: TypeId,
572 record: &Record,
573 docs: &Docs,
574 derive_component: bool,
575 ) {
576 let info = self.info(id);
577 for (name, mode) in self.modes_of(id) {
578 let lt = self.lifetime_for(&info, mode);
579 self.rustdoc(docs);
580
581 if derive_component {
582 self.push_str("#[derive(wasmtime::component::ComponentType)]\n");
583 if lt.is_none() {
584 self.push_str("#[derive(wasmtime::component::Lift)]\n");
585 }
586 self.push_str("#[derive(wasmtime::component::Lower)]\n");
587 self.push_str("#[component(record)]\n");
588 }
589
590 if info.is_copy() {
591 self.push_str("#[repr(C)]\n");
592 self.push_str("#[derive(Copy, Clone)]\n");
593 } else if info.is_clone() {
594 self.push_str("#[derive(Clone)]\n");
595 }
596 self.push_str(&format!("pub struct {}", name));
597 self.print_generics(lt);
598 self.push_str(" {\n");
599 for field in record.fields.iter() {
600 self.rustdoc(&field.docs);
601 if derive_component {
602 self.push_str(&format!("#[component(name = \"{}\")]\n", field.name));
603 }
604 self.push_str("pub ");
605 self.push_str(&to_rust_ident(&field.name));
606 self.push_str(": ");
607 self.print_ty(&field.ty, mode);
608 self.push_str(",\n");
609 }
610 self.push_str("}\n");
611
612 self.push_str("impl");
613 self.print_generics(lt);
614 self.push_str(" ::core::fmt::Debug for ");
615 self.push_str(&name);
616 self.print_generics(lt);
617 self.push_str(" {\n");
618 self.push_str(
619 "fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
620 );
621 self.push_str(&format!("f.debug_struct(\"{}\")", name));
622 for field in record.fields.iter() {
623 self.push_str(&format!(
624 ".field(\"{}\", &self.{})",
625 field.name,
626 to_rust_ident(&field.name)
627 ));
628 }
629 self.push_str(".finish()\n");
630 self.push_str("}\n");
631 self.push_str("}\n");
632
633 if info.error {
634 self.push_str("impl");
635 self.print_generics(lt);
636 self.push_str(" ::core::fmt::Display for ");
637 self.push_str(&name);
638 self.print_generics(lt);
639 self.push_str(" {\n");
640 self.push_str(
641 "fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
642 );
643 self.push_str("write!(f, \"{:?}\", self)\n");
644 self.push_str("}\n");
645 self.push_str("}\n");
646 if self.std_feature() {
647 self.push_str("#[cfg(feature = \"std\")]");
648 }
649 self.push_str("impl std::error::Error for ");
650 self.push_str(&name);
651 self.push_str("{}\n");
652 }
653 }
654 }
655
656 fn print_typedef_tuple(&mut self, id: TypeId, tuple: &Tuple, docs: &Docs) {
657 let info = self.info(id);
658 for (name, mode) in self.modes_of(id) {
659 let lt = self.lifetime_for(&info, mode);
660 self.rustdoc(docs);
661 self.push_str(&format!("pub type {}", name));
662 self.print_generics(lt);
663 self.push_str(" = (");
664 for ty in tuple.types.iter() {
665 self.print_ty(ty, mode);
666 self.push_str(",");
667 }
668 self.push_str(");\n");
669 }
670 }
671
672 fn print_typedef_variant(
673 &mut self,
674 id: TypeId,
675 variant: &Variant,
676 docs: &Docs,
677 derive_component: bool,
678 ) where
679 Self: Sized,
680 {
681 self.print_rust_enum(
682 id,
683 variant.cases.iter().map(|c| {
684 (
685 c.name.to_upper_camel_case(),
686 Some(c.name.clone()),
687 &c.docs,
688 c.ty.as_ref(),
689 )
690 }),
691 docs,
692 if derive_component {
693 Some("variant")
694 } else {
695 None
696 },
697 );
698 }
699
700 fn print_rust_enum<'b>(
701 &mut self,
702 id: TypeId,
703 cases: impl IntoIterator<Item = (String, Option<String>, &'b Docs, Option<&'b Type>)> + Clone,
704 docs: &Docs,
705 derive_component: Option<&str>,
706 ) where
707 Self: Sized,
708 {
709 let info = self.info(id);
710
711 for (name, mode) in self.modes_of(id) {
712 self.rustdoc(docs);
713 let lt = self.lifetime_for(&info, mode);
714 if let Some(derive_component) = derive_component {
715 self.push_str("#[derive(wasmtime::component::ComponentType)]\n");
716 if lt.is_none() {
717 self.push_str("#[derive(wasmtime::component::Lift)]\n");
718 }
719 self.push_str("#[derive(wasmtime::component::Lower)]\n");
720 self.push_str(&format!("#[component({})]\n", derive_component));
721 }
722 if info.is_copy() {
723 self.push_str("#[derive(Copy, Clone)]\n");
724 } else if info.is_clone() {
725 self.push_str("#[derive(Clone)]\n");
726 }
727 self.push_str(&format!("pub enum {name}"));
728 self.print_generics(lt);
729 self.push_str("{\n");
730 for (case_name, component_name, docs, payload) in cases.clone() {
731 self.rustdoc(docs);
732 if derive_component.is_some() {
733 if let Some(n) = component_name {
734 self.push_str(&format!("#[component(name = \"{}\")] ", n));
735 }
736 }
737 self.push_str(&case_name);
738 if let Some(ty) = payload {
739 self.push_str("(");
740 self.print_ty(ty, mode);
741 self.push_str(")")
742 }
743 self.push_str(",\n");
744 }
745 self.push_str("}\n");
746
747 self.print_rust_enum_debug(
748 id,
749 mode,
750 &name,
751 cases
752 .clone()
753 .into_iter()
754 .map(|(name, _attr, _docs, ty)| (name, ty)),
755 );
756
757 if info.error {
758 self.push_str("impl");
759 self.print_generics(lt);
760 self.push_str(" ::core::fmt::Display for ");
761 self.push_str(&name);
762 self.print_generics(lt);
763 self.push_str(" {\n");
764 self.push_str(
765 "fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
766 );
767 self.push_str("write!(f, \"{:?}\", self)\n");
768 self.push_str("}\n");
769 self.push_str("}\n");
770 self.push_str("\n");
771
772 if self.std_feature() {
773 self.push_str("#[cfg(feature = \"std\")]");
774 }
775 self.push_str("impl");
776 self.print_generics(lt);
777 self.push_str(" std::error::Error for ");
778 self.push_str(&name);
779 self.print_generics(lt);
780 self.push_str(" {}\n");
781 }
782 }
783 }
784
785 fn print_rust_enum_debug<'b>(
786 &mut self,
787 id: TypeId,
788 mode: TypeMode,
789 name: &str,
790 cases: impl IntoIterator<Item = (String, Option<&'b Type>)>,
791 ) where
792 Self: Sized,
793 {
794 let info = self.info(id);
795 let lt = self.lifetime_for(&info, mode);
796 self.push_str("impl");
797 self.print_generics(lt);
798 self.push_str(" ::core::fmt::Debug for ");
799 self.push_str(name);
800 self.print_generics(lt);
801 self.push_str(" {\n");
802 self.push_str(
803 "fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
804 );
805 self.push_str("match self {\n");
806 for (case_name, payload) in cases {
807 self.push_str(name);
808 self.push_str("::");
809 self.push_str(&case_name);
810 if payload.is_some() {
811 self.push_str("(e)");
812 }
813 self.push_str(" => {\n");
814 self.push_str(&format!("f.debug_tuple(\"{}::{}\")", name, case_name));
815 if payload.is_some() {
816 self.push_str(".field(e)");
817 }
818 self.push_str(".finish()\n");
819 self.push_str("}\n");
820 }
821 self.push_str("}\n");
822 self.push_str("}\n");
823 self.push_str("}\n");
824 }
825
826 fn print_typedef_option(&mut self, id: TypeId, payload: &Type, docs: &Docs) {
827 let info = self.info(id);
828
829 for (name, mode) in self.modes_of(id) {
830 self.rustdoc(docs);
831 let lt = self.lifetime_for(&info, mode);
832 self.push_str(&format!("pub type {}", name));
833 self.print_generics(lt);
834 self.push_str("= Option<");
835 self.print_ty(payload, mode);
836 self.push_str(">;\n");
837 }
838 }
839
840 fn print_typedef_result(&mut self, id: TypeId, result: &Result_, docs: &Docs) {
841 let info = self.info(id);
842
843 for (name, mode) in self.modes_of(id) {
844 self.rustdoc(docs);
845 let lt = self.lifetime_for(&info, mode);
846 self.push_str(&format!("pub type {}", name));
847 self.print_generics(lt);
848 self.push_str("= Result<");
849 self.print_optional_ty(result.ok.as_ref(), mode);
850 self.push_str(",");
851 self.print_optional_ty(result.err.as_ref(), mode);
852 self.push_str(">;\n");
853 }
854 }
855
856 fn print_typedef_enum(
857 &mut self,
858 id: TypeId,
859 name: &str,
860 enum_: &Enum,
861 docs: &Docs,
862 attrs: &[String],
863 case_attr: Box<dyn Fn(&EnumCase) -> String>,
864 ) where
865 Self: Sized,
866 {
867 let info = self.info(id);
868
869 let name = to_upper_camel_case(name);
870 self.rustdoc(docs);
871 for attr in attrs {
872 self.push_str(&format!("{}\n", attr));
873 }
874 self.push_str("#[repr(");
875 self.int_repr(enum_.tag());
876 self.push_str(")]\n#[derive(Clone, Copy, PartialEq, Eq)]\n");
877 self.push_str(&format!("pub enum {name} {{\n"));
878 for case in enum_.cases.iter() {
879 self.rustdoc(&case.docs);
880 self.push_str(&case_attr(case));
881 self.push_str(&case.name.to_upper_camel_case());
882 self.push_str(",\n");
883 }
884 self.push_str("}\n");
885
886 if info.error {
889 self.push_str("impl ");
890 self.push_str(&name);
891 self.push_str("{\n");
892
893 self.push_str("pub fn name(&self) -> &'static str {\n");
894 self.push_str("match self {\n");
895 for case in enum_.cases.iter() {
896 self.push_str(&name);
897 self.push_str("::");
898 self.push_str(&case.name.to_upper_camel_case());
899 self.push_str(" => \"");
900 self.push_str(case.name.as_str());
901 self.push_str("\",\n");
902 }
903 self.push_str("}\n");
904 self.push_str("}\n");
905
906 self.push_str("pub fn message(&self) -> &'static str {\n");
907 self.push_str("match self {\n");
908 for case in enum_.cases.iter() {
909 self.push_str(&name);
910 self.push_str("::");
911 self.push_str(&case.name.to_upper_camel_case());
912 self.push_str(" => \"");
913 if let Some(contents) = &case.docs.contents {
914 self.push_str(contents.trim());
915 }
916 self.push_str("\",\n");
917 }
918 self.push_str("}\n");
919 self.push_str("}\n");
920
921 self.push_str("}\n");
922
923 self.push_str("impl ::core::fmt::Debug for ");
924 self.push_str(&name);
925 self.push_str(
926 "{\nfn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
927 );
928 self.push_str("f.debug_struct(\"");
929 self.push_str(&name);
930 self.push_str("\")\n");
931 self.push_str(".field(\"code\", &(*self as i32))\n");
932 self.push_str(".field(\"name\", &self.name())\n");
933 self.push_str(".field(\"message\", &self.message())\n");
934 self.push_str(".finish()\n");
935 self.push_str("}\n");
936 self.push_str("}\n");
937
938 self.push_str("impl ::core::fmt::Display for ");
939 self.push_str(&name);
940 self.push_str(
941 "{\nfn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {\n",
942 );
943 self.push_str("write!(f, \"{} (error {})\", self.name(), *self as i32)\n");
944 self.push_str("}\n");
945 self.push_str("}\n");
946 self.push_str("\n");
947 if self.std_feature() {
948 self.push_str("#[cfg(feature = \"std\")]");
949 }
950 self.push_str("impl std::error::Error for ");
951 self.push_str(&name);
952 self.push_str("{}\n");
953 } else {
954 self.print_rust_enum_debug(
955 id,
956 TypeMode::Owned,
957 &name,
958 enum_
959 .cases
960 .iter()
961 .map(|c| (c.name.to_upper_camel_case(), None)),
962 )
963 }
964 }
965
966 fn print_typedef_alias(&mut self, id: TypeId, ty: &Type, docs: &Docs) {
967 if self.is_exported_resource(id) {
968 let target = dealias(self.resolve(), id);
969 let ty = &self.resolve().types[target];
970 self.mark_resource_owned(target);
975 for prefix in ["Own", ""] {
976 self.rustdoc(docs);
977 self.push_str(&format!(
978 "pub type {prefix}{} = {};\n",
979 self.resolve().types[id]
980 .name
981 .as_deref()
982 .unwrap()
983 .to_upper_camel_case(),
984 self.type_path_with_name(
985 target,
986 format!(
987 "{prefix}{}",
988 ty.name.as_deref().unwrap().to_upper_camel_case()
989 )
990 )
991 ));
992 }
993 } else {
994 let info = self.info(id);
995 for (name, mode) in self.modes_of(id) {
996 self.rustdoc(docs);
997 self.push_str(&format!("pub type {name}"));
998 let lt = self.lifetime_for(&info, mode);
999 self.print_generics(lt);
1000 self.push_str(" = ");
1001 self.print_ty(ty, mode);
1002 self.push_str(";\n");
1003 }
1004 }
1005 }
1006
1007 fn print_type_list(&mut self, id: TypeId, ty: &Type, docs: &Docs) {
1008 let info = self.info(id);
1009 for (name, mode) in self.modes_of(id) {
1010 let lt = self.lifetime_for(&info, mode);
1011 self.rustdoc(docs);
1012 self.push_str(&format!("pub type {}", name));
1013 self.print_generics(lt);
1014 self.push_str(" = ");
1015 self.print_list(ty, mode);
1016 self.push_str(";\n");
1017 }
1018 }
1019
1020 fn param_name(&self, ty: TypeId) -> String {
1021 let info = self.info(ty);
1022 let name = to_upper_camel_case(self.resolve().types[ty].name.as_ref().unwrap());
1023 if self.uses_two_names(&info) {
1024 format!("{}Param", name)
1025 } else {
1026 name
1027 }
1028 }
1029
1030 fn result_name(&self, ty: TypeId) -> String {
1031 let info = self.info(ty);
1032 let name = to_upper_camel_case(self.resolve().types[ty].name.as_ref().unwrap());
1033 if self.uses_two_names(&info) {
1034 format!("{}Result", name)
1035 } else if self.is_exported_resource(ty) {
1036 format!("Own{name}")
1037 } else {
1038 name
1039 }
1040 }
1041
1042 fn uses_two_names(&self, info: &TypeInfo) -> bool {
1043 matches!(
1045 self.ownership(),
1046 Ownership::Borrowing {
1047 duplicate_if_necessary: true
1048 }
1049 )
1050 && info.borrowed
1052 && info.owned
1053 && info.has_list
1055 && !info.has_own_handle
1058 }
1059
1060 fn lifetime_for(&self, info: &TypeInfo, mode: TypeMode) -> Option<&'static str> {
1061 let lt = match mode {
1062 TypeMode::AllBorrowed(s) | TypeMode::LeafBorrowed(s) | TypeMode::HandlesBorrowed(s) => {
1063 s
1064 }
1065 TypeMode::Owned => return None,
1066 };
1067 if info.has_borrow_handle {
1068 return Some(lt);
1069 }
1070 if matches!(self.ownership(), Ownership::Owning) {
1071 return None;
1072 }
1073 if !info.has_list {
1075 return None;
1076 }
1077 if self.uses_two_names(info) || (info.borrowed && !info.owned) {
1083 Some(lt)
1084 } else {
1085 None
1086 }
1087 }
1088}
1089
1090#[derive(Default)]
1091pub struct FnSig {
1092 pub async_: bool,
1093 pub unsafe_: bool,
1094 pub private: bool,
1095 pub use_item_name: bool,
1096 pub generics: Option<String>,
1097 pub self_arg: Option<String>,
1098 pub self_is_first_param: bool,
1099}
1100
1101pub trait RustFunctionGenerator {
1102 fn push_str(&mut self, s: &str);
1103 fn tmp(&mut self) -> usize;
1104 fn rust_gen(&self) -> &dyn RustGenerator;
1105 fn lift_lower(&self) -> LiftLower;
1106
1107 fn let_results(&mut self, amt: usize, results: &mut Vec<String>) {
1108 match amt {
1109 0 => {}
1110 1 => {
1111 let tmp = self.tmp();
1112 let res = format!("result{}", tmp);
1113 self.push_str("let ");
1114 self.push_str(&res);
1115 results.push(res);
1116 self.push_str(" = ");
1117 }
1118 n => {
1119 let tmp = self.tmp();
1120 self.push_str("let (");
1121 for i in 0..n {
1122 let arg = format!("result{}_{}", tmp, i);
1123 self.push_str(&arg);
1124 self.push_str(",");
1125 results.push(arg);
1126 }
1127 self.push_str(") = ");
1128 }
1129 }
1130 }
1131
1132 fn record_lower(
1133 &mut self,
1134 id: TypeId,
1135 record: &Record,
1136 operand: &str,
1137 results: &mut Vec<String>,
1138 ) {
1139 let tmp = self.tmp();
1140 self.push_str("let ");
1141 let name = self.typename_lower(id);
1142 self.push_str(&name);
1143 self.push_str("{ ");
1144 for field in record.fields.iter() {
1145 let name = to_rust_ident(&field.name);
1146 let arg = format!("{}{}", name, tmp);
1147 self.push_str(&name);
1148 self.push_str(":");
1149 self.push_str(&arg);
1150 self.push_str(", ");
1151 results.push(arg);
1152 }
1153 self.push_str("} = ");
1154 self.push_str(operand);
1155 self.push_str(";\n");
1156 }
1157
1158 fn record_lift(
1159 &mut self,
1160 id: TypeId,
1161 ty: &Record,
1162 operands: &[String],
1163 results: &mut Vec<String>,
1164 ) {
1165 let mut result = self.typename_lift(id);
1166 result.push_str("{\n");
1167 for (field, val) in ty.fields.iter().zip(operands) {
1168 result.push_str(&to_rust_ident(&field.name));
1169 result.push_str(": ");
1170 result.push_str(&val);
1171 result.push_str(",\n");
1172 }
1173 result.push_str("}");
1174 results.push(result);
1175 }
1176
1177 fn tuple_lower(&mut self, tuple: &Tuple, operand: &str, results: &mut Vec<String>) {
1178 let tmp = self.tmp();
1179 self.push_str("let (");
1180 for i in 0..tuple.types.len() {
1181 let arg = format!("t{}_{}", tmp, i);
1182 self.push_str(&arg);
1183 self.push_str(", ");
1184 results.push(arg);
1185 }
1186 self.push_str(") = ");
1187 self.push_str(operand);
1188 self.push_str(";\n");
1189 }
1190
1191 fn tuple_lift(&mut self, operands: &[String], results: &mut Vec<String>) {
1192 if operands.len() == 1 {
1193 results.push(format!("({},)", operands[0]));
1194 } else {
1195 results.push(format!("({})", operands.join(", ")));
1196 }
1197 }
1198
1199 fn typename_lower(&self, id: TypeId) -> String {
1200 let owned = match self.lift_lower() {
1201 LiftLower::LowerArgsLiftResults => false,
1202 LiftLower::LiftArgsLowerResults => true,
1203 };
1204 self.rust_gen().type_path(id, owned)
1205 }
1206
1207 fn typename_lift(&self, id: TypeId) -> String {
1208 self.rust_gen().type_path(id, true)
1209 }
1210}
1211
1212pub fn to_rust_ident(name: &str) -> String {
1213 match name {
1214 "as" => "as_".into(),
1217 "break" => "break_".into(),
1218 "const" => "const_".into(),
1219 "continue" => "continue_".into(),
1220 "crate" => "crate_".into(),
1221 "else" => "else_".into(),
1222 "enum" => "enum_".into(),
1223 "extern" => "extern_".into(),
1224 "false" => "false_".into(),
1225 "fn" => "fn_".into(),
1226 "for" => "for_".into(),
1227 "if" => "if_".into(),
1228 "impl" => "impl_".into(),
1229 "in" => "in_".into(),
1230 "let" => "let_".into(),
1231 "loop" => "loop_".into(),
1232 "match" => "match_".into(),
1233 "mod" => "mod_".into(),
1234 "move" => "move_".into(),
1235 "mut" => "mut_".into(),
1236 "pub" => "pub_".into(),
1237 "ref" => "ref_".into(),
1238 "return" => "return_".into(),
1239 "self" => "self_".into(),
1240 "static" => "static_".into(),
1241 "struct" => "struct_".into(),
1242 "super" => "super_".into(),
1243 "trait" => "trait_".into(),
1244 "true" => "true_".into(),
1245 "type" => "type_".into(),
1246 "unsafe" => "unsafe_".into(),
1247 "use" => "use_".into(),
1248 "where" => "where_".into(),
1249 "while" => "while_".into(),
1250 "async" => "async_".into(),
1251 "await" => "await_".into(),
1252 "dyn" => "dyn_".into(),
1253 "abstract" => "abstract_".into(),
1254 "become" => "become_".into(),
1255 "box" => "box_".into(),
1256 "do" => "do_".into(),
1257 "final" => "final_".into(),
1258 "macro" => "macro_".into(),
1259 "override" => "override_".into(),
1260 "priv" => "priv_".into(),
1261 "typeof" => "typeof_".into(),
1262 "unsized" => "unsized_".into(),
1263 "virtual" => "virtual_".into(),
1264 "yield" => "yield_".into(),
1265 "try" => "try_".into(),
1266 s => s.to_snake_case(),
1267 }
1268}
1269
1270pub fn to_upper_camel_case(name: &str) -> String {
1271 match name {
1272 "guest" => "Guest_".to_string(),
1275 s => s.to_upper_camel_case(),
1276 }
1277}
1278
1279pub fn wasm_type(ty: WasmType) -> &'static str {
1280 match ty {
1281 WasmType::I32 => "i32",
1282 WasmType::I64 => "i64",
1283 WasmType::F32 => "f32",
1284 WasmType::F64 => "f64",
1285 }
1286}
1287
1288pub fn int_repr(repr: Int) -> &'static str {
1289 match repr {
1290 Int::U8 => "u8",
1291 Int::U16 => "u16",
1292 Int::U32 => "u32",
1293 Int::U64 => "u64",
1294 }
1295}
1296
1297pub fn bitcast(casts: &[Bitcast], operands: &[String], results: &mut Vec<String>) {
1298 for (cast, operand) in casts.iter().zip(operands) {
1299 results.push(match cast {
1300 Bitcast::None => operand.clone(),
1301 Bitcast::I32ToI64 => format!("i64::from({})", operand),
1302 Bitcast::F32ToI32 => format!("({}).to_bits() as i32", operand),
1303 Bitcast::F64ToI64 => format!("({}).to_bits() as i64", operand),
1304 Bitcast::I64ToI32 => format!("{} as i32", operand),
1305 Bitcast::I32ToF32 => format!("f32::from_bits({} as u32)", operand),
1306 Bitcast::I64ToF64 => format!("f64::from_bits({} as u64)", operand),
1307 Bitcast::F32ToI64 => format!("i64::from(({}).to_bits())", operand),
1308 Bitcast::I64ToF32 => format!("f32::from_bits({} as u32)", operand),
1309 });
1310 }
1311}
1312
1313pub enum RustFlagsRepr {
1314 U8,
1315 U16,
1316 U32,
1317 U64,
1318 U128,
1319}
1320
1321impl RustFlagsRepr {
1322 pub fn new(f: &Flags) -> RustFlagsRepr {
1323 match f.repr() {
1324 FlagsRepr::U8 => RustFlagsRepr::U8,
1325 FlagsRepr::U16 => RustFlagsRepr::U16,
1326 FlagsRepr::U32(1) => RustFlagsRepr::U32,
1327 FlagsRepr::U32(2) => RustFlagsRepr::U64,
1328 FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
1329 FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
1330 }
1331 }
1332}
1333
1334impl fmt::Display for RustFlagsRepr {
1335 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1336 match self {
1337 RustFlagsRepr::U8 => "u8".fmt(f),
1338 RustFlagsRepr::U16 => "u16".fmt(f),
1339 RustFlagsRepr::U32 => "u32".fmt(f),
1340 RustFlagsRepr::U64 => "u64".fmt(f),
1341 RustFlagsRepr::U128 => "u128".fmt(f),
1342 }
1343 }
1344}
1345
1346pub fn dealias(resolve: &Resolve, mut id: TypeId) -> TypeId {
1347 loop {
1348 match &resolve.types[id].kind {
1349 TypeDefKind::Type(Type::Id(that_id)) => id = *that_id,
1350 _ => break id,
1351 }
1352 }
1353}