use std::path::PathBuf;
use std::str::FromStr;
use prost::Message;
pub struct Config {
files: Vec<String>,
includes: Vec<String>,
out_dir: Option<PathBuf>,
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
impl Config {
#[must_use]
pub fn new() -> Self {
Self {
files: Vec::new(),
includes: Vec::new(),
out_dir: None,
}
}
#[must_use]
pub fn files(mut self, files: &[&str]) -> Self {
self.files = files.iter().map(|s| s.to_string()).collect();
self
}
#[must_use]
pub fn includes(mut self, dirs: &[&str]) -> Self {
self.includes = dirs.iter().map(|s| s.to_string()).collect();
self
}
#[must_use]
pub fn out_dir(mut self, dir: &str) -> Self {
self.out_dir = Some(PathBuf::from_str(dir).expect("valid path"));
self
}
pub fn compile(self) -> Result<(), Box<dyn std::error::Error>> {
let out_dir = self
.out_dir
.unwrap_or_else(|| PathBuf::from(std::env::var("OUT_DIR").unwrap_or_else(|_| ".".to_string())));
let mut config = prost_build::Config::new();
config.out_dir(out_dir.clone());
let descriptor_path = out_dir.join("file_descriptor_set.bin");
config.file_descriptor_set_path(descriptor_path.clone());
config.compile_protos(&self.files, &self.includes)?;
let buf = std::fs::read(&descriptor_path)?;
let descriptor_set = prost_types::FileDescriptorSet::decode(buf.as_slice())?;
let connectrpc_code =
super::generate_services(&descriptor_set.file);
let out_file = out_dir.join("_connectrpc.rs");
std::fs::write(&out_file, connectrpc_code)?;
let _ = std::fs::remove_file(&descriptor_path);
Ok(())
}
}