s3_wire/operation/multipart/
part.rs1use std::{fmt, num::NonZeroU16};
2
3use super::{MultipartError, UploadId};
4use crate::operation::{Checksum, ObjectKey, RequestIds};
5use crate::stream::ByteStream;
6
7#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
9pub struct PartNumber(NonZeroU16);
10
11impl PartNumber {
12 pub const MAX: u16 = 10_000;
14
15 pub fn new(value: u16) -> Option<Self> {
17 NonZeroU16::new(value)
18 .filter(|value| value.get() <= Self::MAX)
19 .map(Self)
20 }
21
22 pub const fn get(self) -> u16 {
24 self.0.get()
25 }
26}
27
28pub struct UploadPartRequest {
30 key: ObjectKey,
31 upload_id: UploadId,
32 part_number: PartNumber,
33 body: ByteStream,
34 checksum: Checksum,
35}
36
37impl UploadPartRequest {
38 pub fn new(
40 key: ObjectKey,
41 upload_id: UploadId,
42 part_number: PartNumber,
43 body: ByteStream,
44 ) -> Self {
45 Self {
46 key,
47 upload_id,
48 part_number,
49 body,
50 checksum: Checksum::default(),
51 }
52 }
53
54 pub const fn key(&self) -> &ObjectKey {
56 &self.key
57 }
58
59 pub const fn upload_id(&self) -> &UploadId {
61 &self.upload_id
62 }
63
64 pub const fn part_number(&self) -> PartNumber {
66 self.part_number
67 }
68
69 pub const fn body(&self) -> &ByteStream {
71 &self.body
72 }
73
74 pub fn body_mut(&mut self) -> &mut ByteStream {
76 &mut self.body
77 }
78
79 pub const fn checksum(&self) -> &Checksum {
81 &self.checksum
82 }
83
84 pub fn with_checksum(mut self, checksum: Checksum) -> Self {
86 self.checksum = checksum;
87 self
88 }
89
90 pub fn into_body(self) -> ByteStream {
92 self.body
93 }
94}
95
96impl fmt::Debug for UploadPartRequest {
97 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
98 formatter
99 .debug_struct("UploadPartRequest")
100 .field("key", &self.key)
101 .field("upload_id", &self.upload_id)
102 .field("part_number", &self.part_number)
103 .field("body", &"<stream>")
104 .field("checksum", &self.checksum)
105 .finish()
106 }
107}
108
109#[derive(Clone, Debug, Eq, PartialEq)]
111pub struct UploadPartOutput {
112 pub part_number: PartNumber,
114 pub e_tag: String,
116 pub checksum: Checksum,
118 pub request_ids: RequestIds,
120}
121
122#[derive(Clone, Debug, Eq, PartialEq)]
124pub struct CompletedPart {
125 part_number: PartNumber,
126 e_tag: String,
127 checksum: Checksum,
128}
129
130impl CompletedPart {
131 pub fn new(part_number: u16, e_tag: impl Into<String>) -> Result<Self, MultipartError> {
133 let part_number =
134 PartNumber::new(part_number).ok_or(MultipartError::InvalidPartNumber(part_number))?;
135 let e_tag = e_tag.into();
136 if e_tag.trim().is_empty() {
137 return Err(MultipartError::EmptyETag {
138 part_number: part_number.get(),
139 });
140 }
141 Ok(Self {
142 part_number,
143 e_tag,
144 checksum: Checksum::default(),
145 })
146 }
147
148 pub const fn part_number(&self) -> PartNumber {
150 self.part_number
151 }
152
153 pub fn e_tag(&self) -> &str {
155 &self.e_tag
156 }
157
158 pub const fn checksum(&self) -> &Checksum {
160 &self.checksum
161 }
162
163 pub fn with_checksum(mut self, checksum: Checksum) -> Self {
165 self.checksum = checksum;
166 self
167 }
168}