Skip to main content

ve_tos_rust_sdk/
multipart.rs

1/*
2 * Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16use 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) != "" { // callback
1158            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}