icydb_schema/build/
mod.rs1pub mod reserved;
2pub mod validate;
3
4use crate::{
5 Error, ThisError,
6 node::{Schema, VisitableNode},
7 prelude::*,
8 visit::ValidateVisitor,
9};
10use std::sync::{LazyLock, OnceLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
11
12#[derive(Debug, ThisError)]
17pub enum BuildError {
18 #[error("validation failed: {0}")]
19 Validation(ErrorTree),
20}
21
22static SCHEMA: LazyLock<RwLock<Schema>> = LazyLock::new(|| RwLock::new(Schema::new()));
28
29static SCHEMA_VALIDATED: OnceLock<bool> = OnceLock::new();
30
31pub fn schema_write() -> RwLockWriteGuard<'static, Schema> {
33 SCHEMA
34 .write()
35 .expect("schema RwLock poisoned while acquiring write lock")
36}
37
38pub(crate) fn schema_read() -> RwLockReadGuard<'static, Schema> {
41 SCHEMA
42 .read()
43 .expect("schema RwLock poisoned while acquiring read lock")
44}
45
46pub fn get_schema() -> Result<RwLockReadGuard<'static, Schema>, Error> {
48 let schema = schema_read();
49 validate(&schema).map_err(BuildError::Validation)?;
50
51 Ok(schema)
52}
53
54fn validate(schema: &Schema) -> Result<(), ErrorTree> {
56 if *SCHEMA_VALIDATED.get_or_init(|| false) {
57 return Ok(());
58 }
59
60 let mut visitor = ValidateVisitor::new();
62 schema.accept(&mut visitor);
63 visitor.errors.result()?;
64
65 SCHEMA_VALIDATED.set(true).ok();
66
67 Ok(())
68}