Skip to main content

icydb_core/db/store/
mod.rs

1mod data;
2mod key;
3mod row;
4
5pub use data::*;
6pub use key::*;
7pub use row::*;
8
9use crate::error::{ErrorClass, ErrorOrigin, InternalError};
10use std::{cell::RefCell, collections::HashMap, thread::LocalKey};
11use thiserror::Error as ThisError;
12
13///
14/// StoreRegistryError
15///
16
17#[derive(Debug, ThisError)]
18pub enum StoreRegistryError {
19    #[error("store '{0}' not found")]
20    StoreNotFound(String),
21}
22
23impl StoreRegistryError {
24    pub(crate) const fn class() -> ErrorClass {
25        ErrorClass::Internal
26    }
27}
28
29impl From<StoreRegistryError> for InternalError {
30    fn from(err: StoreRegistryError) -> Self {
31        Self::new(
32            StoreRegistryError::class(),
33            ErrorOrigin::Store,
34            err.to_string(),
35        )
36    }
37}
38
39///
40/// StoreRegistry
41///
42
43#[derive(Default)]
44pub struct StoreRegistry<T: 'static>(HashMap<&'static str, &'static LocalKey<RefCell<T>>>);
45
46impl<T: 'static> StoreRegistry<T> {
47    /// Create an empty store registry.
48    #[must_use]
49    pub fn new() -> Self {
50        Self(HashMap::new())
51    }
52
53    /// Iterate registered store names and thread-local keys.
54    pub fn iter(&self) -> impl Iterator<Item = (&'static str, &'static LocalKey<RefCell<T>>)> {
55        self.0.iter().map(|(k, v)| (*k, *v))
56    }
57
58    /// Borrow each registered store immutably.
59    pub fn for_each<R>(&self, mut f: impl FnMut(&'static str, &T) -> R) {
60        for (path, accessor) in &self.0 {
61            accessor.with(|cell| {
62                let store = cell.borrow();
63                f(path, &store);
64            });
65        }
66    }
67
68    /// Register a thread-local store accessor under a path.
69    pub fn register(&mut self, name: &'static str, accessor: &'static LocalKey<RefCell<T>>) {
70        self.0.insert(name, accessor);
71    }
72
73    /// Look up a store accessor by path.
74    pub fn try_get_store(
75        &self,
76        path: &str,
77    ) -> Result<&'static LocalKey<RefCell<T>>, InternalError> {
78        self.0
79            .get(path)
80            .copied()
81            .ok_or_else(|| StoreRegistryError::StoreNotFound(path.to_string()).into())
82    }
83
84    /// Borrow a store immutably by path.
85    pub fn with_store<R>(&self, path: &str, f: impl FnOnce(&T) -> R) -> Result<R, InternalError> {
86        let store = self.try_get_store(path)?;
87
88        Ok(store.with_borrow(|s| f(s)))
89    }
90
91    /// Borrow a store mutably by path.
92    pub fn with_store_mut<R>(
93        &self,
94        path: &str,
95        f: impl FnOnce(&mut T) -> R,
96    ) -> Result<R, InternalError> {
97        let store = self.try_get_store(path)?;
98
99        Ok(store.with_borrow_mut(|s| f(s)))
100    }
101}