use crate::{generate_service_code, parser::parse_proto_file_with_includes};
use anyhow::Result;
use std::path::{Path, PathBuf};
pub struct CodegenConfig {
pub proto_file: PathBuf,
pub out_dir: PathBuf,
pub module_name: String,
pub include_paths: Vec<PathBuf>,
}
impl CodegenConfig {
pub fn from_proto(proto_file: impl AsRef<Path>) -> Self {
let proto_file = proto_file.as_ref().to_path_buf();
let module_name = proto_file
.file_stem()
.unwrap()
.to_string_lossy()
.replace('-', "_");
Self {
proto_file,
out_dir: PathBuf::from(std::env::var("OUT_DIR").unwrap()),
module_name,
include_paths: Vec::new(),
}
}
pub fn out_dir(mut self, out_dir: impl AsRef<Path>) -> Self {
self.out_dir = out_dir.as_ref().to_path_buf();
self
}
pub fn module_name(mut self, name: impl Into<String>) -> Self {
self.module_name = name.into();
self
}
pub fn include_paths(mut self, paths: &[&str]) -> Self {
self.include_paths = paths.iter().map(PathBuf::from).collect();
self
}
pub fn generate(self) -> Result<()> {
let services = parse_proto_file_with_includes(&self.proto_file, &self.include_paths)?;
if services.is_empty() {
println!(
"cargo:warning=No services found in {}",
self.proto_file.display()
);
return Ok(());
}
let mut all_code = String::new();
for service in &services {
let code = generate_service_code(service)?;
all_code.push_str(&code);
all_code.push_str("\n\n");
println!(
"cargo:warning=Generated Synapse code for service {}",
service.service_name,
);
}
let output_file = self
.out_dir
.join(format!("{}_synapse.rs", self.module_name));
std::fs::write(&output_file, all_code)?;
println!(
"cargo:warning=Wrote {} services to {}",
services.len(),
output_file.display()
);
println!("cargo:rerun-if-changed={}", self.proto_file.display());
Ok(())
}
}
pub fn generate_synapse_code(proto_file: impl AsRef<Path>) -> Result<()> {
CodegenConfig::from_proto(proto_file).generate()
}