diskplan_config/
cache.rs

1use std::{collections::HashMap, sync::Mutex};
2
3use anyhow::{anyhow, Context, Result};
4use camino::{Utf8Path, Utf8PathBuf};
5
6use crate::SchemaNode;
7
8/// An append-only cache of schemas ([`SchemaNode`] roots) keyed by their on-disk file path
9#[derive(Default)]
10pub struct SchemaCache<'a> {
11    mapped: Mutex<HashMap<Utf8PathBuf, usize>>,
12    texts: elsa::FrozenVec<String>,
13    schemas: elsa::FrozenVec<Box<SchemaNode<'a>>>,
14}
15
16impl<'a> SchemaCache<'a> {
17    /// Constructs an new cache
18    pub fn new() -> Self {
19        Default::default()
20    }
21
22    /// Parses the file at the given `path`, caches the parsed schema, and returns a reference to it
23    pub fn load<'s, 'r>(&'s self, path: impl AsRef<Utf8Path>) -> Result<&'r SchemaNode<'a>>
24    where
25        's: 'a,
26    {
27        let mut locked = self.mapped.lock().expect("Lock poisoned");
28
29        // Early return for cache hit
30        if let Some(index) = locked.get(path.as_ref()) {
31            return Ok(&self.schemas[*index]);
32        }
33
34        // Cache miss; load text from file and parse it
35        let text = self.texts.push_get(
36            std::fs::read_to_string(path.as_ref())
37                .with_context(|| format!("Failed to load config from: {}", path.as_ref()))?,
38        );
39        let schema = diskplan_schema::parse_schema(text)
40            // ParseError lifetime is tricky, flattern
41            .map_err(|e| anyhow!("{}", e))?;
42        locked.insert(path.as_ref().to_owned(), self.schemas.len());
43        Ok(self.schemas.push_get(Box::new(schema)))
44    }
45
46    /// Injects a path to schema mapping into the cache without loading from disk
47    ///
48    /// This is primarily used for tests
49    pub fn inject(&self, path: impl AsRef<Utf8Path>, schema: SchemaNode<'a>) {
50        let mut locked = self.mapped.lock().expect("Lock poisoned");
51        locked.insert(path.as_ref().to_owned(), self.schemas.len());
52        self.schemas.push(Box::new(schema));
53    }
54}