1pub mod gcs;
9pub mod mongodb;
10pub mod redact;
11pub mod selfstore;
12
13use crate::{CryptoError, Entry, StorableType};
14use ::mongodb::bson::Document;
15use async_trait::async_trait;
16use serde::{Deserialize, Serialize};
17
18pub trait HasIndex {
19 type Index;
20
21 fn get_index() -> Option<Self::Index>;
22}
23
24#[derive(Serialize, Deserialize, Debug, Clone)]
25pub enum TypeStorer {
26 Indexed(IndexedTypeStorer),
27 NonIndexed(NonIndexedTypeStorer),
28}
29
30#[async_trait]
31impl Storer for TypeStorer {
32 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
33 match self {
34 TypeStorer::NonIndexed(ts) => ts.get(path).await,
35 TypeStorer::Indexed(ts) => ts.get(path).await,
36 }
37 }
38
39 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
40 match self {
41 TypeStorer::NonIndexed(ts) => ts.create(value).await,
42 TypeStorer::Indexed(ts) => ts.create(value).await,
43 }
44 }
45}
46
47#[derive(Serialize, Deserialize, Debug, Clone)]
48pub enum IndexedTypeStorer {
49 Redact(redact::RedactStorer),
50 Mongo(mongodb::MongoStorer),
51 Mock(tests::MockIndexedStorer),
52}
53
54#[derive(Serialize, Deserialize, Debug, Clone)]
55pub enum NonIndexedTypeStorer {
56 SelfStore(selfstore::SelfStorer),
57 GoogleCloud(gcs::GoogleCloudStorer),
58 Mock(tests::MockStorer),
59}
60
61impl From<IndexedTypeStorer> for TypeStorer {
62 fn from(its: IndexedTypeStorer) -> Self {
63 TypeStorer::Indexed(its)
64 }
65}
66
67impl From<NonIndexedTypeStorer> for TypeStorer {
68 fn from(nits: NonIndexedTypeStorer) -> Self {
69 TypeStorer::NonIndexed(nits)
70 }
71}
72
73#[async_trait]
74impl IndexedStorer for IndexedTypeStorer {
75 async fn get_indexed<T: StorableType>(
76 &self,
77 path: &str,
78 index: &Option<Document>,
79 ) -> Result<Entry<T>, CryptoError> {
80 match self {
81 IndexedTypeStorer::Redact(rs) => rs.get_indexed(path, index).await,
82 IndexedTypeStorer::Mongo(ms) => ms.get_indexed(path, index).await,
83 IndexedTypeStorer::Mock(ms) => ms.get_indexed(path, index).await,
84 }
85 }
86
87 async fn list<T: StorableType>(
88 &self,
89 path: &str,
90 skip: u64,
91 page_size: i64,
92 ) -> Result<Vec<Entry<T>>, CryptoError> {
93 match self {
94 IndexedTypeStorer::Redact(rs) => rs.list(path, skip, page_size).await,
95 IndexedTypeStorer::Mongo(ms) => ms.list(path, skip, page_size).await,
96 IndexedTypeStorer::Mock(ms) => ms.list(path, skip, page_size).await,
97 }
98 }
99
100 async fn list_indexed<T: StorableType>(
101 &self,
102 path: &str,
103 skip: u64,
104 page_size: i64,
105 index: &Option<Document>,
106 ) -> Result<Vec<Entry<T>>, CryptoError> {
107 match self {
108 IndexedTypeStorer::Redact(rs) => rs.list_indexed(path, skip, page_size, index).await,
109 IndexedTypeStorer::Mongo(ms) => ms.list_indexed(path, skip, page_size, index).await,
110 IndexedTypeStorer::Mock(ms) => ms.list_indexed(path, skip, page_size, index).await,
111 }
112 }
113}
114
115#[async_trait]
116impl Storer for IndexedTypeStorer {
117 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
118 match self {
119 IndexedTypeStorer::Redact(rs) => rs.get(path).await,
120 IndexedTypeStorer::Mongo(ms) => ms.get(path).await,
121 IndexedTypeStorer::Mock(ms) => ms.get(path).await,
122 }
123 }
124
125 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
126 match self {
127 IndexedTypeStorer::Redact(rs) => rs.create(value).await,
128 IndexedTypeStorer::Mongo(ms) => ms.create(value).await,
129 IndexedTypeStorer::Mock(ms) => ms.create(value).await,
130 }
131 }
132}
133
134#[async_trait]
135impl Storer for NonIndexedTypeStorer {
136 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
137 match self {
138 NonIndexedTypeStorer::GoogleCloud(gcs) => gcs.get(path).await,
139 NonIndexedTypeStorer::Mock(ms) => ms.get(path).await,
140 NonIndexedTypeStorer::SelfStore(ss) => ss.get(path).await,
141 }
142 }
143
144 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
145 match self {
146 NonIndexedTypeStorer::GoogleCloud(gcs) => gcs.create(value).await,
147 NonIndexedTypeStorer::Mock(ms) => ms.create(value).await,
148 NonIndexedTypeStorer::SelfStore(ss) => ss.create(value).await,
149 }
150 }
151}
152
153#[async_trait]
155pub trait IndexedStorer: Send + Sync + Storer {
156 async fn get_indexed<T: StorableType>(
158 &self,
159 path: &str,
160 index: &Option<Document>,
161 ) -> Result<Entry<T>, CryptoError>;
162
163 async fn list<T: StorableType>(
165 &self,
166 path: &str,
167 skip: u64,
168 page_size: i64,
169 ) -> Result<Vec<Entry<T>>, CryptoError> {
170 self.list_indexed::<T>(path, skip, page_size, &T::get_index())
171 .await
172 }
173
174 async fn list_indexed<T: StorableType>(
176 &self,
177 path: &str,
178 skip: u64,
179 page_size: i64,
180 index: &Option<Document>,
181 ) -> Result<Vec<Entry<T>>, CryptoError>;
182}
183
184#[async_trait]
186pub trait Storer: Send + Sync + Into<TypeStorer> + Clone {
187 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
189
190 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
192}
193
194pub mod tests {
195 use super::IndexedStorer as IndexedStorerTrait;
196 use super::Storer as StorerTrait;
197 use crate::storage::NonIndexedTypeStorer;
198 use crate::{CryptoError, Entry, IndexedTypeStorer, StorableType, TypeStorer};
199 use async_trait::async_trait;
200 use mockall::predicate::*;
201 use mockall::*;
202 use mongodb::bson::Document;
203 use serde::{Deserialize, Serialize};
204
205 mock! {
206 pub IndexedStorer {
207 pub fn private_deserialize() -> Self;
208 pub fn private_serialize(&self) -> MockIndexedStorer;
209 pub fn private_get_indexed<T: StorableType>(&self, path: &str, index: &Option<Document>) -> Result<Entry<T>, CryptoError>;
210 pub fn private_list_indexed<T: StorableType>(&self, path: &str, skip: u64, page_size: i64, index: &Option<Document>) -> Result<Vec<Entry<T>>, CryptoError>;
211 pub fn private_get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
212 pub fn private_list<T: StorableType>(&self, path: &str, skip: u64, page_size: i64) -> Result<Vec<Entry<T>>, CryptoError>;
213 pub fn private_create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
214 }
215 }
216
217 mock! {
218 pub Storer {
219 pub fn private_deserialize() -> Self;
220 pub fn private_serialize(&self) -> MockIndexedStorer;
221 pub fn private_get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
222 pub fn private_create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
223 }
224 }
225
226 impl core::fmt::Debug for MockIndexedStorer {
227 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228 f.debug_struct("MockStorer").finish()
229 }
230 }
231
232 impl Clone for MockIndexedStorer {
233 fn clone(&self) -> Self {
234 unimplemented!()
235 }
236 }
237
238 impl core::fmt::Debug for MockStorer {
239 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
240 f.debug_struct("MockIndexedStorer").finish()
241 }
242 }
243
244 impl Clone for MockStorer {
245 fn clone(&self) -> Self {
246 unimplemented!()
247 }
248 }
249
250 #[async_trait]
251 impl IndexedStorerTrait for MockIndexedStorer {
252 async fn get_indexed<T: StorableType>(
253 &self,
254 path: &str,
255 index: &Option<Document>,
256 ) -> Result<Entry<T>, CryptoError> {
257 self.private_get_indexed(path, index)
258 }
259 async fn list<T: StorableType>(
260 &self,
261 path: &str,
262 skip: u64,
263 page_size: i64,
264 ) -> Result<Vec<Entry<T>>, CryptoError> {
265 self.private_list(path, skip, page_size)
266 }
267 async fn list_indexed<T: StorableType>(
268 &self,
269 path: &str,
270 skip: u64,
271 page_size: i64,
272 index: &Option<Document>,
273 ) -> Result<Vec<Entry<T>>, CryptoError> {
274 self.private_list_indexed(path, skip, page_size, index)
275 }
276 }
277
278 #[async_trait]
279 impl StorerTrait for MockIndexedStorer {
280 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
281 self.private_get(path)
282 }
283 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
284 self.private_create(value)
285 }
286 }
287
288 #[async_trait]
289 impl StorerTrait for MockStorer {
290 async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
291 self.private_get(path)
292 }
293 async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
294 self.private_create(value)
295 }
296 }
297
298 impl Serialize for MockStorer {
299 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
300 where
301 S: serde::Serializer,
302 {
303 self.private_serialize().serialize(serializer)
304 }
305 }
306
307 impl<'de> Deserialize<'de> for MockStorer {
308 fn deserialize<D>(_: D) -> Result<Self, D::Error>
309 where
310 D: serde::Deserializer<'de>,
311 {
312 Ok(MockStorer::private_deserialize())
313 }
314 }
315
316 impl Serialize for MockIndexedStorer {
317 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
318 where
319 S: serde::Serializer,
320 {
321 self.private_serialize().serialize(serializer)
322 }
323 }
324
325 impl<'de> Deserialize<'de> for MockIndexedStorer {
326 fn deserialize<D>(_: D) -> Result<Self, D::Error>
327 where
328 D: serde::Deserializer<'de>,
329 {
330 Ok(MockIndexedStorer::private_deserialize())
331 }
332 }
333
334 impl From<MockIndexedStorer> for TypeStorer {
335 fn from(mis: MockIndexedStorer) -> Self {
336 TypeStorer::Indexed(IndexedTypeStorer::Mock(mis))
337 }
338 }
339
340 impl From<MockStorer> for TypeStorer {
341 fn from(mis: MockStorer) -> Self {
342 TypeStorer::NonIndexed(NonIndexedTypeStorer::Mock(mis))
343 }
344 }
345}