1use crate::interface::InterfaceGenerator;
2use anyhow::{bail, Result};
3use heck::{ToSnakeCase, ToUpperCamelCase};
4use std::collections::{BTreeMap, HashMap, HashSet};
5use std::fmt::{self, Write as _};
6use std::mem;
7use wit_bindgen_core::wit_parser::{
8 Flags, FlagsRepr, Function, Int, InterfaceId, Resolve, SizeAlign, TypeId, World, WorldId,
9 WorldItem, WorldKey,
10};
11use wit_bindgen_core::{
12 name_package_module, uwrite, uwriteln, Files, InterfaceGenerator as _, Source, Types,
13 WorldGenerator,
14};
15
16mod interface;
17
18struct InterfaceName {
19 remapped: bool,
22
23 path: String,
25}
26
27#[derive(Default)]
28struct RustWrpc {
29 types: Types,
30 src_preamble: Source,
31 src: Source,
32 opts: Opts,
33 import_modules: Vec<(String, Vec<String>)>,
34 export_modules: Vec<(String, Vec<String>)>,
35 skip: HashSet<String>,
36 interface_names: HashMap<InterfaceId, InterfaceName>,
37 import_funcs_called: bool,
38 with_name_counter: usize,
39 generated_interfaces: HashSet<String>,
42 world: Option<WorldId>,
43
44 export_paths: Vec<String>,
45 with: GenerationConfiguration,
47}
48
49#[derive(Default)]
50struct GenerationConfiguration {
51 map: HashMap<String, InterfaceGeneration>,
52 generate_by_default: bool,
53}
54
55impl GenerationConfiguration {
56 fn get(&self, key: &str) -> Option<&InterfaceGeneration> {
57 self.map.get(key).or_else(|| {
58 self.generate_by_default
59 .then_some(&InterfaceGeneration::Generate)
60 })
61 }
62
63 fn insert(&mut self, name: String, generate: InterfaceGeneration) {
64 self.map.insert(name, generate);
65 }
66
67 fn iter(&self) -> impl Iterator<Item = (&String, &InterfaceGeneration)> {
68 self.map.iter()
69 }
70}
71
72enum InterfaceGeneration {
74 Remap(String),
76 Generate,
78}
79
80#[cfg(feature = "clap")]
81fn parse_with(s: &str) -> Result<(String, WithOption), String> {
82 let (k, v) = s.split_once('=').ok_or_else(|| {
83 format!("expected string of form `<key>=<value>[,<key>=<value>...]`; got `{s}`")
84 })?;
85 let v = match v {
86 "generate" => WithOption::Generate,
87 other => WithOption::Path(other.to_string()),
88 };
89 Ok((k.to_string(), v))
90}
91
92#[derive(Default, Debug, Clone)]
93#[cfg_attr(feature = "clap", derive(clap::Args))]
94pub struct Opts {
95 #[cfg_attr(feature = "clap", arg(long))]
97 pub format: bool,
98
99 #[cfg_attr(feature = "clap", arg(long))]
101 pub skip: Vec<String>,
102
103 #[cfg_attr(feature = "clap", arg(long))]
107 pub bitflags_path: Option<String>,
108
109 #[cfg_attr(feature = "clap", arg(long = "additional_derive_attribute", short = 'd', default_values_t = Vec::<String>::new()))]
114 pub additional_derive_attributes: Vec<String>,
115
116 #[cfg_attr(feature = "clap", arg(long, value_parser = parse_with, value_delimiter = ','))]
122 pub with: Vec<(String, WithOption)>,
123
124 #[cfg_attr(feature = "clap", arg(long))]
127 pub generate_all: bool,
128
129 #[cfg_attr(feature = "clap", arg(long))]
131 pub generate_unused_types: bool,
132
133 #[cfg_attr(feature = "clap", arg(long))]
137 pub anyhow_path: Option<String>,
138
139 #[cfg_attr(feature = "clap", arg(long))]
143 pub bytes_path: Option<String>,
144
145 #[cfg_attr(feature = "clap", arg(long))]
149 pub futures_path: Option<String>,
150
151 #[cfg_attr(feature = "clap", arg(long))]
155 pub tokio_path: Option<String>,
156
157 #[cfg_attr(feature = "clap", arg(long))]
161 pub tokio_util_path: Option<String>,
162
163 #[cfg_attr(feature = "clap", arg(long))]
167 pub tracing_path: Option<String>,
168
169 #[cfg_attr(feature = "clap", arg(long))]
173 pub wasm_tokio_path: Option<String>,
174
175 #[cfg_attr(feature = "clap", arg(long))]
179 pub wrpc_transport_path: Option<String>,
180}
181
182impl Opts {
183 #[must_use]
184 pub fn build(self) -> Box<dyn WorldGenerator> {
185 let mut r = RustWrpc::new();
186 r.skip = self.skip.iter().cloned().collect();
187 r.opts = self;
188 Box::new(r)
189 }
190}
191
192impl RustWrpc {
193 fn new() -> RustWrpc {
194 RustWrpc::default()
195 }
196
197 fn interface<'a>(
198 &'a mut self,
199 identifier: Identifier<'a>,
200 resolve: &'a Resolve,
201 in_import: bool,
202 ) -> InterfaceGenerator<'a> {
203 let mut sizes = SizeAlign::default();
204 sizes.fill(resolve);
205
206 InterfaceGenerator {
207 identifier,
208 src: Source::default(),
209 in_import,
210 gen: self,
211 resolve,
212 }
213 }
214
215 fn emit_modules(&mut self, modules: Vec<(String, Vec<String>)>) {
216 #[derive(Default)]
217 struct Module {
218 submodules: BTreeMap<String, Module>,
219 contents: Vec<String>,
220 }
221 let mut map = Module::default();
222 for (module, path) in modules {
223 let mut cur = &mut map;
224 for name in &path[..path.len() - 1] {
225 cur = cur
226 .submodules
227 .entry(name.clone())
228 .or_insert(Module::default());
229 }
230 cur.contents.push(module);
231 }
232
233 emit(&mut self.src, map, &self.opts, true);
234 fn emit(me: &mut Source, module: Module, opts: &Opts, toplevel: bool) {
235 for (name, submodule) in module.submodules {
236 if toplevel {
237 if opts.format {
241 uwriteln!(me, "#[rustfmt::skip]");
242 }
243
244 uwriteln!(me, "#[allow(dead_code, clippy::all)]");
248 }
249
250 uwriteln!(me, "pub mod {name} {{");
251 emit(me, submodule, opts, false);
252 uwriteln!(me, "}}");
253 }
254 for submodule in module.contents {
255 uwriteln!(me, "{submodule}");
256 }
257 }
258 }
259
260 fn anyhow_path(&self) -> &str {
261 self.opts
262 .anyhow_path
263 .as_deref()
264 .unwrap_or("::wit_bindgen_wrpc::anyhow")
265 }
266
267 fn bitflags_path(&self) -> &str {
268 self.opts
269 .bitflags_path
270 .as_deref()
271 .unwrap_or("::wit_bindgen_wrpc::bitflags")
272 }
273
274 fn bytes_path(&self) -> &str {
275 self.opts
276 .bytes_path
277 .as_deref()
278 .unwrap_or("::wit_bindgen_wrpc::bytes")
279 }
280
281 fn futures_path(&self) -> &str {
282 self.opts
283 .futures_path
284 .as_deref()
285 .unwrap_or("::wit_bindgen_wrpc::futures")
286 }
287
288 fn tokio_path(&self) -> &str {
289 self.opts
290 .tokio_path
291 .as_deref()
292 .unwrap_or("::wit_bindgen_wrpc::tokio")
293 }
294
295 fn tokio_util_path(&self) -> &str {
296 self.opts
297 .tokio_util_path
298 .as_deref()
299 .unwrap_or("::wit_bindgen_wrpc::tokio_util")
300 }
301
302 fn tracing_path(&self) -> &str {
303 self.opts
304 .tracing_path
305 .as_deref()
306 .unwrap_or("::wit_bindgen_wrpc::tracing")
307 }
308
309 fn wasm_tokio_path(&self) -> &str {
310 self.opts
311 .wasm_tokio_path
312 .as_deref()
313 .unwrap_or("::wit_bindgen_wrpc::wasm_tokio")
314 }
315
316 fn wrpc_transport_path(&self) -> &str {
317 self.opts
318 .wrpc_transport_path
319 .as_deref()
320 .unwrap_or("::wit_bindgen_wrpc::wrpc_transport")
321 }
322
323 fn name_interface(
324 &mut self,
325 resolve: &Resolve,
326 id: InterfaceId,
327 name: &WorldKey,
328 is_export: bool,
329 ) -> Result<bool> {
330 let with_name = resolve.name_world_key(name);
331 let Some(remapping) = self.with.get(&with_name) else {
332 bail!("no remapping found for {with_name:?} - use the `generate!` macro's `with` option to force the interface to be generated or specify where it is already defined:
333```
334with: {{\n\t{with_name:?}: generate\n}}
335```")
336 };
337 self.generated_interfaces.insert(with_name);
338 let entry = match remapping {
339 InterfaceGeneration::Remap(remapped_path) => {
340 let name = format!("__with_name{}", self.with_name_counter);
341 self.with_name_counter += 1;
342 uwriteln!(self.src, "use {remapped_path} as {name};");
343 InterfaceName {
344 remapped: true,
345 path: name,
346 }
347 }
348 InterfaceGeneration::Generate => {
349 let path = compute_module_path(name, resolve, is_export).join("::");
350
351 InterfaceName {
352 remapped: false,
353 path,
354 }
355 }
356 };
357
358 let remapped = entry.remapped;
359 self.interface_names.insert(id, entry);
360
361 Ok(remapped)
362 }
363
364 fn finish_serve_function(&mut self) {
370 const ROOT: &str = "Handler<T::Context>";
371 let mut traits: Vec<String> = self
372 .export_paths
373 .iter()
374 .map(|path| {
375 if path.is_empty() {
376 ROOT.to_string()
377 } else {
378 format!("{path}::{ROOT}")
379 }
380 })
381 .collect();
382 let bound = match traits.len() {
383 0 => return,
384 1 => traits.pop().unwrap(),
385 _ => traits.join(" + "),
386 };
387 let anyhow = self.anyhow_path().to_string();
388 let futures = self.futures_path().to_string();
389 let tokio = self.tokio_path().to_string();
390 let wrpc_transport = self.wrpc_transport_path().to_string();
391 uwriteln!(
392 self.src,
393 r#"
394#[allow(clippy::manual_async_fn)]
395pub fn serve<'a, T: {wrpc_transport}::Serve>(
396 wrpc: &'a T,
397 handler: impl {bound} + ::core::marker::Send + ::core::marker::Sync + ::core::clone::Clone + 'static,
398) -> impl ::core::future::Future<
399 Output = {anyhow}::Result<
400 ::std::vec::Vec<
401 (
402 &'static str,
403 &'static str,
404 ::core::pin::Pin<
405 ::std::boxed::Box<
406 dyn {futures}::Stream<
407 Item = {anyhow}::Result<
408 ::core::pin::Pin<
409 ::std::boxed::Box<
410 dyn ::core::future::Future<
411 Output = {anyhow}::Result<()>
412 > + ::core::marker::Send + 'static
413 >
414 >
415 >
416 > + ::core::marker::Send + 'static
417 >
418 >
419 )
420 >
421 >
422 > + ::core::marker::Send + {wrpc_transport}::Captures<'a> {{
423 async move {{
424 let interfaces = {tokio}::try_join!("#
425 );
426 for path in &self.export_paths {
427 if !path.is_empty() {
428 self.src.push_str(path);
429 self.src.push_str("::");
430 }
431 self.src.push_str("serve_interface(wrpc, handler.clone()),");
432 }
433 uwriteln!(
434 self.src,
435 r#"
436 )?;
437 let mut streams = Vec::new();"#
438 );
439 for i in 0..self.export_paths.len() {
440 uwrite!(
441 self.src,
442 r"
443 for s in interfaces.{i} {{
444 streams.push(s);
445 }}"
446 );
447 }
448 uwriteln!(
449 self.src,
450 r#"
451 Ok(streams)
452 }}
453}}"#
454 );
455 }
456}
457
458impl WorldGenerator for RustWrpc {
459 fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
460 wit_bindgen_core::generated_preamble(&mut self.src_preamble, env!("CARGO_PKG_VERSION"));
461
462 uwriteln!(self.src_preamble, "// Options used:");
465 if !self.opts.skip.is_empty() {
466 uwriteln!(self.src_preamble, "// * skip: {:?}", self.opts.skip);
467 }
468 if !self.opts.additional_derive_attributes.is_empty() {
469 uwriteln!(
470 self.src_preamble,
471 "// * additional derives {:?}",
472 self.opts.additional_derive_attributes
473 );
474 }
475 for (k, v) in &self.opts.with {
476 uwriteln!(self.src_preamble, "// * with {k:?} = {v:?}");
477 }
478 self.types.analyze(resolve);
479 self.world = Some(world);
480
481 let world = &resolve.worlds[world];
482 for (key, item) in world.imports.iter().chain(world.exports.iter()) {
484 if let WorldItem::Interface { id, .. } = item {
485 if resolve.interfaces[*id].package == world.package {
486 let name = resolve.name_world_key(key);
487 if self.with.get(&name).is_none() {
488 self.with.insert(name, InterfaceGeneration::Generate);
489 }
490 }
491 }
492 }
493 for (k, v) in &self.opts.with {
494 self.with.insert(k.clone(), v.clone().into());
495 }
496 self.with.generate_by_default = self.opts.generate_all;
497 }
498
499 fn import_interface(
500 &mut self,
501 resolve: &Resolve,
502 name: &WorldKey,
503 id: InterfaceId,
504 _files: &mut Files,
505 ) -> Result<()> {
506 let mut gen = self.interface(Identifier::Interface(id, name), resolve, true);
507 let (snake, module_path) = gen.start_append_submodule(name);
508 if gen.gen.name_interface(resolve, id, name, false)? {
509 return Ok(());
510 }
511 gen.types(id);
512
513 let interface = &resolve.interfaces[id];
514 let name = match name {
515 WorldKey::Name(s) => s.to_string(),
516 WorldKey::Interface(..) => interface
517 .name
518 .as_ref()
519 .expect("interface name missing")
520 .to_string(),
521 };
522 let instance = if let Some(package) = interface.package {
523 resolve.id_of_name(package, &name)
524 } else {
525 name
526 };
527 gen.generate_imports(&instance, resolve.interfaces[id].functions.values());
528
529 let docs = &resolve.interfaces[id].docs;
530
531 gen.finish_append_submodule(&snake, module_path, docs);
532
533 Ok(())
534 }
535
536 fn import_funcs(
537 &mut self,
538 resolve: &Resolve,
539 world: WorldId,
540 funcs: &[(&str, &Function)],
541 _files: &mut Files,
542 ) {
543 self.import_funcs_called = true;
544
545 let mut gen = self.interface(Identifier::World(world), resolve, true);
546 let World {
547 ref name, package, ..
548 } = resolve.worlds[world];
549 let instance = if let Some(package) = package {
550 resolve.id_of_name(package, name)
551 } else {
552 name.to_string()
553 };
554 gen.generate_imports(&instance, funcs.iter().map(|(_, func)| *func));
555
556 let src = gen.finish();
557 self.src.push_str(&src);
558 }
559
560 fn export_interface(
561 &mut self,
562 resolve: &Resolve,
563 name: &WorldKey,
564 id: InterfaceId,
565 _files: &mut Files,
566 ) -> Result<()> {
567 let mut gen = self.interface(Identifier::Interface(id, name), resolve, false);
568 let (snake, module_path) = gen.start_append_submodule(name);
569 if gen.gen.name_interface(resolve, id, name, true)? {
570 return Ok(());
571 }
572 gen.types(id);
573 let exports = gen.generate_exports(
574 Identifier::Interface(id, name),
575 resolve.interfaces[id].functions.values(),
576 );
577
578 let docs = &resolve.interfaces[id].docs;
579
580 gen.finish_append_submodule(&snake, module_path, docs);
581 if exports {
582 self.export_paths
583 .push(self.interface_names[&id].path.clone());
584 }
585 Ok(())
586 }
587
588 fn export_funcs(
589 &mut self,
590 resolve: &Resolve,
591 world: WorldId,
592 funcs: &[(&str, &Function)],
593 _files: &mut Files,
594 ) -> Result<()> {
595 let mut gen = self.interface(Identifier::World(world), resolve, false);
596 let exports = gen.generate_exports(Identifier::World(world), funcs.iter().map(|f| f.1));
597 let src = gen.finish();
598 self.src.push_str(&src);
599 if exports {
600 self.export_paths.push(String::new());
601 }
602 Ok(())
603 }
604
605 fn import_types(
606 &mut self,
607 resolve: &Resolve,
608 world: WorldId,
609 types: &[(&str, TypeId)],
610 _files: &mut Files,
611 ) {
612 let mut gen = self.interface(Identifier::World(world), resolve, true);
613 for (name, ty) in types {
614 gen.define_type(name, *ty);
615 }
616 let src = gen.finish();
617 self.src.push_str(&src);
618 }
619
620 fn finish_imports(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) {
621 if !self.import_funcs_called {
622 self.import_funcs(resolve, world, &[], files);
626 }
627 }
628
629 fn finish(&mut self, resolve: &Resolve, world: WorldId, files: &mut Files) -> Result<()> {
630 let name = &resolve.worlds[world].name;
631
632 let imports = mem::take(&mut self.import_modules);
633 self.emit_modules(imports);
634 let exports = mem::take(&mut self.export_modules);
635 self.emit_modules(exports);
636
637 self.finish_serve_function();
638
639 let mut src = mem::take(&mut self.src);
640 if self.opts.format {
641 let syntax_tree = syn::parse_file(src.as_str()).unwrap();
642 *src.as_mut_string() = prettyplease::unparse(&syntax_tree);
643 }
644
645 let src_preamble = mem::take(&mut self.src_preamble);
648 *src.as_mut_string() = format!("{}{}", src_preamble.as_str(), src.as_str());
649
650 let module_name = name.to_snake_case();
651 files.push(&format!("{module_name}.rs"), src.as_bytes());
652
653 let remapped_keys = self
654 .with
655 .iter()
656 .map(|(k, _)| k)
657 .cloned()
658 .collect::<HashSet<String>>();
659
660 let mut unused_keys = remapped_keys
661 .difference(&self.generated_interfaces)
662 .collect::<Vec<&String>>();
663
664 unused_keys.sort();
665
666 if !unused_keys.is_empty() {
667 bail!("unused remappings provided via `with`: {unused_keys:?}");
668 }
669
670 Ok(())
671 }
672}
673
674fn compute_module_path(name: &WorldKey, resolve: &Resolve, is_export: bool) -> Vec<String> {
675 let mut path = Vec::new();
676 if is_export {
677 path.push("exports".to_string());
678 }
679 match name {
680 WorldKey::Name(name) => {
681 path.push(to_rust_ident(name));
682 }
683 WorldKey::Interface(id) => {
684 let iface = &resolve.interfaces[*id];
685 let pkg = iface.package.unwrap();
686 let pkgname = resolve.packages[pkg].name.clone();
687 path.push(to_rust_ident(&pkgname.namespace));
688 path.push(to_rust_ident(&name_package_module(resolve, pkg)));
689 path.push(to_rust_ident(iface.name.as_ref().unwrap()));
690 }
691 }
692 path
693}
694
695enum Identifier<'a> {
696 World(WorldId),
697 Interface(InterfaceId, &'a WorldKey),
698}
699
700#[derive(Debug, Clone)]
702pub enum WithOption {
703 Path(String),
704 Generate,
705}
706
707impl std::fmt::Display for WithOption {
708 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
709 match self {
710 WithOption::Path(p) => f.write_fmt(format_args!("\"{p}\"")),
711 WithOption::Generate => f.write_str("generate"),
712 }
713 }
714}
715
716impl From<WithOption> for InterfaceGeneration {
717 fn from(opt: WithOption) -> Self {
718 match opt {
719 WithOption::Path(p) => InterfaceGeneration::Remap(p),
720 WithOption::Generate => InterfaceGeneration::Generate,
721 }
722 }
723}
724
725#[derive(Default)]
726struct FnSig {
727 private: bool,
728 use_item_name: bool,
729 self_arg: Option<String>,
730 self_is_first_param: bool,
731}
732
733#[must_use]
734pub fn to_rust_ident(name: &str) -> String {
735 match name {
736 "as" => "as_".into(),
739 "break" => "break_".into(),
740 "const" => "const_".into(),
741 "continue" => "continue_".into(),
742 "crate" => "crate_".into(),
743 "else" => "else_".into(),
744 "enum" => "enum_".into(),
745 "extern" => "extern_".into(),
746 "false" => "false_".into(),
747 "fn" => "fn_".into(),
748 "for" => "for_".into(),
749 "if" => "if_".into(),
750 "impl" => "impl_".into(),
751 "in" => "in_".into(),
752 "let" => "let_".into(),
753 "loop" => "loop_".into(),
754 "match" => "match_".into(),
755 "mod" => "mod_".into(),
756 "move" => "move_".into(),
757 "mut" => "mut_".into(),
758 "pub" => "pub_".into(),
759 "ref" => "ref_".into(),
760 "return" => "return_".into(),
761 "self" => "self_".into(),
762 "static" => "static_".into(),
763 "struct" => "struct_".into(),
764 "super" => "super_".into(),
765 "trait" => "trait_".into(),
766 "true" => "true_".into(),
767 "type" => "type_".into(),
768 "unsafe" => "unsafe_".into(),
769 "use" => "use_".into(),
770 "where" => "where_".into(),
771 "while" => "while_".into(),
772 "async" => "async_".into(),
773 "await" => "await_".into(),
774 "dyn" => "dyn_".into(),
775 "abstract" => "abstract_".into(),
776 "become" => "become_".into(),
777 "box" => "box_".into(),
778 "do" => "do_".into(),
779 "final" => "final_".into(),
780 "macro" => "macro_".into(),
781 "override" => "override_".into(),
782 "priv" => "priv_".into(),
783 "typeof" => "typeof_".into(),
784 "unsized" => "unsized_".into(),
785 "virtual" => "virtual_".into(),
786 "yield" => "yield_".into(),
787 "try" => "try_".into(),
788 s => s.to_snake_case(),
789 }
790}
791
792fn to_upper_camel_case(name: &str) -> String {
793 match name {
794 "handler" => "Handler_".to_string(),
797 s => s.to_upper_camel_case(),
798 }
799}
800
801fn int_repr(repr: Int) -> &'static str {
802 match repr {
803 Int::U8 => "u8",
804 Int::U16 => "u16",
805 Int::U32 => "u32",
806 Int::U64 => "u64",
807 }
808}
809
810enum RustFlagsRepr {
811 U8,
812 U16,
813 U32,
814 U64,
815 U128,
816}
817
818impl RustFlagsRepr {
819 fn new(f: &Flags) -> RustFlagsRepr {
820 match f.repr() {
821 FlagsRepr::U8 => RustFlagsRepr::U8,
822 FlagsRepr::U16 => RustFlagsRepr::U16,
823 FlagsRepr::U32(1) => RustFlagsRepr::U32,
824 FlagsRepr::U32(2) => RustFlagsRepr::U64,
825 FlagsRepr::U32(3 | 4) => RustFlagsRepr::U128,
826 FlagsRepr::U32(n) => panic!("unsupported number of flags: {}", n * 32),
827 }
828 }
829}
830
831impl fmt::Display for RustFlagsRepr {
832 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833 match self {
834 RustFlagsRepr::U8 => "u8".fmt(f),
835 RustFlagsRepr::U16 => "u16".fmt(f),
836 RustFlagsRepr::U32 => "u32".fmt(f),
837 RustFlagsRepr::U64 => "u64".fmt(f),
838 RustFlagsRepr::U128 => "u128".fmt(f),
839 }
840 }
841}
842
843#[derive(Debug, Clone)]
844pub struct MissingWith(pub String);
845
846impl fmt::Display for MissingWith {
847 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
848 write!(f, "missing `with` mapping for the key `{}`", self.0)
849 }
850}
851
852impl std::error::Error for MissingWith {}
853
854