systemprompt_config/services/
schema_validation.rs1use std::path::Path;
5
6use schemars::JsonSchema;
7use serde::de::DeserializeOwned;
8use thiserror::Error;
9
10#[derive(Debug, Error)]
11#[non_exhaustive]
12pub enum ConfigValidationError {
13 #[error("Failed to read config file: {0}")]
14 Read(#[from] std::io::Error),
15
16 #[error("Failed to parse YAML config: {0}")]
17 Parse(#[from] serde_yaml::Error),
18
19 #[error("Schema validation failed: {0}")]
20 Schema(String),
21}
22
23pub fn validate_config<T: DeserializeOwned + JsonSchema>(
24 yaml_path: impl AsRef<Path>,
25) -> Result<T, ConfigValidationError> {
26 let content = std::fs::read_to_string(yaml_path)?;
27 let config: T = serde_yaml::from_str(&content)?;
28 Ok(config)
29}
30
31pub fn generate_schema<T: JsonSchema>() -> Result<serde_json::Value, serde_json::Error> {
32 let schema = schemars::schema_for!(T);
33 serde_json::to_value(schema)
34}
35
36pub fn validate_yaml_str<T: DeserializeOwned>(yaml: &str) -> Result<T, ConfigValidationError> {
37 let config: T = serde_yaml::from_str(yaml)?;
38 Ok(config)
39}
40
41pub type ConfigValidatorFn = fn(&str) -> Result<(), String>;
42
43pub fn build_validate_configs(configs: &[(&str, ConfigValidatorFn)]) {
44 for (path, validator) in configs {
45 emit_rerun(path);
46 if let Err(e) = validator(path) {
47 emit_failure(path, &e);
48 }
49 }
50}
51
52#[expect(
53 clippy::print_stdout,
54 reason = "build.rs requires writing cargo:rerun-if-changed directives to stdout"
55)]
56fn emit_rerun(path: &str) {
57 println!("cargo:rerun-if-changed={path}");
58}
59
60#[expect(
61 clippy::print_stderr,
62 clippy::exit,
63 reason = "build.rs failure path must write a diagnostic to stderr and abort with status 1"
64)]
65fn emit_failure(path: &str, message: &str) -> ! {
66 eprintln!("Config validation failed for {path}: {message}");
67 std::process::exit(1);
68}
69
70pub fn validate_yaml_file(
71 path: impl AsRef<Path>,
72) -> Result<serde_yaml::Value, ConfigValidationError> {
73 let content = std::fs::read_to_string(path)?;
74 let value: serde_yaml::Value = serde_yaml::from_str(&content)?;
75 Ok(value)
76}