diff --git a/rlbot_flat/Cargo.toml b/rlbot_flat/Cargo.toml index 2af30f5..0135cd5 100644 --- a/rlbot_flat/Cargo.toml +++ b/rlbot_flat/Cargo.toml @@ -8,6 +8,7 @@ license-file.workspace = true planus = { git = "https://github.com/swz-git/planus", rev = "a0b1fbf" } serde = { version = "1.0.210", features = ["derive"] } glam = { version = "0.30.0", optional = true } +ts-rs = { version = "11.1.0", optional = true } [build-dependencies] planus-translation = { git = "https://github.com/swz-git/planus", rev = "a0b1fbf" } @@ -19,3 +20,4 @@ fluent-uri = "0.3.2" [features] default = ["glam"] glam = ["dep:glam"] +dts = ["dep:ts-rs"] diff --git a/rlbot_flat/build.rs b/rlbot_flat/build.rs index e68349b..af0001f 100644 --- a/rlbot_flat/build.rs +++ b/rlbot_flat/build.rs @@ -4,5 +4,7 @@ fn main() -> eyre::Result<()> { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=codegen"); + println!("cargo:rerun-if-env-changed=CARGO_FEATURE_DTS"); + codegen::main() } diff --git a/rlbot_flat/codegen/mod.rs b/rlbot_flat/codegen/mod.rs index 94c5e80..979d81a 100644 --- a/rlbot_flat/codegen/mod.rs +++ b/rlbot_flat/codegen/mod.rs @@ -62,9 +62,12 @@ pub fn main() -> eyre::Result<()> { } } - let generated_planus = // No idea why planus renames RLBot to RlBot but this fixes it + let mut generated_planus = // No idea why planus renames RLBot to RlBot but this fixes it planus_codegen::generate_rust(&declarations)?.replace("RlBot", "RLBot"); + #[cfg(feature = "dts")] + insert_ts_rs_macros(&mut generated_planus)?; + let generated_custom = generate_custom(declarations.declarations.iter().filter(|x| { x.0.0 .last() @@ -93,6 +96,37 @@ pub fn main() -> eyre::Result<()> { Ok(()) } +fn insert_ts_rs_macros(generated_planus: &mut String) -> eyre::Result<()> { + // the TS derive macro depends on prelude to exist + *generated_planus = generated_planus.replace("#[no_implicit_prelude]", ""); + let mut offset = 0; + while let Some(start_rel) = generated_planus[offset..].find("#[derive(") { + let start_abs = offset + start_rel; + if let Some(end_rel) = generated_planus[start_abs..].find(")]") { + let end_abs = start_abs + end_rel + 2; + if let Some(pos) = generated_planus[start_abs..end_abs].find("::serde::Serialize") { + // let line_start = generated_planus[..start_abs] + // .rfind('\n') + // .map(|i| i + 1) + // .unwrap_or(0); + // let indent = generated_planus[line_start..start_abs].to_owned(); + let macro_insert = "::ts_rs::TS, "; + generated_planus.insert_str(start_abs + pos, macro_insert); + let new_end_abs = end_abs + macro_insert.len(); + // let replacement = format!("\n{indent}#[ts(export)]"); + let replacement = format!(""); + generated_planus.insert_str(new_end_abs, &replacement); + offset = new_end_abs + replacement.len(); + } else { + offset = end_abs; + } + } else { + break; + } + } + Ok(()) +} + fn docstrings_iter_mut(d: &mut Docstrings) -> impl Iterator { d.docstrings.iter_mut().map(|x| &mut x.value) }