//! 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, OutputFile}; 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 = 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::(); }); 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(|OutputFile { 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" ); fs::write(dir.join(filename), code.as_ref()) })?; Ok(()) }