Skip to main content

icydb_core/db/store/
mod.rs

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