1pub mod executor;
2pub mod primitives;
3pub mod query;
4pub mod response;
5pub mod store;
6
7use crate::{
8 Error,
9 db::{
10 executor::{Context, DeleteExecutor, ExecutorError, LoadExecutor, SaveExecutor},
11 query::QueryError,
12 response::ResponseError,
13 store::{DataStoreRegistry, IndexStoreRegistry, StoreError},
14 },
15 serialize::SerializeError,
16 traits::{CanisterKind, EntityKind},
17 visitor::VisitorError,
18};
19use std::{marker::PhantomData, thread::LocalKey};
20use thiserror::Error as ThisError;
21
22#[derive(Debug, ThisError)]
27pub enum DbError {
28 #[error(transparent)]
29 ExecutorError(#[from] ExecutorError),
30
31 #[error(transparent)]
32 QueryError(#[from] QueryError),
33
34 #[error(transparent)]
35 ResponseError(#[from] ResponseError),
36
37 #[error(transparent)]
38 SerializeError(#[from] SerializeError),
39
40 #[error(transparent)]
41 StoreError(#[from] StoreError),
42
43 #[error(transparent)]
44 VisitorError(#[from] VisitorError),
45}
46
47pub struct Db<C: CanisterKind> {
59 data: &'static LocalKey<DataStoreRegistry>,
60 index: &'static LocalKey<IndexStoreRegistry>,
61 _marker: PhantomData<C>,
62}
63
64impl<C: CanisterKind> Db<C> {
65 #[must_use]
66 pub const fn new(
67 data: &'static LocalKey<DataStoreRegistry>,
68 index: &'static LocalKey<IndexStoreRegistry>,
69 ) -> Self {
70 Self {
71 data,
72 index,
73 _marker: PhantomData,
74 }
75 }
76
77 #[must_use]
78 pub const fn context<E>(&self) -> Context<'_, E>
79 where
80 E: EntityKind<Canister = C>,
81 {
82 Context::new(self)
83 }
84
85 pub fn with_data<R>(&self, f: impl FnOnce(&DataStoreRegistry) -> R) -> R {
87 self.data.with(|reg| f(reg))
88 }
89
90 pub fn with_index<R>(&self, f: impl FnOnce(&IndexStoreRegistry) -> R) -> R {
92 self.index.with(|reg| f(reg))
93 }
94}
95
96impl<C: CanisterKind> Copy for Db<C> {}
100
101impl<C: CanisterKind> Clone for Db<C> {
102 fn clone(&self) -> Self {
103 *self
104 }
105}
106
107pub struct DbSession<C: CanisterKind> {
113 db: Db<C>,
114 debug: bool,
115}
116
117impl<C: CanisterKind> DbSession<C> {
118 #[must_use]
119 pub const fn new(db: Db<C>) -> Self {
121 Self { db, debug: false }
122 }
123
124 #[must_use]
125 pub const fn debug(mut self) -> Self {
127 self.debug = true;
128 self
129 }
130
131 #[must_use]
137 pub const fn load<E>(&self) -> LoadExecutor<E>
138 where
139 E: EntityKind<Canister = C>,
140 {
141 LoadExecutor::new(self.db, self.debug)
142 }
143
144 #[must_use]
148 pub const fn save<E>(&self) -> SaveExecutor<E>
149 where
150 E: EntityKind<Canister = C>,
151 {
152 SaveExecutor::new(self.db, self.debug)
153 }
154
155 #[must_use]
157 pub const fn delete<E>(&self) -> DeleteExecutor<E>
158 where
159 E: EntityKind<Canister = C>,
160 {
161 DeleteExecutor::new(self.db, self.debug)
162 }
163
164 pub fn insert<E>(&self, entity: E) -> Result<E, Error>
170 where
171 E: EntityKind<Canister = C>,
172 {
173 self.save::<E>().insert(entity)
174 }
175
176 pub fn replace<E>(&self, entity: E) -> Result<E, Error>
178 where
179 E: EntityKind<Canister = C>,
180 {
181 self.save::<E>().replace(entity)
182 }
183
184 pub fn update<E>(&self, entity: E) -> Result<E, Error>
186 where
187 E: EntityKind<Canister = C>,
188 {
189 self.save::<E>().update(entity)
190 }
191
192 pub fn insert_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
194 where
195 E: EntityKind<Canister = C>,
196 {
197 self.save::<E>().insert_view::<E::ViewType>(view)
198 }
199
200 pub fn replace_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
202 where
203 E: EntityKind<Canister = C>,
204 {
205 self.save::<E>().replace_view::<E::ViewType>(view)
206 }
207
208 pub fn update_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
210 where
211 E: EntityKind<Canister = C>,
212 {
213 self.save::<E>().update_view::<E::ViewType>(view)
214 }
215}