icydb_core/db/store/
mod.rs1mod data;
2mod error;
3mod key;
4mod row;
5
6pub use data::*;
7pub use error::StoreError;
8pub use key::*;
9pub use row::*;
10
11use crate::error::{ErrorClass, ErrorOrigin, InternalError};
12use std::{cell::RefCell, collections::HashMap, thread::LocalKey};
13use thiserror::Error as ThisError;
14
15#[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(&self) -> ErrorClass {
27 match self {
28 Self::StoreNotFound(_) => ErrorClass::Internal,
29 }
30 }
31}
32
33impl From<StoreRegistryError> for InternalError {
34 fn from(err: StoreRegistryError) -> Self {
35 Self::new(err.class(), ErrorOrigin::Store, err.to_string())
36 }
37}
38
39#[derive(Default)]
44pub struct StoreRegistry<T: 'static>(HashMap<&'static str, &'static LocalKey<RefCell<T>>>);
45
46impl<T: 'static> StoreRegistry<T> {
47 #[must_use]
49 pub fn new() -> Self {
51 Self(HashMap::new())
52 }
53
54 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 pub fn for_each<R>(&self, mut f: impl FnMut(&'static str, &T) -> R) {
63 for (path, accessor) in &self.0 {
64 accessor.with(|cell| {
65 let store = cell.borrow();
66 f(path, &store);
67 });
68 }
69 }
70
71 pub fn register(&mut self, name: &'static str, accessor: &'static LocalKey<RefCell<T>>) {
74 self.0.insert(name, accessor);
75 }
76
77 pub fn try_get_store(
80 &self,
81 path: &str,
82 ) -> Result<&'static LocalKey<RefCell<T>>, InternalError> {
83 self.0
84 .get(path)
85 .copied()
86 .ok_or_else(|| StoreRegistryError::StoreNotFound(path.to_string()).into())
87 }
88
89 pub fn with_store<R>(&self, path: &str, f: impl FnOnce(&T) -> R) -> Result<R, InternalError> {
92 let store = self.try_get_store(path)?;
93
94 Ok(store.with_borrow(|s| f(s)))
95 }
96
97 pub fn with_store_mut<R>(
100 &self,
101 path: &str,
102 f: impl FnOnce(&mut T) -> R,
103 ) -> Result<R, InternalError> {
104 let store = self.try_get_store(path)?;
105
106 Ok(store.with_borrow_mut(|s| f(s)))
107 }
108}