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 {
86 self.data.with(|reg| f(reg))
87 }
88
89 pub fn with_index<R>(&self, f: impl FnOnce(&IndexStoreRegistry) -> R) -> R {
90 self.index.with(|reg| f(reg))
91 }
92}
93
94impl<C: CanisterKind> Copy for Db<C> {}
98
99impl<C: CanisterKind> Clone for Db<C> {
100 fn clone(&self) -> Self {
101 *self
102 }
103}
104
105pub struct DbSession<C: CanisterKind> {
112 db: Db<C>,
113 debug: bool,
114}
115
116impl<C: CanisterKind> DbSession<C> {
117 #[must_use]
118 pub const fn new(db: Db<C>) -> Self {
119 Self { db, debug: false }
120 }
121
122 #[must_use]
123 pub const fn debug(mut self) -> Self {
124 self.debug = true;
125 self
126 }
127
128 #[must_use]
134 pub const fn load<E>(&self) -> LoadExecutor<E>
135 where
136 E: EntityKind<Canister = C>,
137 {
138 LoadExecutor::new(self.db, self.debug)
139 }
140
141 #[must_use]
145 pub const fn save<E>(&self) -> SaveExecutor<E>
146 where
147 E: EntityKind<Canister = C>,
148 {
149 SaveExecutor::new(self.db, self.debug)
150 }
151
152 #[must_use]
154 pub const fn delete<E>(&self) -> DeleteExecutor<E>
155 where
156 E: EntityKind<Canister = C>,
157 {
158 DeleteExecutor::new(self.db, self.debug)
159 }
160
161 pub fn insert<E>(&self, entity: E) -> Result<E, Error>
166 where
167 E: EntityKind<Canister = C>,
168 {
169 self.save::<E>().insert(entity)
170 }
171
172 pub fn replace<E>(&self, entity: E) -> Result<E, Error>
173 where
174 E: EntityKind<Canister = C>,
175 {
176 self.save::<E>().replace(entity)
177 }
178
179 pub fn update<E>(&self, entity: E) -> Result<E, Error>
180 where
181 E: EntityKind<Canister = C>,
182 {
183 self.save::<E>().update(entity)
184 }
185
186 pub fn insert_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
187 where
188 E: EntityKind<Canister = C>,
189 {
190 self.save::<E>().insert_view::<E::ViewType>(view)
191 }
192
193 pub fn replace_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
194 where
195 E: EntityKind<Canister = C>,
196 {
197 self.save::<E>().replace_view::<E::ViewType>(view)
198 }
199
200 pub fn update_view<E>(&self, view: E::ViewType) -> Result<E::ViewType, Error>
201 where
202 E: EntityKind<Canister = C>,
203 {
204 self.save::<E>().update_view::<E::ViewType>(view)
205 }
206}