1use anyhow::Context as _;
2use quote::{format_ident, quote};
3
4use crate::rust_source::{FileComment, render_rust, rust_ident};
5
6const GENERATED_BANNER: &str = "@generated by codegen-cli -- do not edit by hand.";
7
8pub(crate) fn generate_top_mod() -> anyhow::Result<String> {
10 let lint_level = format_ident!("allow");
11
12 render_rust(
13 quote! {
14 #![#lint_level(
15 dead_code,
16 clippy::allow_attributes_without_reason,
17 clippy::doc_markdown,
18 clippy::fn_to_numeric_cast_any,
19 clippy::must_use_candidate,
20 clippy::needless_pass_by_value,
21 reason = "generated bindings preserve manifest names and registry ABI shapes"
22 )]
23
24 pub(crate) mod items;
25 pub(crate) mod shared;
26 pub(crate) mod specs;
27 },
28 &[FileComment::inner_doc(GENERATED_BANNER)?],
29 )
30 .context("rendering top-level generated module")
31}
32
33pub(crate) fn generate_shared_mod(module_names: &[String]) -> anyhow::Result<String> {
35 let mut sorted_names = module_names.to_vec();
36
37 sorted_names.sort();
38
39 let modules = sorted_names
40 .iter()
41 .map(|name| rust_ident(name))
42 .collect::<Result<Vec<_>, _>>()
43 .context("shared module name is not a Rust identifier")?;
44 let lint_level = format_ident!("allow");
45
46 render_rust(
47 quote! {
48 #![#lint_level(dead_code)]
49
50 #(pub(crate) mod #modules;)*
51 },
52 &[FileComment::inner_doc(GENERATED_BANNER)?],
53 )
54 .context("rendering shared generated module")
55}
56
57pub(crate) fn generate_specs_mod(spec_names: &[String]) -> anyhow::Result<String> {
59 let mut sorted_names = spec_names.to_vec();
60
61 sorted_names.sort();
62
63 let modules = sorted_names
64 .iter()
65 .map(|name| rust_ident(name))
66 .collect::<Result<Vec<_>, _>>()
67 .context("spec module name is not a Rust identifier")?;
68 let descriptors = spec_names
69 .iter()
70 .map(|name| rust_ident(name))
71 .collect::<Result<Vec<_>, _>>()
72 .context("spec descriptor module name is not a Rust identifier")?;
73 let lint_level = format_ident!("allow");
74
75 render_rust(
76 quote! {
77 #![#lint_level(dead_code)]
78
79 #(pub(crate) mod #modules;)*
80
81 use wowlab_engine_ports::SpecDescriptor;
82
83 pub(crate) const SPEC_DESCRIPTORS: &[SpecDescriptor] = &[
84 #(#descriptors::SPEC_DESCRIPTOR,)*
85 ];
86
87 #[doc(hidden)]
88 #[inline(never)]
89 pub(crate) fn force_link_generated_specs() -> usize {
90 std::hint::black_box(SPEC_DESCRIPTORS.as_ptr() as usize)
91 }
92 },
93 &[FileComment::inner_doc(GENERATED_BANNER)?],
94 )
95 .context("rendering spec generated module")
96}