use crate::objstore::Bucket;
use crate::{CreateProgressCallback, ExtractFilter, ExtractProgressCallback, Result};
use bytes::Bytes;
use dyn_clone::DynClone;
use futures::Stream;
use std::ops::Range;
use std::sync::Arc;
#[derive(Clone, Debug, Default)]
pub struct ArchiveObject {
pub obj_store_type: &'static str,
pub key: String,
pub version_id: Option<String>,
pub metadata: ArchiveObjectMetadata,
}
#[derive(Clone, Debug, Default)]
pub struct ArchiveObjectMetadata {
pub size: u64,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub tags: Vec<(String, Option<String>)>,
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[async_trait::async_trait]
pub trait ArchiveFormat {
type Creator: ArchiveCreator;
type Extractor: ArchiveExtractor;
type CreateParams: Sized;
type ExtractParams: Sized;
async fn create_archive(
&self,
params: Self::CreateParams,
progress: Arc<dyn CreateProgressCallback>,
) -> Result<Self::Creator>;
async fn extract_archive(
&self,
params: Self::ExtractParams,
progress: Arc<dyn ExtractProgressCallback>,
) -> Result<Self::Extractor>;
}
#[async_trait::async_trait]
pub trait ArchiveCreator {
fn estimate_archive_size(&self, total_objects: u64, total_bytes: u64) -> u64;
async fn add_object(
&self,
object: ArchiveObject,
data: Box<dyn Stream<Item = Result<bytes::Bytes>>>,
) -> Result<()>;
async fn flush_and_finish(self) -> Result<u64>;
}
pub trait MultiPartPartitioner: DynClone + Sync + Send + 'static {
fn partition_for_multipart_upload(
&self,
key: &str,
size: u64,
) -> Result<Option<Vec<Range<u64>>>>;
}
impl<T> MultiPartPartitioner for T
where
T: Bucket,
{
fn partition_for_multipart_upload(
&self,
key: &str,
size: u64,
) -> Result<Option<Vec<Range<u64>>>> {
<T as Bucket>::partition_for_multipart_upload(self, key, size)
}
}
dyn_clone::clone_trait_object!(MultiPartPartitioner);
#[async_trait::async_trait]
pub trait ArchiveExtractor {
fn total_bytes(&self) -> Option<u64>;
async fn read_objects(
&self,
filters: Vec<ExtractFilter>,
multi_part_partitioner: Box<dyn MultiPartPartitioner>,
) -> Result<Box<dyn Stream<Item = ArchiveEntryComponent>>>;
}
pub enum ArchiveEntryComponent {
SmallObject { object: ArchiveObject, data: Bytes },
StartMultipartObject {
object: ArchiveObject,
parts: Vec<Range<u64>>,
},
ObjectPart { part: Range<u64>, data: Bytes },
EndMultipartObject,
}