use std::collections::BTreeMap;
use std::fmt;
use std::path::{Path, PathBuf};
use bytes::Bytes;
use super::{CompletedPart, MultipartError, UploadId};
use crate::operation::{ChecksumAlgorithm, ObjectKey, RequestIds};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CreateMultipartUploadRequest {
pub key: ObjectKey,
pub content_type: Option<String>,
pub user_metadata: BTreeMap<String, String>,
pub checksum_algorithm: Option<ChecksumAlgorithm>,
}
impl CreateMultipartUploadRequest {
pub fn new(key: ObjectKey) -> Self {
Self {
key,
content_type: None,
user_metadata: BTreeMap::new(),
checksum_algorithm: None,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CreateMultipartUploadOutput {
pub bucket: Option<String>,
pub key: ObjectKey,
upload_id: UploadId,
pub checksum_algorithm: Option<String>,
pub request_ids: RequestIds,
}
impl CreateMultipartUploadOutput {
pub(crate) fn new(
bucket: Option<String>,
key: ObjectKey,
upload_id: UploadId,
checksum_algorithm: Option<String>,
) -> Self {
Self {
bucket,
key,
upload_id,
checksum_algorithm,
request_ids: RequestIds::default(),
}
}
pub const fn upload_id(&self) -> &UploadId {
&self.upload_id
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MultipartUpload {
key: ObjectKey,
upload_id: UploadId,
completed_parts: Vec<CompletedPart>,
}
pub(crate) enum MultipartUploadSource {
Bytes(Bytes),
File(PathBuf),
}
pub struct ManagedMultipartUploadRequest {
pub(crate) key: ObjectKey,
pub(crate) source: MultipartUploadSource,
pub(crate) content_type: Option<String>,
pub(crate) user_metadata: BTreeMap<String, String>,
}
impl ManagedMultipartUploadRequest {
pub fn from_bytes(key: ObjectKey, bytes: impl Into<Bytes>) -> Self {
Self {
key,
source: MultipartUploadSource::Bytes(bytes.into()),
content_type: None,
user_metadata: BTreeMap::new(),
}
}
pub fn from_path(key: ObjectKey, path: impl AsRef<Path>) -> Self {
Self {
key,
source: MultipartUploadSource::File(path.as_ref().to_owned()),
content_type: None,
user_metadata: BTreeMap::new(),
}
}
pub fn with_content_type(mut self, content_type: impl Into<String>) -> Self {
self.content_type = Some(content_type.into());
self
}
pub fn with_metadata(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.user_metadata.insert(name.into(), value.into());
self
}
pub const fn key(&self) -> &ObjectKey {
&self.key
}
}
impl fmt::Debug for ManagedMultipartUploadRequest {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("ManagedMultipartUploadRequest")
.field("key", &self.key)
.field(
"source",
&match self.source {
MultipartUploadSource::Bytes(_) => "bytes",
MultipartUploadSource::File(_) => "file",
},
)
.field("content_type", &self.content_type)
.field(
"user_metadata_names",
&self.user_metadata.keys().collect::<Vec<_>>(),
)
.finish()
}
}
impl MultipartUpload {
pub fn new(key: ObjectKey, upload_id: UploadId) -> Self {
Self {
key,
upload_id,
completed_parts: Vec::new(),
}
}
pub fn record_part(&mut self, part: CompletedPart) -> Result<(), MultipartError> {
match self
.completed_parts
.binary_search_by_key(&part.part_number(), CompletedPart::part_number)
{
Ok(_) => Err(MultipartError::DuplicatePart(part.part_number())),
Err(index) => {
self.completed_parts.insert(index, part);
Ok(())
}
}
}
pub fn completed_parts(&self) -> &[CompletedPart] {
&self.completed_parts
}
pub const fn key(&self) -> &ObjectKey {
&self.key
}
pub const fn upload_id(&self) -> &UploadId {
&self.upload_id
}
}