1use bytes::Bytes;
17use chrono::{DateTime, Utc};
18use serde::{Deserialize, Serialize};
19use std::cell::{Ref, RefCell};
20use std::cmp::Ordering;
21use std::collections::{HashMap, LinkedList};
22use std::io::Read;
23use std::sync::mpsc::Sender;
24use std::sync::Arc;
25use ve_tos_generic::{AclHeader, CallbackHeader, CopySourceHeader, CopySourceIfConditionHeader, CopySourceSSecHeader, GenericInput, HttpBasicHeader, ListCommonQuery, MiscHeader, MultipartUploadQuery, RequestInfo, SseHeader, SsecHeader};
26
27use crate::common::{DataTransferListener, DataTransferStatus, GenericInput, ListedCommonPrefix, Meta, Owner, RateLimiter, RequestInfo, TempCopyResult};
28use crate::config::ConfigHolder;
29use crate::constant::{HEADER_CALLBACK, HEADER_COMPLETE_ALL, HEADER_CONTENT_LENGTH, HEADER_CONTENT_MD5, HEADER_COPY_SOURCE_RANGE, HEADER_COPY_SOURCE_VERSION_ID, HEADER_ETAG, HEADER_FORBID_OVERWRITE, HEADER_HASH_CRC64ECMA, HEADER_IF_NONE_MATCH, HEADER_LOCATION, HEADER_OBJECT_EXPIRES, HEADER_SERVER_SIDE_ENCRYPTION, HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID, HEADER_SSEC_ALGORITHM, HEADER_SSEC_KEY_MD5, HEADER_TAGGING, HEADER_TRAFFIC_LIMIT, HEADER_VERSION_ID, HEADER_X_IF_MATCH, QUERY_ENCODING_TYPE, QUERY_KEY_MARKER, QUERY_MAX_PARTS, QUERY_MAX_UPLOADS, QUERY_PART_NUMBER, QUERY_PART_NUMBER_MARKER, QUERY_UPLOAD_ID_MARKER};
30use crate::enumeration::HttpMethodType::{HttpMethodDelete, HttpMethodGet, HttpMethodPost, HttpMethodPut};
31use crate::enumeration::{ACLType, StorageClassType};
32use crate::error::{ErrorResponse, GenericError, TosError};
33use crate::http::{HttpRequest, HttpResponse, RequestContext};
34use crate::internal::{get_header_value, get_header_value_from_str, get_map_value_from_str, get_map_value_str, map_insert, parse_date_time_iso8601, parse_json, parse_json_by_buf, parse_response_string_by_buf, read_response, set_acl_header, set_callback_header, set_copy_source_header, set_copy_source_if_condition_header, set_copy_source_ssec_header, set_http_basic_header, set_list_common_query, set_misc_header, set_multipart_upload_query, set_sse_header, set_ssec_header, set_upload_id, trans_meta, InputDescriptor, InputTranslator, OutputParser};
35use crate::reader::{BuildBufferReader, BuildFileReader, BuildMultiBufferReader, MultiBytes};
36
37pub trait MultipartAPI {
38 fn create_multipart_upload(&self, input: &CreateMultipartUploadInput) -> Result<CreateMultipartUploadOutput, TosError>;
39 fn upload_part<B>(&self, input: &UploadPartInput<B>) -> Result<UploadPartOutput, TosError>
40 where
41 B: Read + Send + 'static;
42 fn upload_part_from_buffer(&self, input: &UploadPartFromBufferInput) -> Result<UploadPartOutput, TosError>;
43 fn upload_part_from_file(&self, input: &UploadPartFromFileInput) -> Result<UploadPartOutput, TosError>;
44 fn complete_multipart_upload(&self, input: &CompleteMultipartUploadInput) -> Result<CompleteMultipartUploadOutput, TosError>;
45 fn abort_multipart_upload(&self, input: &AbortMultipartUploadInput) -> Result<AbortMultipartUploadOutput, TosError>;
46 fn upload_part_copy(&self, input: &UploadPartCopyInput) -> Result<UploadPartCopyOutput, TosError>;
47 fn list_multipart_uploads(&self, input: &ListMultipartUploadsInput) -> Result<ListMultipartUploadsOutput, TosError>;
48 fn list_parts(&self, input: &ListPartsInput) -> Result<ListPartsOutput, TosError>;
49}
50
51#[derive(
52 Debug,
53 Clone,
54 PartialEq,
55 Default,
56 HttpBasicHeader,
57 AclHeader,
58 MiscHeader,
59 SseHeader,
60 SsecHeader,
61 GenericInput
62)]
63pub struct CreateMultipartUploadInput {
64 pub(crate) generic_input: GenericInput,
65 pub(crate) bucket: String,
66 pub(crate) key: String,
67 pub(crate) encoding_type: String,
68 pub(crate) content_length: i64,
69 pub(crate) cache_control: String,
70 pub(crate) content_disposition: String,
71 pub(crate) content_encoding: String,
72 pub(crate) content_language: String,
73 pub(crate) content_type: String,
74 pub(crate) expires: Option<DateTime<Utc>>,
75 pub(crate) acl: Option<ACLType>,
76 pub(crate) grant_full_control: String,
77 pub(crate) grant_read: String,
78 pub(crate) grant_read_acp: String,
79 pub(crate) grant_write: String,
80 pub(crate) grant_write_acp: String,
81 pub(crate) ssec_algorithm: String,
82 pub(crate) ssec_key: String,
83 pub(crate) ssec_key_md5: String,
84 pub(crate) server_side_encryption: String,
85 pub(crate) server_side_encryption_key_id: String,
86 pub(crate) meta: HashMap<String, String>,
87 pub(crate) website_redirect_location: String,
88 pub(crate) storage_class: Option<StorageClassType>,
89 pub(crate) forbid_overwrite: bool,
90 pub(crate) tagging: String,
91 pub(crate) if_match: String,
92 pub(crate) if_none_match: String,
93 pub(crate) object_expires: i64,
94}
95
96impl CreateMultipartUploadInput {
97 pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
98 let mut input = Self::default();
99 input.bucket = bucket.into();
100 input.key = key.into();
101 input.content_length = -1;
102 input.object_expires = -1;
103 input
104 }
105 pub fn bucket(&self) -> &str {
106 &self.bucket
107 }
108 pub fn key(&self) -> &str {
109 &self.key
110 }
111 pub fn encoding_type(&self) -> &str {
112 &self.encoding_type
113 }
114 pub fn meta(&self) -> &HashMap<String, String> {
115 &self.meta
116 }
117 pub fn forbid_overwrite(&self) -> bool {
118 self.forbid_overwrite
119 }
120 pub fn tagging(&self) -> &str {
121 &self.tagging
122 }
123 pub fn object_expires(&self) -> i64 {
124 self.object_expires
125 }
126 pub fn if_match(&self) -> &str {
127 &self.if_match
128 }
129
130 pub fn if_none_match(&self) -> &str {
131 &self.if_none_match
132 }
133 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
134 self.bucket = bucket.into();
135 }
136 pub fn set_key(&mut self, key: impl Into<String>) {
137 self.key = key.into();
138 }
139 pub fn set_encoding_type(&mut self, encoding_type: impl Into<String>) {
140 self.encoding_type = encoding_type.into();
141 }
142 pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
143 self.meta = meta.into();
144 }
145 pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
146 self.forbid_overwrite = forbid_overwrite;
147 }
148 pub fn set_tagging(&mut self, tagging: impl Into<String>) {
149 self.tagging = tagging.into();
150 }
151
152 pub fn set_object_expires(&mut self, object_expires: i64) {
153 self.object_expires = object_expires;
154 }
155
156 pub fn set_if_match(&mut self, if_match: impl Into<String>) {
157 self.if_match = if_match.into();
158 }
159
160 pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
161 self.if_none_match = if_none_match.into();
162 }
163}
164
165impl InputDescriptor for CreateMultipartUploadInput {
166 fn operation(&self) -> &str {
167 "CreateMultipartUpload"
168 }
169 fn bucket(&self) -> Result<&str, TosError> {
170 Ok(&self.bucket)
171 }
172
173 fn key(&self) -> Result<&str, TosError> {
174 Ok(&self.key)
175 }
176}
177
178impl<B> InputTranslator<B> for CreateMultipartUploadInput {
179 fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
180 let mut request = self.trans_key()?;
181 request.method = HttpMethodPost;
182 let header = &mut request.header;
183 set_http_basic_header(header, config_holder.disable_encoding_meta, self);
184 set_acl_header(header, self);
185 set_sse_header(header, self)?;
186 set_ssec_header(header, &self.server_side_encryption, self)?;
187 request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
188 set_misc_header(header, self);
189 map_insert(header, HEADER_TAGGING, &self.tagging);
190 if self.forbid_overwrite {
191 header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
192 }
193 map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
194 map_insert(header, HEADER_IF_NONE_MATCH, &self.if_none_match);
195 if self.object_expires >= 0 {
196 header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
197 }
198 let mut query = HashMap::with_capacity(2);
199 query.insert("uploads", "".to_string());
200 map_insert(&mut query, QUERY_ENCODING_TYPE, &self.encoding_type);
201 request.query = Some(query);
202 Ok(request)
203 }
204}
205
206#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
207pub struct CreateMultipartUploadOutput {
208 #[serde(skip)]
209 pub(crate) request_info: RequestInfo,
210 #[serde(default)]
211 #[serde(rename = "Bucket")]
212 pub(crate) bucket: String,
213 #[serde(default)]
214 #[serde(rename = "Key")]
215 pub(crate) key: String,
216 #[serde(default)]
217 #[serde(rename = "UploadId")]
218 pub(crate) upload_id: String,
219 #[serde(skip)]
220 pub(crate) ssec_algorithm: String,
221 #[serde(skip)]
222 pub(crate) ssec_key_md5: String,
223 #[serde(default)]
224 #[serde(rename = "EncodingType")]
225 pub(crate) encoding_type: String,
226 #[serde(skip)]
227 pub(crate) server_side_encryption: String,
228 #[serde(skip)]
229 pub(crate) server_side_encryption_key_id: String,
230}
231
232impl OutputParser for CreateMultipartUploadOutput {
233 fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
234 let mut result = parse_json::<Self>(response)?;
235 result.ssec_algorithm = get_header_value(response.headers(), HEADER_SSEC_ALGORITHM);
236 result.ssec_key_md5 = get_header_value(response.headers(), HEADER_SSEC_KEY_MD5);
237 result.server_side_encryption = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION);
238 result.server_side_encryption_key_id = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID);
239 result.request_info = request_info;
240 Ok(result)
241 }
242}
243
244impl CreateMultipartUploadOutput {
245 pub fn bucket(&self) -> &str {
246 &self.bucket
247 }
248 pub fn key(&self) -> &str {
249 &self.key
250 }
251 pub fn upload_id(&self) -> &str {
252 &self.upload_id
253 }
254 pub fn ssec_algorithm(&self) -> &str {
255 &self.ssec_algorithm
256 }
257 pub fn ssec_key_md5(&self) -> &str {
258 &self.ssec_key_md5
259 }
260 pub fn encoding_type(&self) -> &str {
261 &self.encoding_type
262 }
263 pub fn server_side_encryption(&self) -> &str {
264 &self.server_side_encryption
265 }
266 pub fn server_side_encryption_key_id(&self) -> &str {
267 &self.server_side_encryption_key_id
268 }
269}
270
271#[derive(Debug, Clone, SsecHeader, MultipartUploadQuery, GenericInput)]
272pub(crate) struct UploadPartBasicInput {
273 pub(crate) generic_input: GenericInput,
274 pub(crate) bucket: String,
275 pub(crate) key: String,
276 pub(crate) upload_id: String,
277 pub(crate) part_number: isize,
278 pub(crate) content_md5: String,
279 pub(crate) ssec_algorithm: String,
280 pub(crate) ssec_key: String,
281 pub(crate) ssec_key_md5: String,
282 pub(crate) traffic_limit: i64,
283 pub(crate) rate_limiter: Option<Arc<RateLimiter>>,
284 pub(crate) data_transfer_listener: Option<Sender<DataTransferStatus>>,
285 pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
286}
287
288impl Default for UploadPartBasicInput {
289 fn default() -> Self {
290 Self {
291 generic_input: Default::default(),
292 bucket: "".to_string(),
293 key: "".to_string(),
294 upload_id: "".to_string(),
295 part_number: 1,
296 content_md5: "".to_string(),
297 ssec_algorithm: "".to_string(),
298 ssec_key: "".to_string(),
299 ssec_key_md5: "".to_string(),
300 traffic_limit: 0,
301 rate_limiter: None,
302 data_transfer_listener: None,
303 async_data_transfer_listener: None,
304 }
305 }
306}
307
308impl InputDescriptor for UploadPartBasicInput {
309 fn operation(&self) -> &str {
310 "UploadPart"
311 }
312 fn bucket(&self) -> Result<&str, TosError> {
313 Ok(&self.bucket)
314 }
315
316 fn key(&self) -> Result<&str, TosError> {
317 Ok(&self.key)
318 }
319}
320
321impl<B> InputTranslator<B> for UploadPartBasicInput {
322 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
323 let mut request = self.trans_key()?;
324 request.method = HttpMethodPut;
325 if let Some(ref rl) = self.rate_limiter {
326 let mut rc = RequestContext::default();
327 rc.rate_limiter = Some(rl.clone());
328 request.request_context = Some(rc);
329 }
330
331 if let Some(ref dts) = self.data_transfer_listener {
332 if request.request_context.is_some() {
333 request.request_context.as_mut().unwrap().data_transfer_listener = Some(dts.clone());
334 } else {
335 let mut rc = RequestContext::default();
336 rc.data_transfer_listener = Some(dts.clone());
337 request.request_context = Some(rc);
338 }
339 } else if let Some(ref adts) = self.async_data_transfer_listener {
340 if request.request_context.is_some() {
341 request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
342 } else {
343 let mut rc = RequestContext::default();
344 rc.async_data_transfer_listener = Some(adts.clone());
345 request.request_context = Some(rc);
346 }
347 }
348
349 let header = &mut request.header;
350 map_insert(header, HEADER_CONTENT_MD5, &self.content_md5);
351 set_ssec_header(header, "", self)?;
352 if self.traffic_limit > 0 {
353 header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
354 }
355 let mut query = HashMap::with_capacity(2);
356 set_multipart_upload_query(&mut query, self)?;
357 request.query = Some(query);
358 Ok(request)
359 }
360}
361
362#[derive(Debug, SsecHeader, MultipartUploadQuery, GenericInput)]
363#[handle_content]
364#[use_inner]
365pub struct UploadPartInput<B>
366{
367 pub(crate) inner: UploadPartBasicInput,
368 pub(crate) content: Arc<RefCell<Option<B>>>,
369 pub(crate) content_length: i64,
370}
371
372unsafe impl<B> Sync for UploadPartInput<B> {}
373unsafe impl<B> Send for UploadPartInput<B> {}
374
375impl<B> InputDescriptor for UploadPartInput<B>
376{
377 fn operation(&self) -> &str {
378 "UploadPart"
379 }
380 fn bucket(&self) -> Result<&str, TosError> {
381 Ok(&self.inner.bucket)
382 }
383
384 fn key(&self) -> Result<&str, TosError> {
385 Ok(&self.inner.key)
386 }
387}
388
389impl<B> InputTranslator<B> for UploadPartInput<B>
390{
391 fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
392 let mut request = self.inner.trans(config_holder)?;
393 request.operation = self.operation();
394 request.body = self.content.take();
395 if self.content_length >= 0 {
396 request.header.insert(HEADER_CONTENT_LENGTH, self.content_length.to_string());
397 }
398 Ok(request)
399 }
400}
401
402impl<B> UploadPartInput<B>
403{
404 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
405 let mut input = Self::default();
406 input.inner.bucket = bucket.into();
407 input.inner.key = key.into();
408 input.inner.upload_id = upload_id.into();
409 input
410 }
411 pub fn new_with_part_number(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, part_number: isize) -> Self {
412 let mut input = Self::default();
413 input.inner.bucket = bucket.into();
414 input.inner.key = key.into();
415 input.inner.upload_id = upload_id.into();
416 input.inner.part_number = part_number;
417 input
418 }
419
420 pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>,
421 upload_id: impl Into<String>, content: impl Into<B>) -> Self {
422 let mut input = Self::default();
423 input.inner.bucket = bucket.into();
424 input.inner.key = key.into();
425 input.inner.upload_id = upload_id.into();
426 input.set_content(content);
427 input
428 }
429
430 pub fn new_with_part_number_content(bucket: impl Into<String>, key: impl Into<String>,
431 upload_id: impl Into<String>, part_number: isize, content: impl Into<B>) -> Self {
432 let mut input = Self::default();
433 input.inner.bucket = bucket.into();
434 input.inner.key = key.into();
435 input.inner.upload_id = upload_id.into();
436 input.inner.part_number = part_number;
437 input.set_content(content);
438 input
439 }
440
441 pub fn bucket(&self) -> &str {
442 &self.inner.bucket
443 }
444 pub fn key(&self) -> &str {
445 &self.inner.key
446 }
447 pub fn content(&self) -> Ref<Option<B>> {
448 self.content.borrow()
449 }
450 pub fn content_length(&self) -> i64 {
451 self.content_length
452 }
453 pub fn content_md5(&self) -> &str {
454 &self.inner.content_md5
455 }
456 pub fn traffic_limit(&self) -> i64 {
457 self.inner.traffic_limit
458 }
459 pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
460 &self.inner.rate_limiter
461 }
462 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
463 self.inner.bucket = bucket.into();
464 }
465 pub fn set_key(&mut self, key: impl Into<String>) {
466 self.inner.key = key.into();
467 }
468 pub fn set_content(&mut self, content: impl Into<B>) {
469 self.content = Arc::new(RefCell::new(Some(content.into())));
470 }
471 pub fn set_content_length(&mut self, content_length: i64) {
472 self.content_length = content_length;
473 }
474 pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
475 self.inner.content_md5 = content_md5.into();
476 }
477 pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
478 self.inner.traffic_limit = traffic_limit;
479 }
480 pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
481 self.inner.rate_limiter = Some(rate_limiter.into());
482 }
483}
484
485impl<B> Default for UploadPartInput<B>
486{
487 fn default() -> Self {
488 Self {
489 inner: Default::default(),
490 content: Arc::new(RefCell::new(None)),
491 content_length: -1,
492 }
493 }
494}
495
496impl<B> DataTransferListener for UploadPartInput<B> {
497 fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
498 &self.inner.data_transfer_listener
499 }
500
501 fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
502 self.inner.data_transfer_listener = Some(listener.into());
503 }
504}
505
506#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
507pub struct UploadPartOutput {
508 pub(crate) request_info: RequestInfo,
509 pub(crate) part_number: isize,
510 pub(crate) etag: String,
511 pub(crate) ssec_algorithm: String,
512 pub(crate) ssec_key_md5: String,
513 pub(crate) hash_crc64ecma: u64,
514 pub(crate) server_side_encryption: String,
515 pub(crate) server_side_encryption_key_id: String,
516}
517
518impl OutputParser for UploadPartOutput {
519 fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
520 let hash_crc64ecma = get_header_value_from_str::<u64>(response.headers(), HEADER_HASH_CRC64ECMA, 0)?;
521 if let Some(ref rc) = request.request_context {
522 if let Some(calc_hash_crc64ecma) = rc.crc64 {
523 if calc_hash_crc64ecma != hash_crc64ecma {
524 return Err(TosError::client_error(format!("expect crc64 {hash_crc64ecma}, actual crc64 {calc_hash_crc64ecma}")));
525 }
526 }
527 }
528 let result = Self {
529 request_info: request_info,
530 part_number: get_map_value_from_str(request.query.as_ref().unwrap(), QUERY_PART_NUMBER, 1)?,
531 etag: get_header_value(response.headers(), HEADER_ETAG),
532 ssec_algorithm: get_header_value(response.headers(), HEADER_SSEC_ALGORITHM),
533 ssec_key_md5: get_header_value(response.headers(), HEADER_SSEC_KEY_MD5),
534 hash_crc64ecma: hash_crc64ecma,
535 server_side_encryption: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION),
536 server_side_encryption_key_id: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID),
537 };
538 Ok(result)
539 }
540}
541
542impl UploadPartOutput {
543 pub fn part_number(&self) -> isize {
544 self.part_number
545 }
546 pub fn etag(&self) -> &str {
547 &self.etag
548 }
549 pub fn ssec_algorithm(&self) -> &str {
550 &self.ssec_algorithm
551 }
552 pub fn ssec_key_md5(&self) -> &str {
553 &self.ssec_key_md5
554 }
555 pub fn hash_crc64ecma(&self) -> u64 {
556 self.hash_crc64ecma
557 }
558 pub fn server_side_encryption(&self) -> &str {
559 &self.server_side_encryption
560 }
561 pub fn server_side_encryption_key_id(&self) -> &str {
562 &self.server_side_encryption_key_id
563 }
564}
565
566#[derive(Debug, SsecHeader, MultipartUploadQuery, GenericInput)]
567#[use_inner]
568pub struct UploadPartFromBufferInput {
569 pub(crate) inner: UploadPartBasicInput,
570 pub(crate) content: Option<MultiBytes>,
571 pub(crate) content_length: i64,
572}
573
574impl InputDescriptor for UploadPartFromBufferInput {
575 fn operation(&self) -> &str {
576 "UploadPartFromBuffer"
577 }
578 fn bucket(&self) -> Result<&str, TosError> {
579 Ok(&self.inner.bucket)
580 }
581
582 fn key(&self) -> Result<&str, TosError> {
583 Ok(&self.inner.key)
584 }
585}
586
587impl<B> InputTranslator<B> for UploadPartFromBufferInput
588where
589 B: BuildMultiBufferReader,
590{
591 fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
592 let mut request = self.inner.trans(config_holder)?;
593 request.operation = self.operation();
594 if self.content_length >= 0 {
595 request.header.insert(HEADER_CONTENT_LENGTH, self.content_length.to_string());
596 }
597 if let Some(content) = &self.content {
598 let (body, len) = B::new(content.clone())?;
599 request.body = Some(body);
600 if self.content_length < 0 {
601 request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
602 }
603 }
604 Ok(request)
605 }
606}
607
608impl UploadPartFromBufferInput {
609 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
610 let mut input = Self::default();
611 input.inner.bucket = bucket.into();
612 input.inner.key = key.into();
613 input.inner.upload_id = upload_id.into();
614 input
615 }
616 pub fn new_with_part_number(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, part_number: isize) -> Self {
617 let mut input = Self::default();
618 input.inner.bucket = bucket.into();
619 input.inner.key = key.into();
620 input.inner.upload_id = upload_id.into();
621 input.inner.part_number = part_number;
622 input
623 }
624
625 pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, content: impl AsRef<[u8]>) -> Self {
626 let mut input = Self::default();
627 input.inner.bucket = bucket.into();
628 input.inner.key = key.into();
629 input.inner.upload_id = upload_id.into();
630 input.set_content(content);
631 input
632 }
633
634 pub fn new_with_part_number_content(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, part_number: isize, content: impl AsRef<[u8]>) -> Self {
635 let mut input = Self::default();
636 input.inner.bucket = bucket.into();
637 input.inner.key = key.into();
638 input.inner.upload_id = upload_id.into();
639 input.inner.part_number = part_number;
640 input.set_content(content);
641 input
642 }
643
644 pub fn bucket(&self) -> &str {
645 &self.inner.bucket
646 }
647 pub fn key(&self) -> &str {
648 &self.inner.key
649 }
650 pub fn content(&self) -> Option<impl Iterator<Item=&Bytes>> {
651 match &self.content {
652 None => None,
653 Some(x) => Some(x.inner.iter()),
654 }
655 }
656 pub fn content_length(&self) -> i64 {
657 self.content_length
658 }
659 pub fn content_md5(&self) -> &str {
660 &self.inner.content_md5
661 }
662 pub fn traffic_limit(&self) -> i64 {
663 self.inner.traffic_limit
664 }
665 pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
666 &self.inner.rate_limiter
667 }
668 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
669 self.inner.bucket = bucket.into();
670 }
671 pub fn set_key(&mut self, key: impl Into<String>) {
672 self.inner.key = key.into();
673 }
674 pub fn set_content_with_bytes_list(&mut self, bytes_list: impl Iterator<Item=impl Into<Bytes>>) {
675 let mut list = LinkedList::new();
676 let mut size = 0;
677 for item in bytes_list {
678 let item = item.into();
679 size += item.len();
680 list.push_back(item);
681 }
682 self.content = Some(MultiBytes::new(list, size));
683 }
684 pub fn set_content(&mut self, content: impl AsRef<[u8]>) {
685 let item = content.as_ref().to_owned();
686 let size = item.len();
687 let mut list = LinkedList::new();
688 list.push_back(Bytes::from(item));
689 self.content = Some(MultiBytes::new(list, size));
690 }
691 pub fn append_content(&mut self, content: impl AsRef<[u8]>) {
692 if let Some(contents) = &mut self.content {
693 contents.push(Bytes::from(content.as_ref().to_owned()));
694 } else {
695 self.set_content(content);
696 }
697 }
698 pub fn set_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
699 let item = content.into();
700 let size = item.len();
701 let mut list = LinkedList::new();
702 list.push_back(Bytes::from(item));
703 self.content = Some(MultiBytes::new(list, size));
704 }
705 pub fn append_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
706 if let Some(contents) = &mut self.content {
707 contents.push(Bytes::from(content.into()));
708 } else {
709 self.set_content_nocopy(content);
710 }
711 }
712 pub fn set_content_length(&mut self, content_length: i64) {
713 self.content_length = content_length;
714 }
715 pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
716 self.inner.content_md5 = content_md5.into();
717 }
718 pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
719 self.inner.traffic_limit = traffic_limit;
720 }
721 pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
722 self.inner.rate_limiter = Some(rate_limiter.into());
723 }
724}
725
726impl Default for UploadPartFromBufferInput {
727 fn default() -> Self {
728 Self {
729 inner: Default::default(),
730 content: None,
731 content_length: -1,
732 }
733 }
734}
735
736impl DataTransferListener for UploadPartFromBufferInput {
737 fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
738 &self.inner.data_transfer_listener
739 }
740
741 fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
742 self.inner.data_transfer_listener = Some(listener.into());
743 }
744}
745
746#[derive(Debug, SsecHeader, MultipartUploadQuery, GenericInput)]
747#[use_inner]
748pub struct UploadPartFromFileInput {
749 pub(crate) inner: UploadPartBasicInput,
750 pub(crate) offset: i64,
751 pub(crate) part_size: i64,
752 pub(crate) file_path: String,
753}
754
755
756impl InputDescriptor for UploadPartFromFileInput {
757 fn operation(&self) -> &str {
758 "UploadPartFromFile"
759 }
760 fn bucket(&self) -> Result<&str, TosError> {
761 Ok(&self.inner.bucket)
762 }
763
764 fn key(&self) -> Result<&str, TosError> {
765 Ok(&self.inner.key)
766 }
767}
768
769impl<B> InputTranslator<B> for UploadPartFromFileInput
770where
771 B: BuildFileReader,
772{
773 fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
774 let mut request = self.inner.trans(config_holder)?;
775 request.operation = self.operation();
776 if self.offset < 0 {
777 return Err(TosError::client_error("invalid offset for upload part"));
778 }
779 if self.part_size >= 0 {
780 request.header.insert(HEADER_CONTENT_LENGTH, self.part_size.to_string());
781 }
782 if self.file_path != "" {
783 let (body, len) = B::new_with_offset(&self.file_path, self.offset)?;
784 request.body = Some(body);
785 if let Some(l) = len {
786 if self.part_size < 0 {
787 request.header.insert(HEADER_CONTENT_LENGTH, (l - self.offset as usize).to_string());
788 }
789 }
790 }
791 Ok(request)
792 }
793}
794
795impl UploadPartFromFileInput {
796 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
797 let mut input = Self::default();
798 input.inner.bucket = bucket.into();
799 input.inner.key = key.into();
800 input.inner.upload_id = upload_id.into();
801 input
802 }
803 pub fn new_with_part_number(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, part_number: isize) -> Self {
804 let mut input = Self::default();
805 input.inner.bucket = bucket.into();
806 input.inner.key = key.into();
807 input.inner.upload_id = upload_id.into();
808 input.inner.part_number = part_number;
809 input
810 }
811
812 pub fn new_with_file_path(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, file_path: impl Into<String>) -> Self {
813 let mut input = Self::default();
814 input.inner.bucket = bucket.into();
815 input.inner.key = key.into();
816 input.inner.upload_id = upload_id.into();
817 input.file_path = file_path.into();
818 input
819 }
820
821 pub fn new_with_part_number_file_path(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, part_number: isize, file_path: impl Into<String>) -> Self {
822 let mut input = Self::default();
823 input.inner.bucket = bucket.into();
824 input.inner.key = key.into();
825 input.inner.upload_id = upload_id.into();
826 input.inner.part_number = part_number;
827 input.file_path = file_path.into();
828 input
829 }
830
831 pub fn bucket(&self) -> &str {
832 &self.inner.bucket
833 }
834 pub fn key(&self) -> &str {
835 &self.inner.key
836 }
837 pub fn file_path(&self) -> &str {
838 &self.file_path
839 }
840 pub fn offset(&self) -> i64 {
841 self.offset
842 }
843 pub fn part_size(&self) -> i64 {
844 self.part_size
845 }
846 pub fn content_md5(&self) -> &str {
847 &self.inner.content_md5
848 }
849 pub fn traffic_limit(&self) -> i64 {
850 self.inner.traffic_limit
851 }
852 pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
853 &self.inner.rate_limiter
854 }
855 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
856 self.inner.bucket = bucket.into();
857 }
858 pub fn set_key(&mut self, key: impl Into<String>) {
859 self.inner.key = key.into();
860 }
861 pub fn set_file_path(&mut self, file_path: impl Into<String>) {
862 self.file_path = file_path.into();
863 }
864 pub fn set_offset(&mut self, offset: i64) {
865 self.offset = offset;
866 }
867 pub fn set_part_size(&mut self, part_size: i64) {
868 self.part_size = part_size;
869 }
870 pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
871 self.inner.content_md5 = content_md5.into();
872 }
873 pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
874 self.inner.traffic_limit = traffic_limit;
875 }
876 pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
877 self.inner.rate_limiter = Some(rate_limiter.into());
878 }
879}
880
881impl Default for UploadPartFromFileInput {
882 fn default() -> Self {
883 Self {
884 inner: Default::default(),
885 offset: 0,
886 part_size: -1,
887 file_path: "".to_string(),
888 }
889 }
890}
891
892impl DataTransferListener for UploadPartFromFileInput {
893 fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
894 &self.inner.data_transfer_listener
895 }
896
897 fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
898 self.inner.data_transfer_listener = Some(listener.into());
899 }
900}
901
902
903#[derive(Debug, Clone, PartialEq, Default, CallbackHeader, GenericInput)]
904pub struct CompleteMultipartUploadInput {
905 pub(crate) generic_input: GenericInput,
906 pub(crate) bucket: String,
907 pub(crate) key: String,
908 pub(crate) upload_id: String,
909 pub(crate) parts: Vec<UploadedPart>,
910 pub(crate) complete_all: bool,
911 pub(crate) callback: String,
912 pub(crate) callback_var: String,
913 pub(crate) forbid_overwrite: bool,
914 pub(crate) if_match: String,
915 pub(crate) if_none_match: String,
916}
917
918impl InputDescriptor for CompleteMultipartUploadInput {
919 fn operation(&self) -> &str {
920 "CompleteMultipartUpload"
921 }
922 fn bucket(&self) -> Result<&str, TosError> {
923 Ok(&self.bucket)
924 }
925
926 fn key(&self) -> Result<&str, TosError> {
927 Ok(&self.key)
928 }
929}
930
931impl<B> InputTranslator<B> for CompleteMultipartUploadInput
932where
933 B: BuildBufferReader,
934{
935 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
936 let mut request = self.trans_key()?;
937 request.method = HttpMethodPost;
938 let header = &mut request.header;
939 if self.complete_all {
940 header.insert(HEADER_COMPLETE_ALL, "yes".to_string());
941 } else if self.parts.len() == 0 {
942 return Err(TosError::client_error("empty parts for complete multipart upload"));
943 } else {
944 let mut parts = Vec::with_capacity(self.parts.len());
945 for part in self.parts.iter() {
946 parts.push(part);
947 }
948 parts.sort();
949 match serde_json::to_string(&TempUploadedParts { parts }) {
950 Err(e) => return Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
951 Ok(json) => {
952 let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
953 request.body = Some(body);
954 header.insert(HEADER_CONTENT_LENGTH, len.to_string());
955 }
956 }
957 }
958 set_callback_header(header, self);
959 map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
960 map_insert(header, HEADER_IF_NONE_MATCH, &self.if_none_match);
961 if self.forbid_overwrite {
962 header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
963 }
964 let mut query = HashMap::with_capacity(2);
965 set_upload_id(&mut query, &self.upload_id)?;
966 request.query = Some(query);
967 Ok(request)
968 }
969}
970
971impl CompleteMultipartUploadInput {
972 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
973 let mut input = Self::default();
974 input.bucket = bucket.into();
975 input.key = key.into();
976 input.upload_id = upload_id.into();
977 input
978 }
979
980 pub fn new_with_parts(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, parts: impl Into<Vec<UploadedPart>>) -> Self {
981 let mut input = Self::default();
982 input.bucket = bucket.into();
983 input.key = key.into();
984 input.upload_id = upload_id.into();
985 input.parts = parts.into();
986 input
987 }
988
989 pub fn new_with_complete_all(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>, complete_all: bool) -> Self {
990 let mut input = Self::default();
991 input.bucket = bucket.into();
992 input.key = key.into();
993 input.upload_id = upload_id.into();
994 input.complete_all = complete_all;
995 input
996 }
997
998 pub fn add_part(&mut self, part: impl Into<UploadedPart>) {
999 self.parts.push(part.into());
1000 }
1001 pub fn bucket(&self) -> &str {
1002 &self.bucket
1003 }
1004 pub fn key(&self) -> &str {
1005 &self.key
1006 }
1007 pub fn upload_id(&self) -> &str {
1008 &self.upload_id
1009 }
1010 pub fn parts(&self) -> &Vec<UploadedPart> {
1011 &self.parts
1012 }
1013 pub fn complete_all(&self) -> bool {
1014 self.complete_all
1015 }
1016 pub fn forbid_overwrite(&self) -> bool {
1017 self.forbid_overwrite
1018 }
1019 pub fn if_match(&self) -> &str {
1020 &self.if_match
1021 }
1022
1023 pub fn if_none_match(&self) -> &str {
1024 &self.if_none_match
1025 }
1026 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1027 self.bucket = bucket.into();
1028 }
1029 pub fn set_key(&mut self, key: impl Into<String>) {
1030 self.key = key.into();
1031 }
1032 pub fn set_upload_id(&mut self, upload_id: impl Into<String>) {
1033 self.upload_id = upload_id.into();
1034 }
1035 pub fn set_parts(&mut self, parts: impl Into<Vec<UploadedPart>>) {
1036 self.parts = parts.into();
1037 }
1038 pub fn set_complete_all(&mut self, complete_all: bool) {
1039 self.complete_all = complete_all;
1040 }
1041 pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
1042 self.forbid_overwrite = forbid_overwrite;
1043 }
1044 pub fn set_if_match(&mut self, if_match: impl Into<String>) {
1045 self.if_match = if_match.into();
1046 }
1047 pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
1048 self.if_none_match = if_none_match.into();
1049 }
1050}
1051
1052#[derive(Debug, Clone, PartialEq, Default, Serialize)]
1053pub(crate) struct TempUploadedParts<'a> {
1054 #[serde(default)]
1055 #[serde(rename = "Parts")]
1056 pub(crate) parts: Vec<&'a UploadedPart>,
1057}
1058
1059#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
1060pub struct UploadedPart {
1061 #[serde(default)]
1062 #[serde(rename = "PartNumber")]
1063 pub(crate) part_number: isize,
1064 #[serde(default)]
1065 #[serde(rename = "ETag")]
1066 pub(crate) etag: String,
1067 #[serde(default)]
1068 #[serde(rename = "Size")]
1069 #[serde(skip_serializing)]
1070 pub(crate) size: i64,
1071 #[serde(default)]
1072 #[serde(rename = "LastModified")]
1073 #[serde(skip_serializing)]
1074 pub(crate) last_modified_string: Option<String>,
1075 #[serde(skip)]
1076 pub(crate) last_modified: Option<DateTime<Utc>>,
1077}
1078
1079impl Eq for UploadedPart {}
1080
1081impl PartialOrd<Self> for UploadedPart {
1082 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1083 Some(self.part_number.cmp(&other.part_number))
1084 }
1085}
1086
1087impl Ord for UploadedPart {
1088 fn cmp(&self, other: &Self) -> Ordering {
1089 self.part_number.cmp(&other.part_number)
1090 }
1091}
1092
1093impl UploadedPart {
1094 pub fn new(part_number: isize, etag: impl Into<String>) -> Self {
1095 Self {
1096 part_number: part_number,
1097 etag: etag.into(),
1098 size: 0,
1099 last_modified_string: None,
1100 last_modified: None,
1101 }
1102 }
1103 pub fn part_number(&self) -> isize {
1104 self.part_number
1105 }
1106 pub fn etag(&self) -> &str {
1107 &self.etag
1108 }
1109 pub fn size(&self) -> i64 {
1110 self.size
1111 }
1112 pub fn last_modified(&self) -> Option<DateTime<Utc>> {
1113 self.last_modified
1114 }
1115 pub fn set_part_number(&mut self, part_number: isize) {
1116 self.part_number = part_number;
1117 }
1118 pub fn set_etag(&mut self, etag: impl Into<String>) {
1119 self.etag = etag.into();
1120 }
1121}
1122
1123#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
1124pub struct CompleteMultipartUploadOutput {
1125 #[serde(skip)]
1126 pub(crate) request_info: RequestInfo,
1127 #[serde(default)]
1128 #[serde(rename = "Bucket")]
1129 pub(crate) bucket: String,
1130 #[serde(default)]
1131 #[serde(rename = "Key")]
1132 pub(crate) key: String,
1133 #[serde(default)]
1134 #[serde(rename = "ETag")]
1135 pub(crate) etag: String,
1136 #[serde(default)]
1137 #[serde(rename = "Location")]
1138 pub(crate) location: String,
1139 #[serde(skip)]
1140 pub(crate) version_id: String,
1141 #[serde(skip)]
1142 pub(crate) hash_crc64ecma: u64,
1143 #[serde(default)]
1144 #[serde(rename = "CompletedParts")]
1145 pub(crate) completed_parts: Option<Vec<UploadedPart>>,
1146 #[serde(skip)]
1147 pub(crate) callback_result: String,
1148 #[serde(skip)]
1149 pub(crate) server_side_encryption: String,
1150 #[serde(skip)]
1151 pub(crate) server_side_encryption_key_id: String,
1152}
1153
1154impl OutputParser for CompleteMultipartUploadOutput {
1155 fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1156 let mut result;
1157 if get_map_value_str(&request.header, HEADER_CALLBACK) != "" { let buf = read_response(response)?;
1159 if request_info.status_code == 203 {
1160 if let Ok(error_response) = parse_json_by_buf::<ErrorResponse>(buf.as_slice()) {
1161 return Err(TosError::server_error_with_code(error_response.code, error_response.ec, error_response.key, error_response.message,
1162 error_response.host_id, error_response.resource, request_info));
1163 }
1164 }
1165 result = Self::default();
1166 result.bucket = request.bucket.to_string();
1167 result.key = request.key.to_string();
1168 result.etag = get_header_value(response.headers(), HEADER_ETAG);
1169 result.location = get_header_value(response.headers(), HEADER_LOCATION);
1170 result.callback_result = parse_response_string_by_buf(buf)?;
1171 } else {
1172 result = parse_json::<Self>(response)?;
1173 }
1174
1175 result.version_id = get_header_value(response.headers(), HEADER_VERSION_ID);
1176 result.hash_crc64ecma = get_header_value_from_str::<u64>(response.headers(), HEADER_HASH_CRC64ECMA, 0)?;
1177 result.server_side_encryption = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION);
1178 result.server_side_encryption_key_id = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID);
1179 result.request_info = request_info;
1180 Ok(result)
1181 }
1182}
1183
1184impl CompleteMultipartUploadOutput {
1185 pub fn bucket(&self) -> &str {
1186 &self.bucket
1187 }
1188 pub fn key(&self) -> &str {
1189 &self.key
1190 }
1191 pub fn etag(&self) -> &str {
1192 &self.etag
1193 }
1194 pub fn location(&self) -> &str {
1195 &self.location
1196 }
1197 pub fn version_id(&self) -> &str {
1198 &self.version_id
1199 }
1200 pub fn hash_crc64ecma(&self) -> u64 {
1201 self.hash_crc64ecma
1202 }
1203 pub fn completed_parts(&self) -> &Option<Vec<UploadedPart>> {
1204 &self.completed_parts
1205 }
1206 pub fn callback_result(&self) -> &str {
1207 &self.callback_result
1208 }
1209 pub fn server_side_encryption(&self) -> &str {
1210 &self.server_side_encryption
1211 }
1212 pub fn server_side_encryption_key_id(&self) -> &str {
1213 &self.server_side_encryption_key_id
1214 }
1215}
1216
1217#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
1218pub struct AbortMultipartUploadInput {
1219 pub(crate) generic_input: GenericInput,
1220 pub(crate) bucket: String,
1221 pub(crate) key: String,
1222 pub(crate) upload_id: String,
1223}
1224
1225impl AbortMultipartUploadInput {
1226 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
1227 Self { generic_input: Default::default(), bucket: bucket.into(), key: key.into(), upload_id: upload_id.into() }
1228 }
1229 pub fn bucket(&self) -> &str {
1230 &self.bucket
1231 }
1232 pub fn key(&self) -> &str {
1233 &self.key
1234 }
1235 pub fn upload_id(&self) -> &str {
1236 &self.upload_id
1237 }
1238 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1239 self.bucket = bucket.into();
1240 }
1241 pub fn set_key(&mut self, key: impl Into<String>) {
1242 self.key = key.into();
1243 }
1244 pub fn set_upload_id(&mut self, upload_id: impl Into<String>) {
1245 self.upload_id = upload_id.into();
1246 }
1247}
1248
1249impl InputDescriptor for AbortMultipartUploadInput {
1250 fn operation(&self) -> &str {
1251 "AbortMultipartUpload"
1252 }
1253
1254 fn bucket(&self) -> Result<&str, TosError> {
1255 Ok(&self.bucket)
1256 }
1257
1258 fn key(&self) -> Result<&str, TosError> {
1259 Ok(&self.key)
1260 }
1261}
1262
1263impl<B> InputTranslator<B> for AbortMultipartUploadInput {
1264 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1265 let mut request = self.trans_key()?;
1266 request.method = HttpMethodDelete;
1267 let mut query = HashMap::with_capacity(1);
1268 set_upload_id(&mut query, &self.upload_id)?;
1269 request.query = Some(query);
1270 Ok(request)
1271 }
1272}
1273
1274#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
1275pub struct AbortMultipartUploadOutput {
1276 pub(crate) request_info: RequestInfo,
1277}
1278
1279impl OutputParser for AbortMultipartUploadOutput {
1280 fn parse_by_ref<B>(_: &HttpRequest<B>, _: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1281 Ok(Self { request_info })
1282 }
1283}
1284
1285#[derive(
1286 Debug,
1287 Clone,
1288 PartialEq,
1289 SsecHeader,
1290 CopySourceHeader,
1291 CopySourceSSecHeader,
1292 CopySourceIfConditionHeader,
1293 MultipartUploadQuery,
1294 GenericInput
1295)]
1296pub struct UploadPartCopyInput {
1297 pub(crate) generic_input: GenericInput,
1298 pub(crate) bucket: String,
1299 pub(crate) key: String,
1300 pub(crate) upload_id: String,
1301 pub(crate) part_number: isize,
1302
1303 pub(crate) src_bucket: String,
1304 pub(crate) src_key: String,
1305 pub(crate) src_version_id: String,
1306 pub(crate) copy_source_range_start: i64,
1307 pub(crate) copy_source_range_end: i64,
1308 pub(crate) copy_source_range: String,
1309
1310 pub(crate) copy_source_if_match: String,
1311 pub(crate) copy_source_if_modified_since: Option<DateTime<Utc>>,
1312 pub(crate) copy_source_if_none_match: String,
1313 pub(crate) copy_source_if_unmodified_since: Option<DateTime<Utc>>,
1314
1315 pub(crate) copy_source_ssec_algorithm: String,
1316 pub(crate) copy_source_ssec_key: String,
1317 pub(crate) copy_source_ssec_key_md5: String,
1318 pub(crate) ssec_algorithm: String,
1319 pub(crate) ssec_key: String,
1320 pub(crate) ssec_key_md5: String,
1321 pub(crate) traffic_limit: i64,
1322}
1323
1324impl InputDescriptor for UploadPartCopyInput {
1325 fn operation(&self) -> &str {
1326 "UploadPartCopy"
1327 }
1328 fn bucket(&self) -> Result<&str, TosError> {
1329 Ok(&self.bucket)
1330 }
1331
1332 fn key(&self) -> Result<&str, TosError> {
1333 Ok(&self.key)
1334 }
1335}
1336
1337impl<B> InputTranslator<B> for UploadPartCopyInput {
1338 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1339 let mut request = self.trans_key()?;
1340 request.method = HttpMethodPut;
1341 let header = &mut request.header;
1342 if self.copy_source_range != "" {
1343 if !self.copy_source_range.starts_with("bytes=") {
1344 return Err(TosError::client_error("invalid copy source range format"));
1345 }
1346 header.insert(HEADER_COPY_SOURCE_RANGE, self.copy_source_range.clone());
1347 } else if self.copy_source_range_start >= 0 && self.copy_source_range_end >= 0 && self.copy_source_range_start <= self.copy_source_range_end {
1348 header.insert(HEADER_COPY_SOURCE_RANGE, format!("bytes={}-{}", self.copy_source_range_start, self.copy_source_range_end));
1349 }
1350
1351 set_copy_source_header(header, self)?;
1352 set_copy_source_if_condition_header(header, self);
1353 set_ssec_header(header, "", self)?;
1354 set_copy_source_ssec_header(header, self)?;
1355 if self.traffic_limit > 0 {
1356 header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
1357 }
1358 let mut query = HashMap::with_capacity(2);
1359 set_multipart_upload_query(&mut query, self)?;
1360 request.query = Some(query);
1361 Ok(request)
1362 }
1363}
1364
1365impl Default for UploadPartCopyInput {
1366 fn default() -> Self {
1367 Self {
1368 generic_input: Default::default(),
1369 bucket: "".to_string(),
1370 key: "".to_string(),
1371 upload_id: "".to_string(),
1372 part_number: 1,
1373 src_bucket: "".to_string(),
1374 src_key: "".to_string(),
1375 src_version_id: "".to_string(),
1376 copy_source_range_start: -1,
1377 copy_source_range_end: -1,
1378 copy_source_range: "".to_string(),
1379 copy_source_if_match: "".to_string(),
1380 copy_source_if_modified_since: None,
1381 copy_source_if_none_match: "".to_string(),
1382 copy_source_if_unmodified_since: None,
1383 copy_source_ssec_algorithm: "".to_string(),
1384 copy_source_ssec_key: "".to_string(),
1385 copy_source_ssec_key_md5: "".to_string(),
1386 ssec_algorithm: "".to_string(),
1387 ssec_key: "".to_string(),
1388 ssec_key_md5: "".to_string(),
1389 traffic_limit: 0,
1390 }
1391 }
1392}
1393
1394impl UploadPartCopyInput {
1395 pub fn new(bucket: impl Into<String>, key: impl Into<String>,
1396 src_bucket: impl Into<String>, src_key: impl Into<String>, upload_id: impl Into<String>) -> Self {
1397 let mut input = Self::default();
1398 input.bucket = bucket.into();
1399 input.key = key.into();
1400 input.src_bucket = src_bucket.into();
1401 input.src_key = src_key.into();
1402 input.upload_id = upload_id.into();
1403 input
1404 }
1405
1406 pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>,
1407 src_bucket: impl Into<String>, src_key: impl Into<String>, upload_id: impl Into<String>, src_version_id: impl Into<String>) -> Self {
1408 let mut input = Self::default();
1409 input.bucket = bucket.into();
1410 input.key = key.into();
1411 input.src_bucket = src_bucket.into();
1412 input.src_key = src_key.into();
1413 input.upload_id = upload_id.into();
1414 input.src_version_id = src_version_id.into();
1415 input
1416 }
1417 pub fn new_with_part_number(bucket: impl Into<String>, key: impl Into<String>, src_bucket: impl Into<String>, src_key: impl Into<String>,
1418 upload_id: impl Into<String>, part_number: isize) -> Self {
1419 let mut input = Self::default();
1420 input.bucket = bucket.into();
1421 input.key = key.into();
1422 input.src_bucket = src_bucket.into();
1423 input.src_key = src_key.into();
1424 input.upload_id = upload_id.into();
1425 input.part_number = part_number;
1426 input
1427 }
1428 pub fn bucket(&self) -> &str {
1429 &self.bucket
1430 }
1431 pub fn key(&self) -> &str {
1432 &self.key
1433 }
1434 pub fn copy_source_range_start(&self) -> i64 {
1435 self.copy_source_range_start
1436 }
1437 pub fn copy_source_range_end(&self) -> i64 {
1438 self.copy_source_range_end
1439 }
1440 pub fn copy_source_range(&self) -> &str {
1441 &self.copy_source_range
1442 }
1443 pub fn traffic_limit(&self) -> i64 {
1444 self.traffic_limit
1445 }
1446 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1447 self.bucket = bucket.into();
1448 }
1449 pub fn set_key(&mut self, key: impl Into<String>) {
1450 self.key = key.into();
1451 }
1452 pub fn set_copy_source_range_start(&mut self, copy_source_range_start: i64) {
1453 self.copy_source_range_start = copy_source_range_start;
1454 }
1455 pub fn set_copy_source_range_end(&mut self, copy_source_range_end: i64) {
1456 self.copy_source_range_end = copy_source_range_end;
1457 }
1458 pub fn set_copy_source_range(&mut self, copy_source_range: impl Into<String>) {
1459 self.copy_source_range = copy_source_range.into();
1460 }
1461 pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
1462 self.traffic_limit = traffic_limit;
1463 }
1464}
1465
1466#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
1467pub struct UploadPartCopyOutput {
1468 pub(crate) request_info: RequestInfo,
1469 pub(crate) part_number: isize,
1470 pub(crate) etag: String,
1471 pub(crate) last_modified: Option<DateTime<Utc>>,
1472 pub(crate) copy_source_version_id: String,
1473 pub(crate) ssec_algorithm: String,
1474 pub(crate) ssec_key_md5: String,
1475 pub(crate) server_side_encryption: String,
1476 pub(crate) server_side_encryption_key_id: String,
1477}
1478
1479impl OutputParser for UploadPartCopyOutput {
1480 fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1481 let temp_result = parse_json::<TempCopyResult>(response)?;
1482 if temp_result.etag == "" {
1483 return Err(TosError::server_error_with_code(temp_result.code, temp_result.ec, temp_result.key, temp_result.message,
1484 temp_result.host_id, temp_result.resource, request_info));
1485 }
1486 let result = Self {
1487 request_info: request_info,
1488 part_number: get_map_value_from_str(request.query.as_ref().unwrap(), QUERY_PART_NUMBER, 1)?,
1489 etag: temp_result.etag,
1490 last_modified: parse_date_time_iso8601(&temp_result.last_modified)?,
1491 copy_source_version_id: get_header_value(response.headers(), HEADER_COPY_SOURCE_VERSION_ID),
1492 ssec_algorithm: get_header_value(response.headers(), HEADER_SSEC_ALGORITHM),
1493 ssec_key_md5: get_header_value(response.headers(), HEADER_SSEC_KEY_MD5),
1494 server_side_encryption: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION),
1495 server_side_encryption_key_id: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID),
1496 };
1497 Ok(result)
1498 }
1499}
1500
1501impl UploadPartCopyOutput {
1502 pub fn part_number(&self) -> isize {
1503 self.part_number
1504 }
1505 pub fn etag(&self) -> &str {
1506 &self.etag
1507 }
1508 pub fn last_modified(&self) -> Option<DateTime<Utc>> {
1509 self.last_modified
1510 }
1511 pub fn copy_source_version_id(&self) -> &str {
1512 &self.copy_source_version_id
1513 }
1514 pub fn ssec_algorithm(&self) -> &str {
1515 &self.ssec_algorithm
1516 }
1517 pub fn ssec_key_md5(&self) -> &str {
1518 &self.ssec_key_md5
1519 }
1520 pub fn server_side_encryption(&self) -> &str {
1521 &self.server_side_encryption
1522 }
1523 pub fn server_side_encryption_key_id(&self) -> &str {
1524 &self.server_side_encryption_key_id
1525 }
1526}
1527
1528#[derive(Debug, Clone, PartialEq, ListCommonQuery, GenericInput)]
1529pub struct ListMultipartUploadsInput {
1530 pub(crate) generic_input: GenericInput,
1531 pub(crate) bucket: String,
1532 pub(crate) prefix: String,
1533 pub(crate) delimiter: String,
1534 pub(crate) key_marker: String,
1535 pub(crate) upload_id_marker: String,
1536 pub(crate) max_uploads: isize,
1537 pub(crate) encoding_type: String,
1538}
1539
1540impl InputDescriptor for ListMultipartUploadsInput {
1541 fn operation(&self) -> &str {
1542 "ListMultipartUploads"
1543 }
1544
1545 fn bucket(&self) -> Result<&str, TosError> {
1546 Ok(&self.bucket)
1547 }
1548}
1549
1550impl<B> InputTranslator<B> for ListMultipartUploadsInput {
1551 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1552 let mut request = self.trans_bucket()?;
1553 request.method = HttpMethodGet;
1554 let mut query = HashMap::with_capacity(8);
1555 query.insert("uploads", "".to_string());
1556 set_list_common_query(&mut query, self);
1557 map_insert(&mut query, QUERY_KEY_MARKER, &self.key_marker);
1558 map_insert(&mut query, QUERY_UPLOAD_ID_MARKER, &self.upload_id_marker);
1559 if self.max_uploads >= 0 {
1560 query.insert(QUERY_MAX_UPLOADS, self.max_uploads.to_string());
1561 }
1562 request.query = Some(query);
1563 Ok(request)
1564 }
1565}
1566
1567impl Default for ListMultipartUploadsInput {
1568 fn default() -> Self {
1569 Self {
1570 generic_input: Default::default(),
1571 bucket: "".to_string(),
1572 prefix: "".to_string(),
1573 delimiter: "".to_string(),
1574 key_marker: "".to_string(),
1575 upload_id_marker: "".to_string(),
1576 max_uploads: -1,
1577 encoding_type: "".to_string(),
1578 }
1579 }
1580}
1581
1582impl ListMultipartUploadsInput {
1583 pub fn new(bucket: impl Into<String>) -> Self {
1584 let mut input = Self::default();
1585 input.bucket = bucket.into();
1586 input
1587 }
1588 pub fn bucket(&self) -> &str {
1589 &self.bucket
1590 }
1591 pub fn key_marker(&self) -> &str {
1592 &self.key_marker
1593 }
1594 pub fn upload_id_marker(&self) -> &str {
1595 &self.upload_id_marker
1596 }
1597 pub fn max_uploads(&self) -> isize {
1598 self.max_uploads
1599 }
1600 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1601 self.bucket = bucket.into();
1602 }
1603 pub fn set_key_marker(&mut self, key_marker: impl Into<String>) {
1604 self.key_marker = key_marker.into();
1605 }
1606 pub fn set_upload_id_marker(&mut self, upload_id_marker: impl Into<String>) {
1607 self.upload_id_marker = upload_id_marker.into();
1608 }
1609 pub fn set_max_uploads(&mut self, max_uploads: isize) {
1610 self.max_uploads = max_uploads;
1611 }
1612}
1613
1614#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
1615pub struct ListMultipartUploadsOutput {
1616 #[serde(skip)]
1617 pub(crate) request_info: RequestInfo,
1618 #[serde(default)]
1619 #[serde(rename = "Bucket")]
1620 pub(crate) bucket: String,
1621 #[serde(default)]
1622 #[serde(rename = "Prefix")]
1623 pub(crate) prefix: String,
1624 #[serde(default)]
1625 #[serde(rename = "KeyMarker")]
1626 pub(crate) key_marker: String,
1627 #[serde(default)]
1628 #[serde(rename = "UploadIdMarker")]
1629 pub(crate) upload_id_marker: String,
1630 #[serde(default)]
1631 #[serde(rename = "MaxUploads")]
1632 pub(crate) max_uploads: isize,
1633 #[serde(default)]
1634 #[serde(rename = "Delimiter")]
1635 pub(crate) delimiter: String,
1636 #[serde(default)]
1637 #[serde(rename = "IsTruncated")]
1638 pub(crate) is_truncated: bool,
1639 #[serde(default)]
1640 #[serde(rename = "EncodingType")]
1641 pub(crate) encoding_type: String,
1642 #[serde(default)]
1643 #[serde(rename = "NextKeyMarker")]
1644 pub(crate) next_key_marker: String,
1645 #[serde(default)]
1646 #[serde(rename = "NextUploadIdMarker")]
1647 pub(crate) next_upload_id_marker: String,
1648 #[serde(default)]
1649 #[serde(rename = "CommonPrefixes")]
1650 pub(crate) common_prefixes: Vec<ListedCommonPrefix>,
1651 #[serde(default)]
1652 #[serde(rename = "Uploads")]
1653 pub(crate) uploads: Vec<ListedUpload>,
1654}
1655
1656impl OutputParser for ListMultipartUploadsOutput {
1657 fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1658 let mut result = parse_json::<Self>(response)?;
1659 for upload in &mut result.uploads {
1660 if let Some(x) = upload.initiated_string.take() {
1661 upload.initiated = parse_date_time_iso8601(&x)?;
1662 }
1663 }
1664 result.request_info = request_info;
1665 Ok(result)
1666 }
1667}
1668
1669impl ListMultipartUploadsOutput {
1670 pub fn bucket(&self) -> &str {
1671 &self.bucket
1672 }
1673 pub fn prefix(&self) -> &str {
1674 &self.prefix
1675 }
1676 pub fn key_marker(&self) -> &str {
1677 &self.key_marker
1678 }
1679 pub fn upload_id_marker(&self) -> &str {
1680 &self.upload_id_marker
1681 }
1682 pub fn max_uploads(&self) -> isize {
1683 self.max_uploads
1684 }
1685 pub fn delimiter(&self) -> &str {
1686 &self.delimiter
1687 }
1688 pub fn is_truncated(&self) -> bool {
1689 self.is_truncated
1690 }
1691 pub fn encoding_type(&self) -> &str {
1692 &self.encoding_type
1693 }
1694 pub fn next_key_marker(&self) -> &str {
1695 &self.next_key_marker
1696 }
1697 pub fn next_upload_id_marker(&self) -> &str {
1698 &self.next_upload_id_marker
1699 }
1700 pub fn common_prefixes(&self) -> &Vec<ListedCommonPrefix> {
1701 &self.common_prefixes
1702 }
1703 pub fn uploads(&self) -> &Vec<ListedUpload> {
1704 &self.uploads
1705 }
1706}
1707
1708#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
1709pub struct ListedUpload {
1710 #[serde(default)]
1711 #[serde(rename = "Key")]
1712 pub(crate) key: String,
1713 #[serde(default)]
1714 #[serde(rename = "UploadId")]
1715 pub(crate) upload_id: String,
1716 #[serde(default)]
1717 #[serde(rename = "Owner")]
1718 pub(crate) owner: Owner,
1719 #[serde(default)]
1720 #[serde(rename = "StorageClass")]
1721 pub(crate) storage_class: Option<StorageClassType>,
1722 #[serde(default)]
1723 #[serde(rename = "Initiated")]
1724 pub(crate) initiated_string: Option<String>,
1725 #[serde(skip)]
1726 pub(crate) initiated: Option<DateTime<Utc>>,
1727}
1728
1729impl ListedUpload {
1730 pub fn key(&self) -> &str {
1731 &self.key
1732 }
1733 pub fn upload_id(&self) -> &str {
1734 &self.upload_id
1735 }
1736 pub fn owner(&self) -> &Owner {
1737 &self.owner
1738 }
1739 pub fn storage_class(&self) -> &Option<StorageClassType> {
1740 &self.storage_class
1741 }
1742 pub fn initiated(&self) -> Option<DateTime<Utc>> {
1743 self.initiated
1744 }
1745}
1746
1747#[derive(Debug, Clone, PartialEq, GenericInput)]
1748pub struct ListPartsInput {
1749 pub(crate) generic_input: GenericInput,
1750 pub(crate) bucket: String,
1751 pub(crate) key: String,
1752 pub(crate) upload_id: String,
1753 pub(crate) part_number_marker: isize,
1754 pub(crate) max_parts: isize,
1755}
1756
1757impl InputDescriptor for ListPartsInput {
1758 fn operation(&self) -> &str {
1759 "ListParts"
1760 }
1761
1762 fn bucket(&self) -> Result<&str, TosError> {
1763 Ok(&self.bucket)
1764 }
1765
1766 fn key(&self) -> Result<&str, TosError> {
1767 Ok(&self.key)
1768 }
1769}
1770
1771impl<B> InputTranslator<B> for ListPartsInput {
1772 fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1773 let mut request = self.trans_key()?;
1774 request.method = HttpMethodGet;
1775 let mut query = HashMap::with_capacity(8);
1776 set_upload_id(&mut query, &self.upload_id)?;
1777 if self.part_number_marker >= 0 {
1778 query.insert(QUERY_PART_NUMBER_MARKER, self.part_number_marker.to_string());
1779 }
1780 if self.max_parts >= 0 {
1781 query.insert(QUERY_MAX_PARTS, self.max_parts.to_string());
1782 }
1783 request.query = Some(query);
1784 Ok(request)
1785 }
1786}
1787
1788impl Default for ListPartsInput {
1789 fn default() -> Self {
1790 Self {
1791 generic_input: Default::default(),
1792 bucket: "".to_string(),
1793 key: "".to_string(),
1794 upload_id: "".to_string(),
1795 part_number_marker: 0,
1796 max_parts: -1,
1797 }
1798 }
1799}
1800
1801impl ListPartsInput {
1802 pub fn new(bucket: impl Into<String>, key: impl Into<String>, upload_id: impl Into<String>) -> Self {
1803 let mut input = Self::default();
1804 input.bucket = bucket.into();
1805 input.key = key.into();
1806 input.upload_id = upload_id.into();
1807 input
1808 }
1809 pub fn bucket(&self) -> &str {
1810 &self.bucket
1811 }
1812 pub fn key(&self) -> &str {
1813 &self.key
1814 }
1815 pub fn upload_id(&self) -> &str {
1816 &self.upload_id
1817 }
1818 pub fn part_number_marker(&self) -> isize {
1819 self.part_number_marker
1820 }
1821 pub fn max_parts(&self) -> isize {
1822 self.max_parts
1823 }
1824 pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1825 self.bucket = bucket.into();
1826 }
1827 pub fn set_key(&mut self, key: impl Into<String>) {
1828 self.key = key.into();
1829 }
1830 pub fn set_upload_id(&mut self, upload_id: impl Into<String>) {
1831 self.upload_id = upload_id.into();
1832 }
1833 pub fn set_part_number_marker(&mut self, part_number_marker: isize) {
1834 self.part_number_marker = part_number_marker;
1835 }
1836 pub fn set_max_parts(&mut self, max_parts: isize) {
1837 self.max_parts = max_parts;
1838 }
1839}
1840
1841#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
1842pub struct ListPartsOutput {
1843 #[serde(skip)]
1844 pub(crate) request_info: RequestInfo,
1845 #[serde(default)]
1846 #[serde(rename = "Bucket")]
1847 pub(crate) bucket: String,
1848 #[serde(default)]
1849 #[serde(rename = "Key")]
1850 pub(crate) key: String,
1851 #[serde(default)]
1852 #[serde(rename = "UploadId")]
1853 pub(crate) upload_id: String,
1854 #[serde(default)]
1855 #[serde(rename = "PartNumberMarker")]
1856 pub(crate) part_number_marker: isize,
1857 #[serde(default)]
1858 #[serde(rename = "MaxParts")]
1859 pub(crate) max_parts: isize,
1860 #[serde(default)]
1861 #[serde(rename = "IsTruncated")]
1862 pub(crate) is_truncated: bool,
1863 #[serde(default)]
1864 #[serde(rename = "NextPartNumberMarker")]
1865 pub(crate) next_part_number_marker: isize,
1866 #[serde(default)]
1867 #[serde(rename = "StorageClass")]
1868 pub(crate) storage_class: Option<StorageClassType>,
1869 #[serde(default)]
1870 #[serde(rename = "Owner")]
1871 pub(crate) owner: Owner,
1872 #[serde(default)]
1873 #[serde(rename = "Parts")]
1874 pub(crate) parts: Vec<UploadedPart>,
1875}
1876
1877impl OutputParser for ListPartsOutput {
1878 fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1879 let mut result = parse_json::<Self>(response)?;
1880 for part in &mut result.parts {
1881 if let Some(x) = part.last_modified_string.take() {
1882 part.last_modified = parse_date_time_iso8601(&x)?;
1883 }
1884 }
1885 result.request_info = request_info;
1886 Ok(result)
1887 }
1888}
1889
1890impl ListPartsOutput {
1891 pub fn bucket(&self) -> &str {
1892 &self.bucket
1893 }
1894 pub fn key(&self) -> &str {
1895 &self.key
1896 }
1897 pub fn upload_id(&self) -> &str {
1898 &self.upload_id
1899 }
1900 pub fn part_number_marker(&self) -> isize {
1901 self.part_number_marker
1902 }
1903 pub fn max_parts(&self) -> isize {
1904 self.max_parts
1905 }
1906 pub fn is_truncated(&self) -> bool {
1907 self.is_truncated
1908 }
1909 pub fn next_part_number_marker(&self) -> isize {
1910 self.next_part_number_marker
1911 }
1912 pub fn storage_class(&self) -> &Option<StorageClassType> {
1913 &self.storage_class
1914 }
1915 pub fn owner(&self) -> &Owner {
1916 &self.owner
1917 }
1918 pub fn parts(&self) -> &Vec<UploadedPart> {
1919 &self.parts
1920 }
1921}