use crate::conditional::ConditionalHeaders;
use crate::error::StorageError;
use crate::kb::{KbManifest, ObjectMeta};
use crate::object_path::ObjectPath;
use crate::range::ByteRange;
use crate::slug::KbSlug;
use async_trait::async_trait;
use bytes::Bytes;
use futures::Stream;
use std::pin::Pin;
use crate::staging::StagedBody;
pub type ObjectChunkStream = Pin<Box<dyn Stream<Item = Result<Bytes, StorageError>> + Send>>;
pub struct ObjectStream {
pub chunks: ObjectChunkStream,
pub meta: ObjectMeta,
pub content_range: Option<String>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct CopyObjectOptions {
pub source_if_match: Option<String>,
pub destination_if_none_match: Option<String>,
pub content_type: Option<String>,
}
pub struct ObjectRead {
pub bytes: Bytes,
pub meta: ObjectMeta,
pub content_range: Option<String>,
}
#[derive(Debug)]
pub struct ListResponse {
pub objects: Vec<ObjectMeta>,
pub truncated: bool,
pub next_cursor: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PutOutcome {
pub etag: Option<String>,
}
#[async_trait]
pub trait Storage: Send + Sync {
async fn ensure_bucket(&self, kb: &KbSlug) -> Result<(), StorageError>;
async fn probe(&self, kb: &KbSlug) -> Result<(), StorageError>;
async fn read_manifest(&self, kb: &KbSlug) -> Result<KbManifest, StorageError>;
async fn write_manifest(&self, kb: &KbSlug, manifest: &KbManifest) -> Result<(), StorageError>;
async fn head_object(
&self,
kb: &KbSlug,
path: &ObjectPath,
conditionals: ConditionalHeaders,
) -> Result<ObjectMeta, StorageError>;
async fn get_object(
&self,
kb: &KbSlug,
path: &ObjectPath,
range: Option<ByteRange>,
conditionals: ConditionalHeaders,
) -> Result<ObjectRead, StorageError>;
async fn get_object_stream(
&self,
kb: &KbSlug,
path: &ObjectPath,
range: Option<ByteRange>,
conditionals: ConditionalHeaders,
) -> Result<ObjectStream, StorageError>;
async fn put_object(
&self,
kb: &KbSlug,
path: &ObjectPath,
bytes: Bytes,
content_type: Option<&str>,
conditionals: ConditionalHeaders,
) -> Result<PutOutcome, StorageError>;
async fn put_staged_object(
&self,
kb: &KbSlug,
path: &ObjectPath,
body: StagedBody,
content_type: Option<&str>,
conditionals: ConditionalHeaders,
) -> Result<PutOutcome, StorageError>;
async fn copy_object(
&self,
kb: &KbSlug,
source: &ObjectPath,
destination: &ObjectPath,
options: CopyObjectOptions,
) -> Result<PutOutcome, StorageError>;
async fn delete_object(
&self,
kb: &KbSlug,
path: &ObjectPath,
conditionals: ConditionalHeaders,
) -> Result<(), StorageError>;
async fn list_objects(
&self,
kb: &KbSlug,
prefix: Option<&str>,
limit: u32,
cursor: Option<&str>,
) -> Result<ListResponse, StorageError>;
}
#[cfg(test)]
mod tests {
fn assert_send_sync<T: Send + Sync + ?Sized>() {}
#[test]
fn storage_is_dyn_compatible_and_send_sync() {
assert_send_sync::<dyn crate::storage::Storage>();
}
}