Files
SpacetimeDB/crates/codegen/examples/regen-csharp-moduledef.rs
2025-04-29 17:54:25 +00:00

73 lines
2.3 KiB
Rust

//! This script is used to generate the C# bindings for the `RawModuleDef` type.
//! Run `cargo run --example regen-csharp-moduledef` to update C# bindings whenever the module definition changes.
use fs_err as fs;
use regex::Regex;
use spacetimedb_codegen::{csharp, generate};
use spacetimedb_lib::{RawModuleDef, RawModuleDefV8};
use spacetimedb_schema::def::ModuleDef;
use std::path::Path;
use std::sync::OnceLock;
macro_rules! regex_replace {
($value:expr, $re:expr, $replace:expr) => {{
static RE: OnceLock<Regex> = OnceLock::new();
RE.get_or_init(|| Regex::new($re).unwrap())
.replace_all($value, $replace)
}};
}
fn main() -> anyhow::Result<()> {
let module = RawModuleDefV8::with_builder(|module| {
module.add_type::<RawModuleDef>();
});
let dir = &Path::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../bindings-csharp/Runtime/Internal/Autogen"
))
.canonicalize()?;
fs::remove_dir_all(dir)?;
fs::create_dir(dir)?;
let module: ModuleDef = module.try_into()?;
generate(
&module,
&csharp::Csharp {
namespace: "SpacetimeDB.Internal",
},
)
.into_iter()
.try_for_each(|(filename, code)| {
// Skip anything but raw types (in particular, this will skip top-level SpacetimeDBClient.g.cs which we don't need).
let Some(filename) = filename.strip_prefix("Types/") else {
return Ok(());
};
// Someday we might replace custom BSATN types with autogenerated ones as well,
// but for now they're not very large and our copies are somewhat more optimised.
//
// Ignore those types and replace their references with our own with plain old regexes.
if filename == "AlgebraicType.g.cs" || filename.starts_with("SumType") || filename.starts_with("ProductType") {
return Ok(());
}
let code = regex_replace!(&code, r"\bAlgebraicType\b", "SpacetimeDB.BSATN.$0");
let code = regex_replace!(
&code,
r"\b(ProductTypeElement|SumTypeVariant)\b",
"SpacetimeDB.BSATN.AggregateElement"
);
let code = regex_replace!(
&code,
r"\b(Product|Sum)Type\b",
"List<SpacetimeDB.BSATN.AggregateElement>"
);
fs::write(dir.join(filename), code.as_ref())
})?;
Ok(())
}