pub mod gcs;
pub mod mongodb;
pub mod redact;
pub mod selfstore;
use crate::{CryptoError, Entry, StorableType};
use ::mongodb::bson::Document;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
pub trait HasIndex {
type Index;
fn get_index() -> Option<Self::Index>;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum TypeStorer {
Indexed(IndexedTypeStorer),
NonIndexed(NonIndexedTypeStorer),
}
#[async_trait]
impl Storer for TypeStorer {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
match self {
TypeStorer::NonIndexed(ts) => ts.get(path).await,
TypeStorer::Indexed(ts) => ts.get(path).await,
}
}
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
match self {
TypeStorer::NonIndexed(ts) => ts.create(value).await,
TypeStorer::Indexed(ts) => ts.create(value).await,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum IndexedTypeStorer {
Redact(redact::RedactStorer),
Mongo(mongodb::MongoStorer),
Mock(tests::MockIndexedStorer),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum NonIndexedTypeStorer {
SelfStore(selfstore::SelfStorer),
GoogleCloud(gcs::GoogleCloudStorer),
Mock(tests::MockStorer),
}
impl From<IndexedTypeStorer> for TypeStorer {
fn from(its: IndexedTypeStorer) -> Self {
TypeStorer::Indexed(its)
}
}
impl From<NonIndexedTypeStorer> for TypeStorer {
fn from(nits: NonIndexedTypeStorer) -> Self {
TypeStorer::NonIndexed(nits)
}
}
#[async_trait]
impl IndexedStorer for IndexedTypeStorer {
async fn get_indexed<T: StorableType>(
&self,
path: &str,
index: &Option<Document>,
) -> Result<Entry<T>, CryptoError> {
match self {
IndexedTypeStorer::Redact(rs) => rs.get_indexed(path, index).await,
IndexedTypeStorer::Mongo(ms) => ms.get_indexed(path, index).await,
IndexedTypeStorer::Mock(ms) => ms.get_indexed(path, index).await,
}
}
async fn list<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
) -> Result<Vec<Entry<T>>, CryptoError> {
match self {
IndexedTypeStorer::Redact(rs) => rs.list(path, skip, page_size).await,
IndexedTypeStorer::Mongo(ms) => ms.list(path, skip, page_size).await,
IndexedTypeStorer::Mock(ms) => ms.list(path, skip, page_size).await,
}
}
async fn list_indexed<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
index: &Option<Document>,
) -> Result<Vec<Entry<T>>, CryptoError> {
match self {
IndexedTypeStorer::Redact(rs) => rs.list_indexed(path, skip, page_size, index).await,
IndexedTypeStorer::Mongo(ms) => ms.list_indexed(path, skip, page_size, index).await,
IndexedTypeStorer::Mock(ms) => ms.list_indexed(path, skip, page_size, index).await,
}
}
}
#[async_trait]
impl Storer for IndexedTypeStorer {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
match self {
IndexedTypeStorer::Redact(rs) => rs.get(path).await,
IndexedTypeStorer::Mongo(ms) => ms.get(path).await,
IndexedTypeStorer::Mock(ms) => ms.get(path).await,
}
}
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
match self {
IndexedTypeStorer::Redact(rs) => rs.create(value).await,
IndexedTypeStorer::Mongo(ms) => ms.create(value).await,
IndexedTypeStorer::Mock(ms) => ms.create(value).await,
}
}
}
#[async_trait]
impl Storer for NonIndexedTypeStorer {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
match self {
NonIndexedTypeStorer::GoogleCloud(gcs) => gcs.get(path).await,
NonIndexedTypeStorer::Mock(ms) => ms.get(path).await,
NonIndexedTypeStorer::SelfStore(ss) => ss.get(path).await,
}
}
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
match self {
NonIndexedTypeStorer::GoogleCloud(gcs) => gcs.create(value).await,
NonIndexedTypeStorer::Mock(ms) => ms.create(value).await,
NonIndexedTypeStorer::SelfStore(ss) => ss.create(value).await,
}
}
}
#[async_trait]
pub trait IndexedStorer: Send + Sync + Storer {
async fn get_indexed<T: StorableType>(
&self,
path: &str,
index: &Option<Document>,
) -> Result<Entry<T>, CryptoError>;
async fn list<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
) -> Result<Vec<Entry<T>>, CryptoError> {
self.list_indexed::<T>(path, skip, page_size, &T::get_index())
.await
}
async fn list_indexed<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
index: &Option<Document>,
) -> Result<Vec<Entry<T>>, CryptoError>;
}
#[async_trait]
pub trait Storer: Send + Sync + Into<TypeStorer> + Clone {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
}
pub mod tests {
use super::IndexedStorer as IndexedStorerTrait;
use super::Storer as StorerTrait;
use crate::storage::NonIndexedTypeStorer;
use crate::{CryptoError, Entry, IndexedTypeStorer, StorableType, TypeStorer};
use async_trait::async_trait;
use mockall::predicate::*;
use mockall::*;
use mongodb::bson::Document;
use serde::{Deserialize, Serialize};
mock! {
pub IndexedStorer {
pub fn private_deserialize() -> Self;
pub fn private_serialize(&self) -> MockIndexedStorer;
pub fn private_get_indexed<T: StorableType>(&self, path: &str, index: &Option<Document>) -> Result<Entry<T>, CryptoError>;
pub fn private_list_indexed<T: StorableType>(&self, path: &str, skip: u64, page_size: i64, index: &Option<Document>) -> Result<Vec<Entry<T>>, CryptoError>;
pub fn private_get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
pub fn private_list<T: StorableType>(&self, path: &str, skip: u64, page_size: i64) -> Result<Vec<Entry<T>>, CryptoError>;
pub fn private_create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
}
}
mock! {
pub Storer {
pub fn private_deserialize() -> Self;
pub fn private_serialize(&self) -> MockIndexedStorer;
pub fn private_get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError>;
pub fn private_create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError>;
}
}
impl core::fmt::Debug for MockIndexedStorer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MockStorer").finish()
}
}
impl Clone for MockIndexedStorer {
fn clone(&self) -> Self {
unimplemented!()
}
}
impl core::fmt::Debug for MockStorer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MockIndexedStorer").finish()
}
}
impl Clone for MockStorer {
fn clone(&self) -> Self {
unimplemented!()
}
}
#[async_trait]
impl IndexedStorerTrait for MockIndexedStorer {
async fn get_indexed<T: StorableType>(
&self,
path: &str,
index: &Option<Document>,
) -> Result<Entry<T>, CryptoError> {
self.private_get_indexed(path, index)
}
async fn list<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
) -> Result<Vec<Entry<T>>, CryptoError> {
self.private_list(path, skip, page_size)
}
async fn list_indexed<T: StorableType>(
&self,
path: &str,
skip: u64,
page_size: i64,
index: &Option<Document>,
) -> Result<Vec<Entry<T>>, CryptoError> {
self.private_list_indexed(path, skip, page_size, index)
}
}
#[async_trait]
impl StorerTrait for MockIndexedStorer {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
self.private_get(path)
}
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
self.private_create(value)
}
}
#[async_trait]
impl StorerTrait for MockStorer {
async fn get<T: StorableType>(&self, path: &str) -> Result<Entry<T>, CryptoError> {
self.private_get(path)
}
async fn create<T: StorableType>(&self, value: Entry<T>) -> Result<Entry<T>, CryptoError> {
self.private_create(value)
}
}
impl Serialize for MockStorer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.private_serialize().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for MockStorer {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(MockStorer::private_deserialize())
}
}
impl Serialize for MockIndexedStorer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.private_serialize().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for MockIndexedStorer {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(MockIndexedStorer::private_deserialize())
}
}
impl From<MockIndexedStorer> for TypeStorer {
fn from(mis: MockIndexedStorer) -> Self {
TypeStorer::Indexed(IndexedTypeStorer::Mock(mis))
}
}
impl From<MockStorer> for TypeStorer {
fn from(mis: MockStorer) -> Self {
TypeStorer::NonIndexed(NonIndexedTypeStorer::Mock(mis))
}
}
}