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