use std::{fmt, num::NonZeroU16};
use super::{MultipartError, UploadId};
use crate::operation::{Checksum, ObjectKey, RequestIds};
use crate::stream::ByteStream;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PartNumber(NonZeroU16);
impl PartNumber {
pub const MAX: u16 = 10_000;
pub fn new(value: u16) -> Option<Self> {
NonZeroU16::new(value)
.filter(|value| value.get() <= Self::MAX)
.map(Self)
}
pub const fn get(self) -> u16 {
self.0.get()
}
}
pub struct UploadPartRequest {
key: ObjectKey,
upload_id: UploadId,
part_number: PartNumber,
body: ByteStream,
checksum: Checksum,
}
impl UploadPartRequest {
pub fn new(
key: ObjectKey,
upload_id: UploadId,
part_number: PartNumber,
body: ByteStream,
) -> Self {
Self {
key,
upload_id,
part_number,
body,
checksum: Checksum::default(),
}
}
pub const fn key(&self) -> &ObjectKey {
&self.key
}
pub const fn upload_id(&self) -> &UploadId {
&self.upload_id
}
pub const fn part_number(&self) -> PartNumber {
self.part_number
}
pub const fn body(&self) -> &ByteStream {
&self.body
}
pub fn body_mut(&mut self) -> &mut ByteStream {
&mut self.body
}
pub const fn checksum(&self) -> &Checksum {
&self.checksum
}
pub fn with_checksum(mut self, checksum: Checksum) -> Self {
self.checksum = checksum;
self
}
pub fn into_body(self) -> ByteStream {
self.body
}
}
impl fmt::Debug for UploadPartRequest {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("UploadPartRequest")
.field("key", &self.key)
.field("upload_id", &self.upload_id)
.field("part_number", &self.part_number)
.field("body", &"<stream>")
.field("checksum", &self.checksum)
.finish()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UploadPartOutput {
pub part_number: PartNumber,
pub e_tag: String,
pub checksum: Checksum,
pub request_ids: RequestIds,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CompletedPart {
part_number: PartNumber,
e_tag: String,
checksum: Checksum,
}
impl CompletedPart {
pub fn new(part_number: u16, e_tag: impl Into<String>) -> Result<Self, MultipartError> {
let part_number =
PartNumber::new(part_number).ok_or(MultipartError::InvalidPartNumber(part_number))?;
let e_tag = e_tag.into();
if e_tag.trim().is_empty() {
return Err(MultipartError::EmptyETag {
part_number: part_number.get(),
});
}
Ok(Self {
part_number,
e_tag,
checksum: Checksum::default(),
})
}
pub const fn part_number(&self) -> PartNumber {
self.part_number
}
pub fn e_tag(&self) -> &str {
&self.e_tag
}
pub const fn checksum(&self) -> &Checksum {
&self.checksum
}
pub fn with_checksum(mut self, checksum: Checksum) -> Self {
self.checksum = checksum;
self
}
}