use async_trait::async_trait;
use chrono::Utc;
use tokio::io::AsyncRead;
use crate::error::Result;
use crate::list_filter::ListFilter;
use crate::types::{BlobInput, BlobMeta, PutResult};
use crate::visitor::BlobVisitor;
#[async_trait]
pub trait BlobStore: Send + Sync {
async fn put(&self, blobs: Vec<BlobInput>) -> Result<PutResult>;
async fn get(&self, key: &str) -> Result<Box<dyn AsyncRead + Send + Unpin>>;
async fn delete(&self, keys: &[&str]) -> Result<()>;
async fn list(&self, filter: &dyn ListFilter) -> Result<Vec<String>>;
async fn exists(&self, key: &str) -> Result<bool>;
async fn get_with_metadata(
&self,
key: &str,
) -> Result<(BlobMeta, Box<dyn AsyncRead + Send + Unpin>)> {
let reader = self.get(key).await?;
let meta = BlobMeta {
key: key.to_string(),
stored_size: 0,
modified_at: Utc::now(),
etag: None,
};
Ok((meta, reader))
}
async fn visit(&self, filter: &dyn ListFilter, visitor: &mut dyn BlobVisitor) -> Result<()> {
let keys = self.list(filter).await?;
for key in &keys {
if !visitor.visit(key, None).await? {
break;
}
}
Ok(())
}
async fn list_with_metadata(&self, filter: &dyn ListFilter) -> Result<Vec<BlobMeta>> {
let keys = self.list(filter).await?;
let now = Utc::now();
Ok(keys
.into_iter()
.map(|key| BlobMeta {
key,
stored_size: 0,
modified_at: now,
etag: None,
})
.collect())
}
}