use anyhow::Result;
use async_trait::async_trait;
use bytes::Bytes;
use futures::Stream;
use std::{fmt::Display, pin::Pin};
use thiserror;
#[cfg(any(test, feature = "mock"))]
type ClonableError = String;
#[cfg(not(any(test, feature = "mock")))]
type ClonableError = anyhow::Error;
#[cfg_attr(any(test, feature = "mock"), derive(Clone))]
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Blob with hash {0} not found")]
BlobNotFound(String),
#[error("Chunk with id {0} not found in blob {1}: {2}")]
ChunkNotFound(String, String, ClonableError),
#[error("Storage error: {0}")]
StorageError(ClonableError),
#[error("Invalid hash {0}. Error: {1}")]
InvalidHash(String, String),
#[error("Error occurred: {0}")]
Other(ClonableError),
}
pub fn wrap_error(err: anyhow::Error) -> ClonableError {
#[cfg(any(test, feature = "mock"))]
return err.to_string();
#[cfg(not(any(test, feature = "mock")))]
return err;
}
pub trait ChunkId:
Clone + Default + PartialEq + Eq + std::hash::Hash + Display + Send + Sync
{
}
pub type ByteStream = Pin<Box<dyn Stream<Item = Result<Bytes, Error>> + Send>>;
pub type ChunkStream<T> = Pin<Box<dyn Stream<Item = (T, Result<Bytes, Error>)> + Send>>;
pub trait ChunkIdMapper<T: ChunkId>: Clone + Send {
fn index_to_id(&self, index: u64) -> Result<T, Error>;
fn id_to_index(&self, chunk_id: &T) -> Result<u64, Error>;
}
#[derive(Debug, PartialEq, Clone)]
pub struct UploadResult {
pub hash: String,
pub size: u64,
pub info: std::collections::HashMap<String, String>,
}
#[async_trait]
pub trait Storage: Send + Sync + Clone {
type ChunkId: ChunkId;
type ChunkIdMapper: ChunkIdMapper<Self::ChunkId>;
async fn upload_bytes(&self, bytes: impl Into<Bytes> + Send) -> Result<UploadResult, Error>;
async fn download_bytes(&self, hash: &str) -> Result<ByteStream, Error>;
async fn iter_chunks(&self, hash: &str) -> Result<ChunkStream<Self::ChunkId>, Error>;
async fn download_chunk(&self, hash: &str, chunk_id: Self::ChunkId) -> Result<Bytes, Error>;
async fn chunk_id_mapper(&self, hash: &str) -> Result<Self::ChunkIdMapper, Error>;
}