use crate::{Error, ThisError, node::Schema, prelude::*, validate::validate_schema};
use std::sync::{LazyLock, OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
#[derive(Debug, ThisError)]
pub enum BuildError {
#[error("validation failed: {0}")]
Validation(ErrorTree),
}
static SCHEMA: LazyLock<RwLock<Schema>> = LazyLock::new(|| RwLock::new(Schema::new()));
static SCHEMA_VALIDATED: OnceLock<bool> = OnceLock::new();
pub fn schema_write() -> RwLockWriteGuard<'static, Schema> {
SCHEMA
.write()
.expect("schema RwLock poisoned while acquiring write lock")
}
pub(crate) fn schema_read() -> RwLockReadGuard<'static, Schema> {
SCHEMA
.read()
.expect("schema RwLock poisoned while acquiring read lock")
}
pub fn get_schema() -> Result<RwLockReadGuard<'static, Schema>, Error> {
let schema = schema_read();
validate(&schema).map_err(BuildError::Validation)?;
Ok(schema)
}
fn validate(schema: &Schema) -> Result<(), ErrorTree> {
if *SCHEMA_VALIDATED.get_or_init(|| false) {
return Ok(());
}
validate_schema(schema)?;
SCHEMA_VALIDATED.set(true).ok();
Ok(())
}