Skip to main content

ve_tos_rust_sdk/
object.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 */
16
17use crate::bucket::is_non_positive;
18use crate::common::{DataTransferListener, DataTransferStatus, Grant, ListedCommonPrefix, Meta, Owner, RateLimiter, RequestInfo, RequestInfoTrait, TagSet, TempCopyResult};
19use crate::common::{GenericInput, UserMeta};
20use crate::config::ConfigHolder;
21use crate::constant::{DEFAULT_READ_BUFFER_SIZE, HEADER_CACHE_CONTROL, HEADER_CALLBACK, HEADER_CONTENT_DISPOSITION, HEADER_CONTENT_ENCODING, HEADER_CONTENT_LANGUAGE, HEADER_CONTENT_LENGTH, HEADER_CONTENT_MD5, HEADER_CONTENT_RANGE, HEADER_CONTENT_SHA256, HEADER_CONTENT_TYPE, HEADER_COPY_SOURCE_VERSION_ID, HEADER_DELETE_MARKER, HEADER_DIRECTORY, HEADER_ETAG, HEADER_EXPIRATION, HEADER_EXPIRES, HEADER_FETCH_DETECT_MIME_TYPE, HEADER_FORBID_OVERWRITE, HEADER_HASH_CRC64ECMA, HEADER_IF_NONE_MATCH, HEADER_LAST_MODIFIED, HEADER_LAST_MODIFIED_NS, HEADER_METADATA_DIRECTIVE, HEADER_MODIFY_TIMESTAMP, HEADER_MODIFY_TIMESTAMP_NS, HEADER_NEXT_APPEND_OFFSET, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, HEADER_OBJECT_EXPIRES, HEADER_OBJECT_TYPE, HEADER_PREFIX_META, HEADER_RANGE, HEADER_RECURSIVE_MKDIR, HEADER_REPLICATION_STATUS, HEADER_RESTORE, HEADER_RESTORE_EXPIRY_DAYS, HEADER_RESTORE_REQUEST_DATE, HEADER_RESTORE_TIER, HEADER_SERVER_SIDE_ENCRYPTION, HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID, HEADER_SSEC_ALGORITHM, HEADER_SSEC_KEY_MD5, HEADER_STORAGE_CLASS, HEADER_SYMLINK_BUCKET, HEADER_SYMLINK_TARGET, HEADER_SYMLINK_TARGET_SIZE, HEADER_TAGGING, HEADER_TAGGING_COUNT, HEADER_TAGGING_DIRECTIVE, HEADER_TRAFFIC_LIMIT, HEADER_TRANSFER_ENCODING_LOWER, HEADER_VERSION_ID, HEADER_WEBSITE_REDIRECT_LOCATION, HEADER_X_IF_MATCH, QUERY_CONTINUATION_TOKEN, QUERY_FETCH_META, QUERY_FETCH_OWNER, QUERY_KEY_MARKER, QUERY_MARKER, QUERY_MAX_KEYS, QUERY_OFFSET, QUERY_PROCESS, QUERY_RECURSIVE, QUERY_SKIP_TRASH, QUERY_START_AFTER, QUERY_TASK_ID, QUERY_VERSION_ID, QUERY_VERSION_ID_MARKER, TRUE, UUID_NODE};
22use crate::enumeration::HttpMethodType::{HttpMethodDelete, HttpMethodGet, HttpMethodHead, HttpMethodPost, HttpMethodPut};
23use crate::enumeration::{ACLType, DocPreviewDstType, DocPreviewSrcType, HttpMethodType, MetadataDirectiveType, ObjectLockModeType, ReplicationStatusType, StorageClassType, TaggingDirectiveType, TierType};
24use crate::error::{ErrorResponse, GenericError, TosError};
25use crate::http::{HttpRequest, HttpResponse, RequestContext};
26use crate::internal::{base64_md5, get_header_value_ref, map_insert, parse_json_by_buf, parse_response_string_by_buf, read_response, set_acl_header, set_copy_source_header, set_copy_source_if_condition_header, set_copy_source_ssec_header, set_data_process_query, set_http_basic_header, set_http_basic_header_for_fetch, set_if_match_header, set_misc_header, set_misc_header_for_fetch, set_object_lock_header, set_rewrite_response_query, set_sse_header, trans_meta, url_encode_with_safe};
27use crate::internal::{get_header_value, get_header_value_from_str, get_header_value_str, get_header_value_url_decoded, get_map_value_str, parse_date_time_iso8601, parse_date_time_rfc1123, parse_json, set_callback_header, set_if_condition_header, set_list_common_query, set_ssec_header, InputDescriptor, InputTranslator, OutputParser};
28use crate::reader::{BuildBufferReader, BuildFileReader, BuildMultiBufferReader, MultiBytes, MultifunctionalReader};
29use bytes::Bytes;
30use chrono::{DateTime, Utc};
31use futures_core::Stream;
32use reqwest::header::HeaderMap;
33use serde::{Deserialize, Serialize};
34use std::cell::{Ref, RefCell};
35use std::collections::{HashMap, LinkedList};
36use std::fmt::{Debug, Formatter};
37use std::fs;
38use std::fs::File;
39use std::io::{ErrorKind, Read, Write};
40use std::ops::Add;
41use std::path::Path;
42use std::sync::atomic::AtomicU64;
43use std::sync::mpsc::Sender;
44use std::sync::Arc;
45use std::time::Duration;
46use uuid::Uuid;
47use ve_tos_generic::{AclHeader, CallbackHeader, CopySourceHeader, CopySourceIfConditionHeader, CopySourceSSecHeader, DataProcessQuery, GenericInput, HttpBasicHeader, IfConditionHeader, IfMatch, ListCommonQuery, MiscHeader, ObjectLock, RequestInfo, RewriteResponseQuery, SseHeader, SsecHeader};
48
49pub trait ObjectAPI {
50    fn copy_object(&self, input: &CopyObjectInput) -> Result<CopyObjectOutput, TosError>;
51    fn delete_object(&self, input: &DeleteObjectInput) -> Result<DeleteObjectOutput, TosError>;
52    fn delete_multi_objects(&self, input: &DeleteMultiObjectsInput) -> Result<DeleteMultiObjectsOutput, TosError>;
53    fn get_object(&self, input: &GetObjectInput) -> Result<GetObjectOutput, TosError>;
54    fn get_object_to_file(&self, input: &GetObjectToFileInput) -> Result<GetObjectToFileOutput, TosError>;
55    fn get_object_acl(&self, input: &GetObjectACLInput) -> Result<GetObjectACLOutput, TosError>;
56    fn head_object(&self, input: &HeadObjectInput) -> Result<HeadObjectOutput, TosError>;
57    fn append_object<B>(&self, input: &AppendObjectInput<B>) -> Result<AppendObjectOutput, TosError>
58    where
59        B: Read + Send + 'static;
60    fn append_object_from_buffer(&self, input: &AppendObjectFromBufferInput) -> Result<AppendObjectOutput, TosError>;
61    #[deprecated]
62    fn list_objects(&self, input: &ListObjectsInput) -> Result<ListObjectsOutput, TosError>;
63    fn list_objects_type2(&self, input: &ListObjectsType2Input) -> Result<ListObjectsType2Output, TosError>;
64    fn list_object_versions(&self, input: &ListObjectVersionsInput) -> Result<ListObjectVersionsOutput, TosError>;
65    fn put_object<B>(&self, input: &PutObjectInput<B>) -> Result<PutObjectOutput, TosError>
66    where
67        B: Read + Send + 'static;
68    fn put_object_from_buffer(&self, input: &PutObjectFromBufferInput) -> Result<PutObjectOutput, TosError>;
69    fn put_object_from_file(&self, input: &PutObjectFromFileInput) -> Result<PutObjectOutput, TosError>;
70    fn put_object_acl(&self, input: &PutObjectACLInput) -> Result<PutObjectACLOutput, TosError>;
71    fn set_object_meta(&self, input: &SetObjectMetaInput) -> Result<SetObjectMetaOutput, TosError>;
72}
73
74pub trait ObjectContent {
75    type Content: ?Sized;
76
77    fn content(&mut self) -> Option<&mut Self::Content>;
78
79    fn read_all(&mut self) -> Result<Vec<u8>, TosError>;
80}
81
82#[derive(
83    Debug,
84    Clone,
85    PartialEq,
86    Default,
87    HttpBasicHeader,
88    AclHeader,
89    MiscHeader,
90    SseHeader,
91    SsecHeader,
92    CopySourceHeader,
93    CopySourceSSecHeader,
94    CopySourceIfConditionHeader,
95    GenericInput
96)]
97pub struct CopyObjectInput {
98    pub(crate) generic_input: GenericInput,
99    pub(crate) bucket: String,
100    pub(crate) key: String,
101
102    pub(crate) src_bucket: String,
103    pub(crate) src_key: String,
104    pub(crate) src_version_id: String,
105
106    pub(crate) content_length: i64,
107    pub(crate) cache_control: String,
108    pub(crate) content_disposition: String,
109    pub(crate) content_encoding: String,
110    pub(crate) content_language: String,
111    pub(crate) content_type: String,
112    pub(crate) expires: Option<DateTime<Utc>>,
113
114    pub(crate) copy_source_if_match: String,
115    pub(crate) copy_source_if_modified_since: Option<DateTime<Utc>>,
116    pub(crate) copy_source_if_none_match: String,
117    pub(crate) copy_source_if_unmodified_since: Option<DateTime<Utc>>,
118
119    pub(crate) copy_source_ssec_algorithm: String,
120    pub(crate) copy_source_ssec_key: String,
121    pub(crate) copy_source_ssec_key_md5: String,
122    pub(crate) ssec_algorithm: String,
123    pub(crate) ssec_key: String,
124    pub(crate) ssec_key_md5: String,
125    pub(crate) server_side_encryption: String,
126    pub(crate) server_side_encryption_key_id: String,
127
128    pub(crate) acl: Option<ACLType>,
129    pub(crate) grant_full_control: String,
130    pub(crate) grant_read: String,
131    pub(crate) grant_read_acp: String,
132    pub(crate) grant_write: String,
133    pub(crate) grant_write_acp: String,
134
135    pub(crate) metadata_directive: Option<MetadataDirectiveType>,
136    pub(crate) meta: HashMap<String, String>,
137    pub(crate) website_redirect_location: String,
138    pub(crate) storage_class: Option<StorageClassType>,
139    pub(crate) traffic_limit: i64,
140    pub(crate) forbid_overwrite: bool,
141    pub(crate) if_match: String,
142    pub(crate) if_none_match: String,
143
144    pub(crate) tagging: String,
145    pub(crate) tagging_directive: Option<TaggingDirectiveType>,
146    pub(crate) object_expires: i64,
147}
148
149impl CopyObjectInput {
150    pub fn new(bucket: impl Into<String>, key: impl Into<String>,
151               src_bucket: impl Into<String>, src_key: impl Into<String>) -> Self {
152        let mut input = Self::default();
153        input.bucket = bucket.into();
154        input.key = key.into();
155        input.src_bucket = src_bucket.into();
156        input.src_key = src_key.into();
157        input.content_length = -1;
158        input.object_expires = -1;
159        input
160    }
161
162    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>,
163                               src_bucket: impl Into<String>, src_key: impl Into<String>, src_version_id: impl Into<String>) -> Self {
164        let mut input = Self::default();
165        input.bucket = bucket.into();
166        input.key = key.into();
167        input.src_bucket = src_bucket.into();
168        input.src_key = src_key.into();
169        input.content_length = -1;
170        input.src_version_id = src_version_id.into();
171        input.object_expires = -1;
172        input
173    }
174
175    pub fn bucket(&self) -> &str {
176        &self.bucket
177    }
178
179    pub fn key(&self) -> &str {
180        &self.key
181    }
182
183    pub fn metadata_directive(&self) -> &Option<MetadataDirectiveType> {
184        &self.metadata_directive
185    }
186    pub fn meta(&self) -> &HashMap<String, String> {
187        &self.meta
188    }
189    pub fn traffic_limit(&self) -> i64 {
190        self.traffic_limit
191    }
192    pub fn forbid_overwrite(&self) -> bool {
193        self.forbid_overwrite
194    }
195    pub fn if_match(&self) -> &str {
196        &self.if_match
197    }
198    pub fn if_none_match(&self) -> &str {
199        &self.if_none_match
200    }
201    pub fn tagging(&self) -> &str {
202        &self.tagging
203    }
204
205    pub fn tagging_directive(&self) -> &Option<TaggingDirectiveType> {
206        &self.tagging_directive
207    }
208    pub fn object_expires(&self) -> i64 {
209        self.object_expires
210    }
211    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
212        self.bucket = bucket.into();
213    }
214    pub fn set_key(&mut self, key: impl Into<String>) {
215        self.key = key.into();
216    }
217    pub fn set_metadata_directive(&mut self, metadata_directive: impl Into<MetadataDirectiveType>) {
218        self.metadata_directive = Some(metadata_directive.into());
219    }
220    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
221        self.meta = meta.into();
222    }
223    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
224        self.traffic_limit = traffic_limit;
225    }
226    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
227        self.forbid_overwrite = forbid_overwrite;
228    }
229    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
230        self.if_match = if_match.into();
231    }
232    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
233        self.if_none_match = if_none_match.into();
234    }
235    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
236        self.tagging = tagging.into();
237    }
238    pub fn set_tagging_directive(&mut self, tagging_directive: impl Into<TaggingDirectiveType>) {
239        self.tagging_directive = Some(tagging_directive.into());
240    }
241    pub fn set_object_expires(&mut self, object_expires: i64) {
242        self.object_expires = object_expires;
243    }
244}
245
246impl InputDescriptor for CopyObjectInput {
247    fn operation(&self) -> &str {
248        "CopyObject"
249    }
250    fn bucket(&self) -> Result<&str, TosError> {
251        Ok(&self.bucket)
252    }
253    fn key(&self) -> Result<&str, TosError> {
254        Ok(&self.key)
255    }
256}
257
258impl<B> InputTranslator<B> for CopyObjectInput {
259    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
260        let mut request = self.trans_key()?;
261        request.method = HttpMethodPut;
262        let header = &mut request.header;
263        set_copy_source_header(header, self)?;
264        set_copy_source_if_condition_header(header, self);
265        set_http_basic_header(header, config_holder.disable_encoding_meta, self);
266        set_sse_header(header, self)?;
267        set_ssec_header(header, &self.server_side_encryption, self)?;
268        set_copy_source_ssec_header(header, self)?;
269        set_acl_header(header, self);
270        request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
271        set_misc_header(header, self);
272        if let Some(metadata_directive) = &self.metadata_directive {
273            header.insert(HEADER_METADATA_DIRECTIVE, metadata_directive.as_str().to_string());
274        }
275        if self.forbid_overwrite {
276            header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
277        }
278        if self.traffic_limit > 0 {
279            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
280        }
281        map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
282        map_insert(header, HEADER_IF_NONE_MATCH, &self.if_none_match);
283
284        if self.tagging != "" {
285            if let Some(tagging_directive) = &self.tagging_directive {
286                header.insert(HEADER_TAGGING_DIRECTIVE, tagging_directive.as_str().to_string());
287            }
288            header.insert(HEADER_TAGGING, self.tagging.clone());
289        }
290        if self.object_expires >= 0 {
291            header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
292        }
293
294        Ok(request)
295    }
296}
297
298#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
299pub struct CopyObjectOutput {
300    pub(crate) request_info: RequestInfo,
301    pub(crate) etag: String,
302    pub(crate) last_modified: Option<DateTime<Utc>>,
303    pub(crate) copy_source_version_id: String,
304    pub(crate) version_id: String,
305    pub(crate) ssec_algorithm: String,
306    pub(crate) ssec_key_md5: String,
307    pub(crate) server_side_encryption: String,
308    pub(crate) server_side_encryption_key_id: String,
309}
310
311impl CopyObjectOutput {
312    pub fn etag(&self) -> &str {
313        &self.etag
314    }
315    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
316        self.last_modified
317    }
318    pub fn copy_source_version_id(&self) -> &str {
319        &self.copy_source_version_id
320    }
321    pub fn version_id(&self) -> &str {
322        &self.version_id
323    }
324    pub fn ssec_algorithm(&self) -> &str {
325        &self.ssec_algorithm
326    }
327    pub fn ssec_key_md5(&self) -> &str {
328        &self.ssec_key_md5
329    }
330    pub fn server_side_encryption(&self) -> &str {
331        &self.server_side_encryption
332    }
333    pub fn server_side_encryption_key_id(&self) -> &str {
334        &self.server_side_encryption_key_id
335    }
336}
337
338impl OutputParser for CopyObjectOutput {
339    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
340        let temp_result = parse_json::<TempCopyResult>(response)?;
341        if temp_result.etag == "" {
342            return Err(TosError::server_error_with_code(temp_result.code, temp_result.ec, temp_result.key, temp_result.message,
343                                                        temp_result.host_id, temp_result.resource, request_info));
344        }
345
346        let mut result = Self {
347            request_info: RequestInfo::default(),
348            etag: temp_result.etag,
349            last_modified: parse_date_time_iso8601(&temp_result.last_modified)?,
350            copy_source_version_id: get_header_value(response.headers(), HEADER_COPY_SOURCE_VERSION_ID),
351            version_id: get_header_value(response.headers(), HEADER_VERSION_ID),
352            ssec_algorithm: get_header_value(response.headers(), HEADER_SSEC_ALGORITHM),
353            ssec_key_md5: get_header_value(response.headers(), HEADER_SSEC_KEY_MD5),
354            server_side_encryption: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION),
355            server_side_encryption_key_id: get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID),
356        };
357
358        result.request_info = request_info;
359        Ok(result)
360    }
361}
362
363#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
364pub struct DeleteObjectInput {
365    pub(crate) generic_input: GenericInput,
366    pub(crate) bucket: String,
367    pub(crate) key: String,
368    pub(crate) version_id: String,
369    pub(crate) recursive: bool,
370    pub(crate) skip_trash: bool,
371    pub(crate) if_match: String,
372}
373
374impl DeleteObjectInput {
375    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
376        Self {
377            generic_input: Default::default(),
378            bucket: bucket.into(),
379            key: key.into(),
380            version_id: "".to_string(),
381            recursive: false,
382            skip_trash: false,
383            if_match: "".to_string(),
384        }
385    }
386    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
387        Self {
388            generic_input: Default::default(),
389            bucket: bucket.into(),
390            key: key.into(),
391            version_id: version_id.into(),
392            recursive: false,
393            skip_trash: false,
394            if_match: "".to_string(),
395        }
396    }
397    pub fn bucket(&self) -> &str {
398        &self.bucket
399    }
400    pub fn key(&self) -> &str {
401        &self.key
402    }
403    pub fn version_id(&self) -> &str {
404        &self.version_id
405    }
406    pub fn recursive(&self) -> bool {
407        self.recursive
408    }
409    pub fn if_match(&self) -> &str {
410        &self.if_match
411    }
412    pub fn skip_trash(&self) -> bool {
413        self.skip_trash
414    }
415    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
416        self.bucket = bucket.into();
417    }
418    pub fn set_key(&mut self, key: impl Into<String>) {
419        self.key = key.into();
420    }
421    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
422        self.version_id = version_id.into();
423    }
424    pub fn set_recursive(&mut self, recursive: bool) {
425        self.recursive = recursive;
426    }
427
428    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
429        self.if_match = if_match.into();
430    }
431    pub fn set_skip_trash(&mut self, skip_trash: bool) {
432        self.skip_trash = skip_trash;
433    }
434}
435
436impl InputDescriptor for DeleteObjectInput {
437    fn operation(&self) -> &str {
438        "DeleteObject"
439    }
440    fn bucket(&self) -> Result<&str, TosError> {
441        Ok(&self.bucket)
442    }
443    fn key(&self) -> Result<&str, TosError> {
444        Ok(&self.key)
445    }
446}
447
448impl<B> InputTranslator<B> for DeleteObjectInput {
449    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
450        let mut request = self.trans_key()?;
451        request.method = HttpMethodDelete;
452        map_insert(&mut request.header, HEADER_X_IF_MATCH, &self.if_match);
453        let mut query = HashMap::with_capacity(3);
454        map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
455        if self.recursive {
456            query.insert(QUERY_RECURSIVE, self.recursive.to_string());
457        }
458        if self.skip_trash {
459            query.insert(QUERY_SKIP_TRASH, self.skip_trash.to_string());
460        }
461        request.query = Some(query);
462        Ok(request)
463    }
464}
465
466#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
467pub struct DeleteObjectOutput {
468    pub(crate) request_info: RequestInfo,
469    pub(crate) delete_marker: bool,
470    pub(crate) version_id: String,
471}
472
473impl DeleteObjectOutput {
474    pub fn delete_marker(&self) -> bool {
475        self.delete_marker
476    }
477    pub fn version_id(&self) -> &str {
478        &self.version_id
479    }
480}
481
482impl OutputParser for DeleteObjectOutput {
483    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
484        let version_id = get_header_value(response.headers(), HEADER_VERSION_ID);
485        let delete_marker = get_header_value_ref(response.headers(), HEADER_DELETE_MARKER) == TRUE;
486        Ok(Self {
487            request_info,
488            delete_marker,
489            version_id,
490        })
491    }
492}
493
494#[derive(Debug, Clone, PartialEq, Default, Serialize, GenericInput)]
495pub struct DeleteMultiObjectsInput {
496    #[serde(skip)]
497    pub(crate) generic_input: GenericInput,
498    #[serde(skip)]
499    pub(crate) bucket: String,
500    #[serde(rename = "Objects")]
501    pub(crate) objects: Vec<ObjectTobeDeleted>,
502    #[serde(rename = "Quiet")]
503    pub(crate) quiet: bool,
504    #[serde(skip)]
505    pub(crate) recursive: bool,
506    #[serde(skip)]
507    pub(crate) skip_trash: bool,
508}
509
510#[derive(Debug, Clone, PartialEq, Default, Serialize)]
511pub struct ObjectTobeDeleted {
512    #[serde(rename = "Key")]
513    pub(crate) key: String,
514    #[serde(rename = "VersionId")]
515    #[serde(skip_serializing_if = "String::is_empty")]
516    pub(crate) version_id: String,
517}
518
519impl ObjectTobeDeleted {
520    pub fn new(key: impl Into<String>) -> Self {
521        Self { key: key.into(), version_id: "".to_string() }
522    }
523    pub fn new_with_version_id(key: impl Into<String>, version_id: impl Into<String>) -> Self {
524        Self { key: key.into(), version_id: version_id.into() }
525    }
526    pub fn key(&self) -> &str {
527        &self.key
528    }
529    pub fn version_id(&self) -> &str {
530        &self.version_id
531    }
532    pub fn set_key(&mut self, key: impl Into<String>) {
533        self.key = key.into();
534    }
535    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
536        self.version_id = version_id.into();
537    }
538}
539
540
541impl DeleteMultiObjectsInput {
542    pub fn new(bucket: impl Into<String>) -> Self {
543        Self {
544            generic_input: Default::default(),
545            bucket: bucket.into(),
546            objects: vec![],
547            quiet: false,
548            recursive: false,
549            skip_trash: false,
550        }
551    }
552    pub fn new_with_objects(bucket: impl Into<String>, objects: impl Into<Vec<ObjectTobeDeleted>>) -> Self {
553        Self {
554            generic_input: Default::default(),
555            bucket: bucket.into(),
556            objects: objects.into(),
557            quiet: false,
558            recursive: false,
559            skip_trash: false,
560        }
561    }
562
563    pub fn add_object(&mut self, object: impl Into<ObjectTobeDeleted>) {
564        self.objects.push(object.into());
565    }
566
567    pub fn bucket(&self) -> &str {
568        &self.bucket
569    }
570    pub fn objects(&self) -> &Vec<ObjectTobeDeleted> {
571        &self.objects
572    }
573    pub fn quiet(&self) -> bool {
574        self.quiet
575    }
576    pub fn recursive(&self) -> bool {
577        self.recursive
578    }
579
580    pub fn skip_trash(&self) -> bool {
581        self.skip_trash
582    }
583    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
584        self.bucket = bucket.into();
585    }
586    pub fn set_objects(&mut self, objects: impl Into<Vec<ObjectTobeDeleted>>) {
587        self.objects = objects.into();
588    }
589    pub fn set_quiet(&mut self, quiet: bool) {
590        self.quiet = quiet;
591    }
592
593    pub fn set_recursive(&mut self, recursive: bool) {
594        self.recursive = recursive;
595    }
596
597    pub fn set_skip_trash(&mut self, skip_trash: bool) {
598        self.skip_trash = skip_trash;
599    }
600}
601
602impl InputDescriptor for DeleteMultiObjectsInput {
603    fn operation(&self) -> &str {
604        "DeleteMultiObjects"
605    }
606
607    fn bucket(&self) -> Result<&str, TosError> {
608        Ok(&self.bucket)
609    }
610}
611
612impl<B> InputTranslator<B> for DeleteMultiObjectsInput
613where
614    B: BuildBufferReader,
615{
616    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
617        if self.objects.len() == 0 {
618            return Err(TosError::client_error("empty objects for delete"));
619        }
620
621        match serde_json::to_string(self) {
622            Err(e) => Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
623            Ok(json) => {
624                let mut request = self.trans_bucket()?;
625                request.method = HttpMethodPost;
626                request.header.insert(HEADER_CONTENT_MD5, base64_md5(&json));
627                let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
628                request.body = Some(body);
629                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
630
631                let mut query = HashMap::with_capacity(3);
632                if self.recursive {
633                    query.insert(QUERY_RECURSIVE, self.recursive.to_string());
634                }
635                if self.skip_trash {
636                    query.insert(QUERY_SKIP_TRASH, self.skip_trash.to_string());
637                }
638                query.insert("delete", "".to_string());
639                request.query = Some(query);
640                Ok(request)
641            }
642        }
643    }
644}
645
646
647#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
648pub struct DeleteMultiObjectsOutput {
649    #[serde(skip)]
650    pub(crate) request_info: RequestInfo,
651    #[serde(default)]
652    #[serde(rename = "Deleted")]
653    pub(crate) deleted: Vec<Deleted>,
654    #[serde(default)]
655    #[serde(rename = "Error")]
656    pub(crate) error: Vec<DeleteError>,
657}
658
659#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
660pub struct Deleted {
661    #[serde(default)]
662    #[serde(rename = "Key")]
663    pub(crate) key: String,
664    #[serde(default)]
665    #[serde(rename = "VersionId")]
666    pub(crate) version_id: String,
667    #[serde(default)]
668    #[serde(rename = "DeleteMarker")]
669    pub(crate) delete_marker: bool,
670    #[serde(default)]
671    #[serde(rename = "DeleteMarkerVersionId")]
672    pub(crate) delete_marker_version_id: String,
673}
674
675#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
676pub struct DeleteError {
677    #[serde(default)]
678    #[serde(rename = "Key")]
679    pub(crate) key: String,
680    #[serde(default)]
681    #[serde(rename = "VersionId")]
682    pub(crate) version_id: String,
683    #[serde(default)]
684    #[serde(rename = "Code")]
685    pub(crate) code: String,
686    #[serde(default)]
687    #[serde(rename = "Message")]
688    pub(crate) message: String,
689}
690
691impl Deleted {
692    pub fn key(&self) -> &str {
693        &self.key
694    }
695    pub fn version_id(&self) -> &str {
696        &self.version_id
697    }
698    pub fn delete_marker(&self) -> bool {
699        self.delete_marker
700    }
701    pub fn delete_marker_version_id(&self) -> &str {
702        &self.delete_marker_version_id
703    }
704}
705
706
707impl DeleteError {
708    pub fn key(&self) -> &str {
709        &self.key
710    }
711    pub fn version_id(&self) -> &str {
712        &self.version_id
713    }
714    pub fn code(&self) -> &str {
715        &self.code
716    }
717    pub fn message(&self) -> &str {
718        &self.message
719    }
720}
721
722impl DeleteMultiObjectsOutput {
723    pub fn deleted(&self) -> &Vec<Deleted> {
724        &self.deleted
725    }
726    pub fn error(&self) -> &Vec<DeleteError> {
727        &self.error
728    }
729}
730
731impl OutputParser for DeleteMultiObjectsOutput {
732    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
733        let mut result = parse_json::<Self>(response)?;
734        result.request_info = request_info;
735        Ok(result)
736    }
737}
738
739#[derive(
740    Debug,
741    Clone,
742    IfConditionHeader,
743    SsecHeader,
744    RewriteResponseQuery,
745    DataProcessQuery,
746    GenericInput
747)]
748pub struct GetObjectInput {
749    pub(crate) generic_input: GenericInput,
750    pub(crate) bucket: String,
751    pub(crate) key: String,
752    pub(crate) version_id: String,
753    pub(crate) if_match: String,
754    pub(crate) if_modified_since: Option<DateTime<Utc>>,
755    pub(crate) if_none_match: String,
756    pub(crate) if_unmodified_since: Option<DateTime<Utc>>,
757    pub(crate) ssec_algorithm: String,
758    pub(crate) ssec_key: String,
759    pub(crate) ssec_key_md5: String,
760
761    pub(crate) response_cache_control: String,
762    pub(crate) response_content_disposition: String,
763    pub(crate) response_content_encoding: String,
764    pub(crate) response_content_language: String,
765    pub(crate) response_content_type: String,
766    pub(crate) response_expires: Option<DateTime<Utc>>,
767
768    pub(crate) range_start: i64,
769    pub(crate) range_end: i64,
770
771    pub(crate) range: String,
772    pub(crate) traffic_limit: i64,
773
774    pub(crate) process: String,
775
776    pub(crate) doc_page: isize,
777    pub(crate) src_type: Option<DocPreviewSrcType>,
778    pub(crate) dst_type: Option<DocPreviewDstType>,
779
780    pub(crate) save_bucket: String,
781    pub(crate) save_object: String,
782    pub(crate) rate_limiter: Option<Arc<RateLimiter>>,
783    pub(crate) data_transfer_listener: Option<Sender<DataTransferStatus>>,
784    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
785}
786
787impl InputDescriptor for GetObjectInput {
788    fn operation(&self) -> &str {
789        "GetObject"
790    }
791    fn bucket(&self) -> Result<&str, TosError> {
792        Ok(&self.bucket)
793    }
794
795    fn key(&self) -> Result<&str, TosError> {
796        Ok(&self.key)
797    }
798}
799
800impl<B> InputTranslator<B> for GetObjectInput {
801    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
802        let mut request = self.trans_key()?;
803        request.method = HttpMethodGet;
804        if let Some(rl) = self.rate_limiter() {
805            let mut rc = RequestContext::default();
806            rc.rate_limiter = Some(rl.clone());
807            request.request_context = Some(rc);
808        }
809
810        if let Some(ref dts) = self.data_transfer_listener {
811            if request.request_context.is_some() {
812                request.request_context.as_mut().unwrap().data_transfer_listener = Some(dts.clone());
813            } else {
814                let mut rc = RequestContext::default();
815                rc.data_transfer_listener = Some(dts.clone());
816                request.request_context = Some(rc);
817            }
818        } else if let Some(ref adts) = self.async_data_transfer_listener {
819            if request.request_context.is_some() {
820                request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
821            } else {
822                let mut rc = RequestContext::default();
823                rc.async_data_transfer_listener = Some(adts.clone());
824                request.request_context = Some(rc);
825            }
826        }
827
828        let header = &mut request.header;
829        set_if_condition_header(header, self);
830        set_ssec_header(header, "", self)?;
831        if self.range != "" {
832            if !self.range.starts_with("bytes=") {
833                return Err(TosError::client_error("invalid range format"));
834            }
835            header.insert(HEADER_RANGE, self.range.clone());
836        } else if self.range_start >= 0 && self.range_end >= 0 && self.range_start <= self.range_end {
837            header.insert(HEADER_RANGE, format!("bytes={}-{}", self.range_start, self.range_end));
838        }
839        if self.traffic_limit > 0 {
840            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
841        }
842
843        let mut query = HashMap::with_capacity(16);
844        map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
845        set_rewrite_response_query(&mut query, self);
846        set_data_process_query(&mut query, self);
847
848        request.query = Some(query);
849        Ok(request)
850    }
851}
852
853impl Default for GetObjectInput {
854    fn default() -> Self {
855        Self {
856            generic_input: Default::default(),
857            bucket: "".to_string(),
858            key: "".to_string(),
859            version_id: "".to_string(),
860            if_match: "".to_string(),
861            if_modified_since: None,
862            if_none_match: "".to_string(),
863            if_unmodified_since: None,
864            ssec_algorithm: "".to_string(),
865            ssec_key: "".to_string(),
866            ssec_key_md5: "".to_string(),
867            response_cache_control: "".to_string(),
868            response_content_disposition: "".to_string(),
869            response_content_encoding: "".to_string(),
870            response_content_language: "".to_string(),
871            response_content_type: "".to_string(),
872            response_expires: None,
873            range_start: -1,
874            range_end: -1,
875            range: "".to_string(),
876            traffic_limit: 0,
877            process: "".to_string(),
878            doc_page: 0,
879            src_type: None,
880            dst_type: None,
881            save_bucket: "".to_string(),
882            save_object: "".to_string(),
883            rate_limiter: None,
884            data_transfer_listener: None,
885            async_data_transfer_listener: None,
886        }
887    }
888}
889
890impl DataTransferListener for GetObjectInput {
891    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
892        &self.data_transfer_listener
893    }
894
895    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
896        self.data_transfer_listener = Some(listener.into());
897    }
898}
899
900impl GetObjectInput {
901    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
902        let mut input = Self::default();
903        input.bucket = bucket.into();
904        input.key = key.into();
905        input
906    }
907    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
908        let mut input = Self::default();
909        input.bucket = bucket.into();
910        input.key = key.into();
911        input.version_id = version_id.into();
912        input
913    }
914    pub fn bucket(&self) -> &str {
915        &self.bucket
916    }
917    pub fn key(&self) -> &str {
918        &self.key
919    }
920    pub fn version_id(&self) -> &str {
921        &self.version_id
922    }
923    pub fn range_start(&self) -> i64 {
924        self.range_start
925    }
926    pub fn range_end(&self) -> i64 {
927        self.range_end
928    }
929    pub fn range(&self) -> &str {
930        &self.range
931    }
932    pub fn traffic_limit(&self) -> i64 {
933        self.traffic_limit
934    }
935    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
936        &self.rate_limiter
937    }
938    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
939        self.bucket = bucket.into();
940    }
941    pub fn set_key(&mut self, key: impl Into<String>) {
942        self.key = key.into();
943    }
944    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
945        self.version_id = version_id.into();
946    }
947    pub fn set_range_start(&mut self, range_start: i64) {
948        self.range_start = range_start;
949    }
950    pub fn set_range_end(&mut self, range_end: i64) {
951        self.range_end = range_end;
952    }
953    pub fn set_range(&mut self, range: impl Into<String>) {
954        self.range = range.into();
955    }
956    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
957        self.traffic_limit = traffic_limit;
958    }
959    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
960        self.rate_limiter = Some(rate_limiter.into());
961    }
962}
963
964#[derive(Default)]
965pub struct GetObjectOutput {
966    pub(crate) content_range: String,
967    pub(crate) content: Option<MultifunctionalReader<HttpResponse>>,
968    pub(crate) async_content: Option<MultifunctionalReader<Box<dyn Stream<Item=Result<Bytes, crate::error::CommonError>> + Send + Unpin>>>,
969    pub(crate) head_object_output: HeadObjectOutput,
970}
971
972unsafe impl Sync for GetObjectOutput {}
973
974impl Debug for GetObjectOutput {
975    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
976        write!(f, "({:?}, {})", self.head_object_output, self.content_range)
977    }
978}
979
980impl OutputParser for GetObjectOutput {
981    fn parse_by_ref<B>(_: &HttpRequest<B>, _: &mut HttpResponse, _: RequestInfo, _: Meta) -> Result<Self, TosError> {
982        Err(TosError::client_error("unimplemented"))
983    }
984
985    fn parse<B>(request: HttpRequest<B>, response: HttpResponse, request_info: RequestInfo, meta: Meta) -> Result<Self, TosError> {
986        let transfer_encoding = request_info.header.get(HEADER_TRANSFER_ENCODING_LOWER).map(|x| x.to_string());
987        let head_object_output = HeadObjectOutput::parse_by_header(response.headers(), request_info, meta)?;
988        let content_range = get_header_value(response.headers(), HEADER_CONTENT_RANGE);
989        let mut target_crc64 = None;
990        if request.enable_crc && !request.header.contains_key(HEADER_RANGE) &&
991            (request.query.is_none() || !request.query.as_ref().unwrap().contains_key(QUERY_PROCESS)) {
992            if let Some(te) = transfer_encoding {
993                if te != "chunked" {
994                    target_crc64 = Some(head_object_output.hash_crc64ecma);
995                }
996            } else {
997                target_crc64 = Some(head_object_output.hash_crc64ecma);
998            }
999        }
1000        let mut crc64 = None;
1001        if target_crc64.is_some() {
1002            crc64 = Some(Arc::new(AtomicU64::new(0)));
1003        }
1004        let mut reader = MultifunctionalReader::with_target_crc64(response, crc64, head_object_output.content_length,
1005                                                                  &request, target_crc64);
1006
1007        if let Some(ref rc) = request.request_context {
1008            if let Some(ref rl) = rc.rate_limiter {
1009                reader.set_rate_limiter(rl.clone());
1010            }
1011            if let Some(ref dts) = rc.data_transfer_listener {
1012                reader.set_data_transfer_listener(dts.clone());
1013                reader.inner.operation = request.operation.to_string();
1014                reader.inner.bucket = request.bucket.to_string();
1015                reader.inner.key = request.key.to_string();
1016                reader.inner.retry_count = request.retry_count;
1017            }
1018        }
1019
1020        Ok(Self {
1021            content_range,
1022            content: Some(reader),
1023            async_content: None,
1024            head_object_output,
1025        })
1026    }
1027}
1028
1029impl Read for GetObjectOutput {
1030    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1031        match self.content.as_mut() {
1032            None => {
1033                Err(std::io::Error::new(ErrorKind::Other, "empty content"))
1034            }
1035            Some(content) => {
1036                content.read(buf)
1037            }
1038        }
1039    }
1040}
1041
1042impl ObjectContent for GetObjectOutput {
1043    type Content = dyn Read;
1044
1045    fn content(&mut self) -> Option<&mut Self::Content> {
1046        match self.content.as_mut() {
1047            None => None,
1048            Some(x) => Some(x as &mut dyn Read),
1049        }
1050    }
1051
1052    fn read_all(&mut self) -> Result<Vec<u8>, TosError> {
1053        let x = self.content_length();
1054        if x == 0 {
1055            return Ok(vec![]);
1056        }
1057        let mut buf;
1058        if x > 0 {
1059            buf = Vec::with_capacity(x as usize);
1060        } else {
1061            buf = Vec::new();
1062        }
1063        match self.content.as_mut() {
1064            None => Err(TosError::client_error("empty content")),
1065            Some(r) => {
1066                match r.read_to_end(&mut buf) {
1067                    Err(e) => Err(TosError::client_error_with_cause("read error", GenericError::IoError(e.to_string()))),
1068                    Ok(_) => Ok(buf),
1069                }
1070            }
1071        }
1072    }
1073}
1074
1075impl RequestInfoTrait for GetObjectOutput {
1076    fn request_id(&self) -> &str {
1077        &self.head_object_output.request_info.request_id
1078    }
1079
1080    fn id2(&self) -> &str {
1081        &self.head_object_output.request_info.id2
1082    }
1083
1084    fn status_code(&self) -> isize {
1085        self.head_object_output.request_info.status_code
1086    }
1087
1088    fn header(&self) -> &HashMap<String, String> {
1089        &self.head_object_output.request_info.header
1090    }
1091}
1092
1093impl GetObjectOutput {
1094    pub fn request_id(&self) -> &str {
1095        &self.head_object_output.request_info.request_id
1096    }
1097
1098    pub fn id2(&self) -> &str {
1099        &self.head_object_output.request_info.id2
1100    }
1101
1102    pub fn status_code(&self) -> isize {
1103        self.head_object_output.request_info.status_code
1104    }
1105
1106    pub fn header(&self) -> &HashMap<String, String> {
1107        &self.head_object_output.request_info.header
1108    }
1109    pub fn content_range(&self) -> &str {
1110        &self.content_range
1111    }
1112    pub fn etag(&self) -> &str {
1113        &self.head_object_output.etag
1114    }
1115    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
1116        self.head_object_output.last_modified
1117    }
1118    pub fn last_modified_timestamp(&self) -> Option<DateTime<Utc>> {
1119        self.head_object_output.last_modify_timestamp
1120    }
1121    pub fn delete_marker(&self) -> bool {
1122        self.head_object_output.delete_marker
1123    }
1124    pub fn ssec_algorithm(&self) -> &str {
1125        &self.head_object_output.ssec_algorithm
1126    }
1127    pub fn ssec_key_md5(&self) -> &str {
1128        &self.head_object_output.ssec_key_md5
1129    }
1130    pub fn version_id(&self) -> &str {
1131        &self.head_object_output.version_id
1132    }
1133    pub fn website_redirect_location(&self) -> &str {
1134        &self.head_object_output.website_redirect_location
1135    }
1136    pub fn object_type(&self) -> &str {
1137        &self.head_object_output.object_type
1138    }
1139    pub fn hash_crc64ecma(&self) -> u64 {
1140        self.head_object_output.hash_crc64ecma
1141    }
1142    pub fn storage_class(&self) -> &Option<StorageClassType> {
1143        &self.head_object_output.storage_class
1144    }
1145    pub fn meta(&self) -> &HashMap<String, String> {
1146        &self.head_object_output.meta
1147    }
1148    pub fn content_length(&self) -> i64 {
1149        self.head_object_output.content_length
1150    }
1151    pub fn cache_control(&self) -> &str {
1152        &self.head_object_output.cache_control
1153    }
1154    pub fn content_disposition(&self) -> &str {
1155        &self.head_object_output.content_disposition
1156    }
1157    pub fn content_encoding(&self) -> &str {
1158        &self.head_object_output.content_encoding
1159    }
1160    pub fn content_language(&self) -> &str {
1161        &self.head_object_output.content_language
1162    }
1163    pub fn content_type(&self) -> &str {
1164        &self.head_object_output.content_type
1165    }
1166    pub fn expires(&self) -> Option<DateTime<Utc>> {
1167        self.head_object_output.expires
1168    }
1169    pub fn restore_info(&self) -> &Option<RestoreInfo> {
1170        &self.head_object_output.restore_info
1171    }
1172    pub fn server_side_encryption(&self) -> &str {
1173        &self.head_object_output.server_side_encryption
1174    }
1175    pub fn server_side_encryption_key_id(&self) -> &str {
1176        &self.head_object_output.server_side_encryption_key_id
1177    }
1178    pub fn replication_status(&self) -> &Option<ReplicationStatusType> {
1179        &self.head_object_output.replication_status
1180    }
1181    pub fn tagging_count(&self) -> isize {
1182        self.head_object_output.tagging_count
1183    }
1184    pub fn expiration(&self) -> &str {
1185        &self.head_object_output.expiration
1186    }
1187    pub fn is_directory(&self) -> bool {
1188        self.head_object_output.is_directory
1189    }
1190}
1191
1192#[derive(
1193    Debug,
1194    Clone,
1195    IfConditionHeader,
1196    SsecHeader,
1197    RewriteResponseQuery,
1198    DataProcessQuery,
1199    GenericInput
1200)]
1201#[use_inner]
1202pub struct GetObjectToFileInput {
1203    pub(crate) inner: GetObjectInput,
1204    pub(crate) file_path: String,
1205}
1206
1207
1208impl InputDescriptor for GetObjectToFileInput {
1209    fn operation(&self) -> &str {
1210        "GetObjectToFile"
1211    }
1212    fn bucket(&self) -> Result<&str, TosError> {
1213        Ok(&self.inner.bucket)
1214    }
1215
1216    fn key(&self) -> Result<&str, TosError> {
1217        Ok(&self.inner.key)
1218    }
1219}
1220
1221impl<B> InputTranslator<B> for GetObjectToFileInput {
1222    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1223        if self.file_path == "" {
1224            return Err(TosError::client_error("empty file path"));
1225        }
1226        let mut request = self.inner.trans(config_holder)?;
1227        if request.request_context.is_some() {
1228            request.request_context.as_mut().unwrap().file_path = &self.file_path
1229        } else {
1230            let mut rc = RequestContext::default();
1231            rc.file_path = &self.file_path;
1232            request.request_context = Some(rc);
1233        }
1234        Ok(request)
1235    }
1236}
1237
1238impl Default for GetObjectToFileInput {
1239    fn default() -> Self {
1240        Self {
1241            inner: Default::default(),
1242            file_path: "".to_string(),
1243        }
1244    }
1245}
1246
1247impl DataTransferListener for GetObjectToFileInput {
1248    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
1249        &self.inner.data_transfer_listener
1250    }
1251
1252    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
1253        self.inner.data_transfer_listener = Some(listener.into());
1254    }
1255}
1256
1257impl GetObjectToFileInput {
1258    pub fn new(bucket: impl Into<String>, key: impl Into<String>, file_path: impl Into<String>) -> Self {
1259        let mut input = Self::default();
1260        input.inner.bucket = bucket.into();
1261        input.inner.key = key.into();
1262        input.file_path = file_path.into();
1263        input
1264    }
1265    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>, file_path: impl Into<String>) -> Self {
1266        let mut input = Self::default();
1267        input.inner.bucket = bucket.into();
1268        input.inner.key = key.into();
1269        input.inner.version_id = version_id.into();
1270        input.file_path = file_path.into();
1271        input
1272    }
1273    pub fn bucket(&self) -> &str {
1274        &self.inner.bucket
1275    }
1276    pub fn key(&self) -> &str {
1277        &self.inner.key
1278    }
1279    pub fn version_id(&self) -> &str {
1280        &self.inner.version_id
1281    }
1282    pub fn range_start(&self) -> i64 {
1283        self.inner.range_start
1284    }
1285    pub fn range_end(&self) -> i64 {
1286        self.inner.range_end
1287    }
1288    pub fn range(&self) -> &str {
1289        &self.inner.range
1290    }
1291    pub fn traffic_limit(&self) -> i64 {
1292        self.inner.traffic_limit
1293    }
1294    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
1295        &self.inner.rate_limiter
1296    }
1297    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1298        self.inner.bucket = bucket.into();
1299    }
1300    pub fn set_key(&mut self, key: impl Into<String>) {
1301        self.inner.key = key.into();
1302    }
1303    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
1304        self.inner.version_id = version_id.into();
1305    }
1306    pub fn set_range_start(&mut self, range_start: i64) {
1307        self.inner.range_start = range_start;
1308    }
1309    pub fn set_range_end(&mut self, range_end: i64) {
1310        self.inner.range_end = range_end;
1311    }
1312    pub fn set_range(&mut self, range: impl Into<String>) {
1313        self.inner.range = range.into();
1314    }
1315    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
1316        self.inner.traffic_limit = traffic_limit;
1317    }
1318    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
1319        self.inner.rate_limiter = Some(rate_limiter.into());
1320    }
1321}
1322#[derive(Default)]
1323pub struct GetObjectToFileOutput {
1324    pub(crate) content_range: String,
1325    pub(crate) head_object_output: HeadObjectOutput,
1326}
1327
1328impl Debug for GetObjectToFileOutput {
1329    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1330        write!(f, "({:?}, {})", self.head_object_output, self.content_range)
1331    }
1332}
1333
1334impl OutputParser for GetObjectToFileOutput {
1335    fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, meta: Meta) -> Result<Self, TosError> {
1336        let transfer_encoding = request_info.header.get(HEADER_TRANSFER_ENCODING_LOWER).map(|x| x.to_string());
1337        let head_object_output = HeadObjectOutput::parse_by_header(response.headers(), request_info, meta)?;
1338        let content_range = get_header_value(response.headers(), HEADER_CONTENT_RANGE);
1339        let mut target_crc64 = None;
1340        if request.enable_crc && !request.header.contains_key(HEADER_RANGE) &&
1341            (request.query.is_none() || !request.query.as_ref().unwrap().contains_key(QUERY_PROCESS)) {
1342            if let Some(te) = transfer_encoding {
1343                if te != "chunked" {
1344                    target_crc64 = Some(head_object_output.hash_crc64ecma);
1345                }
1346            } else {
1347                target_crc64 = Some(head_object_output.hash_crc64ecma);
1348            }
1349        }
1350        let mut crc64 = None;
1351        if target_crc64.is_some() {
1352            crc64 = Some(Arc::new(AtomicU64::new(0)));
1353        }
1354        let mut reader = MultifunctionalReader::with_target_crc64(response, crc64, head_object_output.content_length,
1355                                                                  &request, target_crc64);
1356        if let Some(ref rc) = request.request_context {
1357            if let Some(ref rl) = rc.rate_limiter {
1358                reader.set_rate_limiter(rl.clone());
1359            }
1360            if let Some(ref dts) = rc.data_transfer_listener {
1361                reader.set_data_transfer_listener(dts.clone());
1362                reader.inner.operation = request.operation.to_string();
1363                reader.inner.bucket = request.bucket.to_string();
1364                reader.inner.key = request.key.to_string();
1365                reader.inner.retry_count = request.retry_count;
1366            }
1367        }
1368        let file_path = &request.request_context.as_ref().unwrap().file_path;
1369        let path = Path::new(file_path);
1370        match path.parent() {
1371            None => return Err(TosError::client_error(format!("cannot get parent for path {}", file_path))),
1372            Some(p) => {
1373                if !p.exists() {
1374                    if let Err(e) = fs::create_dir_all(p) {
1375                        return Err(TosError::client_error_with_cause(format!("create dir for parent {} error", p.display()),
1376                                                                     GenericError::IoError(e.to_string())));
1377                    }
1378                }
1379            }
1380        }
1381        let final_file_path;
1382        if path.exists() && path.is_dir() {
1383            final_file_path = path.join(request.key);
1384        } else {
1385            final_file_path = path.to_path_buf();
1386        }
1387
1388        let temp_file_path = final_file_path.parent().unwrap().join(Uuid::now_v1(&UUID_NODE).to_string());
1389        match File::options().write(true).truncate(true).create(true).open(temp_file_path.clone()) {
1390            Err(e) => {
1391                return Err(TosError::client_error_with_cause("open file to write error", GenericError::IoError(e.to_string())))
1392            }
1393            Ok(mut fd) => {
1394                let mut data = [0u8; DEFAULT_READ_BUFFER_SIZE];
1395                loop {
1396                    match reader.read(&mut data) {
1397                        Err(re) => {
1398                            if re.kind() == ErrorKind::Interrupted {
1399                                continue;
1400                            }
1401                            let _ = fs::remove_file(temp_file_path);
1402                            return Err(TosError::client_error_with_cause("read content to write error", GenericError::IoError(re.to_string())));
1403                        }
1404                        Ok(n) => {
1405                            if n == 0 {
1406                                break;
1407                            }
1408                            if let Err(we) = fd.write_all(&data[..n]) {
1409                                let _ = fs::remove_file(temp_file_path);
1410                                return Err(TosError::client_error_with_cause("write data to file error", GenericError::IoError(we.to_string())));
1411                            }
1412                        }
1413                    }
1414                }
1415            }
1416        }
1417        if let Err(re) = fs::rename(temp_file_path.clone(), final_file_path) {
1418            let _ = fs::remove_file(temp_file_path);
1419            return Err(TosError::client_error_with_cause("rename file error", GenericError::IoError(re.to_string())));
1420        }
1421
1422        Ok(Self {
1423            content_range,
1424            head_object_output,
1425        })
1426    }
1427}
1428
1429impl RequestInfoTrait for GetObjectToFileOutput {
1430    fn request_id(&self) -> &str {
1431        &self.head_object_output.request_info.request_id
1432    }
1433
1434    fn id2(&self) -> &str {
1435        &self.head_object_output.request_info.id2
1436    }
1437
1438    fn status_code(&self) -> isize {
1439        self.head_object_output.request_info.status_code
1440    }
1441
1442    fn header(&self) -> &HashMap<String, String> {
1443        &self.head_object_output.request_info.header
1444    }
1445}
1446
1447impl GetObjectToFileOutput {
1448    pub fn request_id(&self) -> &str {
1449        &self.head_object_output.request_info.request_id
1450    }
1451
1452    pub fn id2(&self) -> &str {
1453        &self.head_object_output.request_info.id2
1454    }
1455
1456    pub fn status_code(&self) -> isize {
1457        self.head_object_output.request_info.status_code
1458    }
1459
1460    pub fn header(&self) -> &HashMap<String, String> {
1461        &self.head_object_output.request_info.header
1462    }
1463    pub fn content_range(&self) -> &str {
1464        &self.content_range
1465    }
1466    pub fn etag(&self) -> &str {
1467        &self.head_object_output.etag
1468    }
1469    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
1470        self.head_object_output.last_modified
1471    }
1472    pub fn last_modify_timestamp(&self) -> Option<DateTime<Utc>> {
1473        self.head_object_output.last_modify_timestamp
1474    }
1475    pub fn delete_marker(&self) -> bool {
1476        self.head_object_output.delete_marker
1477    }
1478    pub fn ssec_algorithm(&self) -> &str {
1479        &self.head_object_output.ssec_algorithm
1480    }
1481    pub fn ssec_key_md5(&self) -> &str {
1482        &self.head_object_output.ssec_key_md5
1483    }
1484    pub fn version_id(&self) -> &str {
1485        &self.head_object_output.version_id
1486    }
1487    pub fn website_redirect_location(&self) -> &str {
1488        &self.head_object_output.website_redirect_location
1489    }
1490    pub fn object_type(&self) -> &str {
1491        &self.head_object_output.object_type
1492    }
1493    pub fn hash_crc64ecma(&self) -> u64 {
1494        self.head_object_output.hash_crc64ecma
1495    }
1496    pub fn storage_class(&self) -> &Option<StorageClassType> {
1497        &self.head_object_output.storage_class
1498    }
1499    pub fn meta(&self) -> &HashMap<String, String> {
1500        &self.head_object_output.meta
1501    }
1502    pub fn content_length(&self) -> i64 {
1503        self.head_object_output.content_length
1504    }
1505    pub fn cache_control(&self) -> &str {
1506        &self.head_object_output.cache_control
1507    }
1508    pub fn content_disposition(&self) -> &str {
1509        &self.head_object_output.content_disposition
1510    }
1511    pub fn content_encoding(&self) -> &str {
1512        &self.head_object_output.content_encoding
1513    }
1514    pub fn content_language(&self) -> &str {
1515        &self.head_object_output.content_language
1516    }
1517    pub fn content_type(&self) -> &str {
1518        &self.head_object_output.content_type
1519    }
1520    pub fn expires(&self) -> Option<DateTime<Utc>> {
1521        self.head_object_output.expires
1522    }
1523    pub fn restore_info(&self) -> &Option<RestoreInfo> {
1524        &self.head_object_output.restore_info
1525    }
1526    pub fn server_side_encryption(&self) -> &str {
1527        &self.head_object_output.server_side_encryption
1528    }
1529    pub fn server_side_encryption_key_id(&self) -> &str {
1530        &self.head_object_output.server_side_encryption_key_id
1531    }
1532    pub fn replication_status(&self) -> &Option<ReplicationStatusType> {
1533        &self.head_object_output.replication_status
1534    }
1535    pub fn tagging_count(&self) -> isize {
1536        self.head_object_output.tagging_count
1537    }
1538}
1539
1540#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
1541pub struct GetObjectACLInput {
1542    pub(crate) generic_input: GenericInput,
1543    pub(crate) bucket: String,
1544    pub(crate) key: String,
1545    pub(crate) version_id: String,
1546}
1547
1548impl GetObjectACLInput {
1549    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
1550        Self {
1551            generic_input: Default::default(),
1552            bucket: bucket.into(),
1553            key: key.into(),
1554            version_id: "".to_string(),
1555        }
1556    }
1557    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
1558        Self {
1559            generic_input: Default::default(),
1560            bucket: bucket.into(),
1561            key: key.into(),
1562            version_id: version_id.into(),
1563        }
1564    }
1565    pub fn bucket(&self) -> &str {
1566        &self.bucket
1567    }
1568    pub fn key(&self) -> &str {
1569        &self.key
1570    }
1571    pub fn version_id(&self) -> &str {
1572        &self.version_id
1573    }
1574    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1575        self.bucket = bucket.into();
1576    }
1577    pub fn set_key(&mut self, key: impl Into<String>) {
1578        self.key = key.into();
1579    }
1580    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
1581        self.version_id = version_id.into();
1582    }
1583}
1584
1585impl InputDescriptor for GetObjectACLInput {
1586    fn operation(&self) -> &str {
1587        "GetObjectACL"
1588    }
1589    fn bucket(&self) -> Result<&str, TosError> {
1590        Ok(&self.bucket)
1591    }
1592
1593    fn key(&self) -> Result<&str, TosError> {
1594        Ok(&self.key)
1595    }
1596}
1597
1598impl<B> InputTranslator<B> for GetObjectACLInput {
1599    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1600        let mut request = self.trans_key()?;
1601        request.method = HttpMethodGet;
1602        let mut query = HashMap::with_capacity(2);
1603        query.insert("acl", "".to_string());
1604        map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
1605        request.query = Some(query);
1606        Ok(request)
1607    }
1608}
1609
1610#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
1611pub struct GetObjectACLOutput {
1612    #[serde(skip)]
1613    pub(crate) request_info: RequestInfo,
1614    #[serde(skip)]
1615    pub(crate) version_id: String,
1616    #[serde(default)]
1617    #[serde(rename = "Owner")]
1618    pub(crate) owner: Owner,
1619    #[serde(default)]
1620    #[serde(rename = "Grants")]
1621    pub(crate) grants: Vec<Grant>,
1622    #[serde(default)]
1623    #[serde(rename = "BucketOwnerEntrusted")]
1624    pub(crate) bucket_owner_entrusted: bool,
1625    #[serde(default)]
1626    #[serde(rename = "IsDefault")]
1627    pub(crate) is_default: bool,
1628}
1629
1630impl GetObjectACLOutput {
1631    pub fn version_id(&self) -> &str {
1632        &self.version_id
1633    }
1634    pub fn owner(&self) -> &Owner {
1635        &self.owner
1636    }
1637    pub fn grants(&self) -> &Vec<Grant> {
1638        &self.grants
1639    }
1640    pub fn bucket_owner_entrusted(&self) -> bool {
1641        self.bucket_owner_entrusted
1642    }
1643
1644    pub fn is_default(&self) -> bool {
1645        self.is_default
1646    }
1647}
1648
1649impl OutputParser for GetObjectACLOutput {
1650    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
1651        let mut result = parse_json::<Self>(response)?;
1652        result.version_id = get_header_value(response.headers(), HEADER_VERSION_ID);
1653        result.request_info = request_info;
1654        Ok(result)
1655    }
1656}
1657
1658#[derive(Debug, Clone, PartialEq, Default, IfConditionHeader, SsecHeader, GenericInput)]
1659pub struct HeadObjectInput {
1660    pub(crate) generic_input: GenericInput,
1661    pub(crate) bucket: String,
1662    pub(crate) key: String,
1663    pub(crate) version_id: String,
1664    pub(crate) if_match: String,
1665    pub(crate) if_modified_since: Option<DateTime<Utc>>,
1666    pub(crate) if_none_match: String,
1667    pub(crate) if_unmodified_since: Option<DateTime<Utc>>,
1668    pub(crate) ssec_algorithm: String,
1669    pub(crate) ssec_key: String,
1670    pub(crate) ssec_key_md5: String,
1671}
1672
1673impl HeadObjectInput {
1674    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
1675        let mut input = Self::default();
1676        input.bucket = bucket.into();
1677        input.key = key.into();
1678        input
1679    }
1680    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
1681        let mut input = Self::default();
1682        input.bucket = bucket.into();
1683        input.key = key.into();
1684        input.version_id = version_id.into();
1685        input
1686    }
1687    pub fn bucket(&self) -> &str {
1688        &self.bucket
1689    }
1690    pub fn key(&self) -> &str {
1691        &self.key
1692    }
1693    pub fn version_id(&self) -> &str {
1694        &self.version_id
1695    }
1696    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
1697        self.bucket = bucket.into();
1698    }
1699    pub fn set_key(&mut self, key: impl Into<String>) {
1700        self.key = key.into();
1701    }
1702    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
1703        self.version_id = version_id.into();
1704    }
1705}
1706
1707impl InputDescriptor for HeadObjectInput {
1708    fn operation(&self) -> &str {
1709        "HeadObject"
1710    }
1711
1712    fn bucket(&self) -> Result<&str, TosError> {
1713        Ok(&self.bucket)
1714    }
1715
1716    fn key(&self) -> Result<&str, TosError> {
1717        Ok(&self.key)
1718    }
1719}
1720
1721impl<B> InputTranslator<B> for HeadObjectInput {
1722    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
1723        let mut request = self.trans_key()?;
1724        request.method = HttpMethodHead;
1725        if self.version_id != "" {
1726            request.query = Some(HashMap::from([(QUERY_VERSION_ID, self.version_id.clone())]));
1727        }
1728        let header = &mut request.header;
1729        set_if_condition_header(header, self);
1730        set_ssec_header(header, "", self)?;
1731        Ok(request)
1732    }
1733}
1734
1735#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
1736pub struct HeadObjectOutput {
1737    pub(crate) request_info: RequestInfo,
1738    pub(crate) etag: String,
1739    pub(crate) last_modified: Option<DateTime<Utc>>,
1740    pub(crate) last_modify_timestamp: Option<DateTime<Utc>>,
1741    pub(crate) delete_marker: bool,
1742    pub(crate) ssec_algorithm: String,
1743    pub(crate) ssec_key_md5: String,
1744    pub(crate) version_id: String,
1745    pub(crate) website_redirect_location: String,
1746    pub(crate) object_type: String,
1747    pub(crate) hash_crc64ecma: u64,
1748    pub(crate) storage_class: Option<StorageClassType>,
1749    pub(crate) meta: HashMap<String, String>,
1750
1751    pub(crate) content_length: i64,
1752    pub(crate) cache_control: String,
1753    pub(crate) content_disposition: String,
1754    pub(crate) content_encoding: String,
1755    pub(crate) content_language: String,
1756    pub(crate) content_type: String,
1757    pub(crate) expires: Option<DateTime<Utc>>,
1758    pub(crate) restore_info: Option<RestoreInfo>,
1759
1760    pub(crate) server_side_encryption: String,
1761    pub(crate) server_side_encryption_key_id: String,
1762    pub(crate) replication_status: Option<ReplicationStatusType>,
1763    pub(crate) tagging_count: isize,
1764    pub(crate) symlink_target_size: i64,
1765    pub(crate) expiration: String,
1766    pub(crate) is_directory: bool,
1767}
1768
1769impl OutputParser for HeadObjectOutput {
1770    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, meta: Meta) -> Result<Self, TosError> {
1771        Self::parse_by_header(response.headers(), request_info, meta)
1772    }
1773}
1774
1775impl HeadObjectOutput {
1776    pub fn etag(&self) -> &str {
1777        &self.etag
1778    }
1779    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
1780        self.last_modified
1781    }
1782    pub fn last_modify_timestamp(&self) -> Option<DateTime<Utc>> {
1783        self.last_modify_timestamp
1784    }
1785    pub fn delete_marker(&self) -> bool {
1786        self.delete_marker
1787    }
1788    pub fn ssec_algorithm(&self) -> &str {
1789        &self.ssec_algorithm
1790    }
1791    pub fn ssec_key_md5(&self) -> &str {
1792        &self.ssec_key_md5
1793    }
1794    pub fn version_id(&self) -> &str {
1795        &self.version_id
1796    }
1797    pub fn website_redirect_location(&self) -> &str {
1798        &self.website_redirect_location
1799    }
1800    pub fn object_type(&self) -> &str {
1801        &self.object_type
1802    }
1803    pub fn hash_crc64ecma(&self) -> u64 {
1804        self.hash_crc64ecma
1805    }
1806    pub fn storage_class(&self) -> &Option<StorageClassType> {
1807        &self.storage_class
1808    }
1809    pub fn meta(&self) -> &HashMap<String, String> {
1810        &self.meta
1811    }
1812    pub fn content_length(&self) -> i64 {
1813        self.content_length
1814    }
1815    pub fn cache_control(&self) -> &str {
1816        &self.cache_control
1817    }
1818    pub fn content_disposition(&self) -> &str {
1819        &self.content_disposition
1820    }
1821    pub fn content_encoding(&self) -> &str {
1822        &self.content_encoding
1823    }
1824    pub fn content_language(&self) -> &str {
1825        &self.content_language
1826    }
1827    pub fn content_type(&self) -> &str {
1828        &self.content_type
1829    }
1830    pub fn expires(&self) -> Option<DateTime<Utc>> {
1831        self.expires
1832    }
1833    pub fn restore_info(&self) -> &Option<RestoreInfo> {
1834        &self.restore_info
1835    }
1836    pub fn server_side_encryption(&self) -> &str {
1837        &self.server_side_encryption
1838    }
1839    pub fn server_side_encryption_key_id(&self) -> &str {
1840        &self.server_side_encryption_key_id
1841    }
1842    pub fn replication_status(&self) -> &Option<ReplicationStatusType> {
1843        &self.replication_status
1844    }
1845    pub fn tagging_count(&self) -> isize {
1846        self.tagging_count
1847    }
1848    pub fn symlink_target_size(&self) -> i64 {
1849        self.symlink_target_size
1850    }
1851    pub fn expiration(&self) -> &str {
1852        &self.expiration
1853    }
1854
1855    pub fn is_directory(&self) -> bool {
1856        self.is_directory
1857    }
1858    pub(crate) fn parse_by_header(header: &HeaderMap, request_info: RequestInfo, meta: Meta) -> Result<Self, TosError> {
1859        let mut result = Self::default();
1860        result.etag = get_header_value(header, HEADER_ETAG);
1861        result.last_modified = parse_date_time_rfc1123(&get_header_value(header, HEADER_LAST_MODIFIED))?;
1862
1863        let ns = get_header_value_from_str::<u64>(header, HEADER_LAST_MODIFIED_NS, 0)?;
1864        if ns > 0 {
1865            if let Some(last_modified) = &result.last_modified {
1866                result.last_modify_timestamp = Some(last_modified.add(Duration::from_nanos(ns)));
1867            }
1868        }
1869
1870        result.delete_marker = get_header_value_str(header, HEADER_DELETE_MARKER) == TRUE;
1871        result.ssec_algorithm = get_header_value(header, HEADER_SSEC_ALGORITHM);
1872        result.ssec_key_md5 = get_header_value(header, HEADER_SSEC_KEY_MD5);
1873        result.version_id = get_header_value(header, HEADER_VERSION_ID);
1874        result.website_redirect_location = get_header_value(header, HEADER_WEBSITE_REDIRECT_LOCATION);
1875        result.object_type = get_header_value(header, HEADER_OBJECT_TYPE);
1876        result.hash_crc64ecma = get_header_value_from_str::<u64>(header, HEADER_HASH_CRC64ECMA, 0)?;
1877        result.content_length = get_header_value_from_str::<i64>(header, HEADER_CONTENT_LENGTH, -1)?;
1878        result.cache_control = get_header_value(header, HEADER_CACHE_CONTROL);
1879        result.content_disposition = get_header_value_url_decoded(header, HEADER_CONTENT_DISPOSITION);
1880        result.content_encoding = get_header_value(header, HEADER_CONTENT_ENCODING);
1881        result.content_language = get_header_value(header, HEADER_CONTENT_LANGUAGE);
1882        result.content_type = get_header_value(header, HEADER_CONTENT_TYPE);
1883        result.expires = parse_date_time_rfc1123(&get_header_value(header, HEADER_EXPIRES))?;
1884        let restore = get_header_value(header, HEADER_RESTORE);
1885        let restore_trim = restore.trim();
1886        if restore_trim != "" {
1887            if restore_trim == "ongoing-request=\"true\"" {
1888                result.restore_info = Some(RestoreInfo {
1889                    restore_status: RestoreStatus {
1890                        ongoing_request: true,
1891                        expiry_date: None,
1892                    },
1893                    restore_param: Some(RestoreParam {
1894                        request_date: parse_date_time_rfc1123(&get_header_value(header, HEADER_RESTORE_REQUEST_DATE))?,
1895                        expiry_days: get_header_value_from_str::<isize>(header, HEADER_RESTORE_EXPIRY_DAYS, 0)?,
1896                        tier: TierType::from(get_header_value_str(header, HEADER_RESTORE_TIER)),
1897                    }),
1898                });
1899            } else {
1900                let pattern = "ongoing-request=\"false\", expiry-date=\"";
1901                if let Some(idx) = restore_trim.find(pattern) {
1902                    let mut expiry_date = &restore_trim[idx..];
1903                    if expiry_date.len() > 0 && &expiry_date[expiry_date.len() - 1..] == "\"" {
1904                        expiry_date = &expiry_date[..expiry_date.len() - 1];
1905                    }
1906                    result.restore_info = Some(RestoreInfo {
1907                        restore_status: RestoreStatus {
1908                            ongoing_request: false,
1909                            expiry_date: parse_date_time_rfc1123(expiry_date)?,
1910                        },
1911                        restore_param: None,
1912                    });
1913                }
1914            }
1915        }
1916        result.server_side_encryption = get_header_value(header, HEADER_SERVER_SIDE_ENCRYPTION);
1917        result.server_side_encryption_key_id = get_header_value(header, HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID);
1918        result.storage_class = StorageClassType::from(get_header_value_str(header, HEADER_STORAGE_CLASS));
1919        result.replication_status = ReplicationStatusType::from(get_header_value_str(header, HEADER_REPLICATION_STATUS));
1920        result.tagging_count = get_header_value_from_str::<isize>(header, HEADER_TAGGING_COUNT, 0)?;
1921        result.symlink_target_size = get_header_value_from_str::<i64>(header, HEADER_SYMLINK_TARGET_SIZE, -1)?;
1922        result.expiration = get_header_value(header, HEADER_EXPIRATION);
1923        result.is_directory = get_header_value_str(header, HEADER_DIRECTORY) == TRUE;
1924        result.meta = meta;
1925        result.request_info = request_info;
1926        Ok(result)
1927    }
1928}
1929
1930#[derive(Debug, Clone, PartialEq, Default)]
1931pub struct RestoreInfo {
1932    pub(crate) restore_status: RestoreStatus,
1933    pub(crate) restore_param: Option<RestoreParam>,
1934}
1935
1936impl RestoreInfo {
1937    pub fn restore_status(&self) -> &RestoreStatus {
1938        &self.restore_status
1939    }
1940    pub fn restore_param(&self) -> &Option<RestoreParam> {
1941        &self.restore_param
1942    }
1943}
1944
1945#[derive(Debug, Clone, PartialEq, Default)]
1946pub struct RestoreStatus {
1947    pub(crate) ongoing_request: bool,
1948    pub(crate) expiry_date: Option<DateTime<Utc>>,
1949}
1950
1951impl RestoreStatus {
1952    pub fn ongoing_request(&self) -> bool {
1953        self.ongoing_request
1954    }
1955    pub fn expiry_date(&self) -> Option<DateTime<Utc>> {
1956        self.expiry_date
1957    }
1958}
1959
1960#[derive(Debug, Clone, PartialEq, Default)]
1961pub struct RestoreParam {
1962    pub(crate) request_date: Option<DateTime<Utc>>,
1963    pub(crate) expiry_days: isize,
1964    pub(crate) tier: Option<TierType>,
1965}
1966
1967impl RestoreParam {
1968    pub fn request_date(&self) -> Option<DateTime<Utc>> {
1969        self.request_date
1970    }
1971    pub fn expiry_days(&self) -> isize {
1972        self.expiry_days
1973    }
1974    pub fn tier(&self) -> &Option<TierType> {
1975        &self.tier
1976    }
1977}
1978
1979#[derive(Debug, Clone, HttpBasicHeader, AclHeader, MiscHeader, GenericInput)]
1980#[enable_content_length]
1981pub(crate) struct AppendObjectBasicInput {
1982    pub(crate) generic_input: GenericInput,
1983    pub(crate) bucket: String,
1984    pub(crate) key: String,
1985    pub(crate) offset: i64,
1986    pub(crate) content_length: i64,
1987    pub(crate) cache_control: String,
1988    pub(crate) content_disposition: String,
1989    pub(crate) content_encoding: String,
1990    pub(crate) content_language: String,
1991    pub(crate) content_type: String,
1992    pub(crate) expires: Option<DateTime<Utc>>,
1993    pub(crate) acl: Option<ACLType>,
1994    pub(crate) grant_full_control: String,
1995    pub(crate) grant_read: String,
1996    pub(crate) grant_read_acp: String,
1997    pub(crate) grant_write: String,
1998    pub(crate) grant_write_acp: String,
1999    pub(crate) meta: HashMap<String, String>,
2000    pub(crate) website_redirect_location: String,
2001    pub(crate) storage_class: Option<StorageClassType>,
2002    pub(crate) traffic_limit: i64,
2003    pub(crate) if_match: String,
2004    pub(crate) if_none_match: String,
2005    pub(crate) pre_hash_crc64ecma: u64,
2006    pub(crate) object_expires: i64,
2007    pub(crate) rate_limiter: Option<Arc<RateLimiter>>,
2008    pub(crate) data_transfer_listener: Option<Sender<DataTransferStatus>>,
2009    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
2010    pub(crate) notification_custom_parameters: String,
2011}
2012
2013
2014impl InputDescriptor for AppendObjectBasicInput {
2015    fn operation(&self) -> &str {
2016        "AppendObject"
2017    }
2018
2019    fn bucket(&self) -> Result<&str, TosError> {
2020        Ok(&self.bucket)
2021    }
2022
2023    fn key(&self) -> Result<&str, TosError> {
2024        Ok(&self.key)
2025    }
2026}
2027
2028impl<B> InputTranslator<B> for AppendObjectBasicInput {
2029    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
2030        if self.offset < 0
2031        {
2032            return Err(TosError::client_error("invalid offset for append object"));
2033        }
2034        let mut request = self.trans_key()?;
2035        request.method = HttpMethodPost;
2036        if let Some(ref rl) = self.rate_limiter {
2037            let mut rc = RequestContext::default();
2038            rc.rate_limiter = Some(rl.clone());
2039            request.request_context = Some(rc);
2040        }
2041
2042        if let Some(ref dts) = self.data_transfer_listener {
2043            if request.request_context.is_some() {
2044                request.request_context.as_mut().unwrap().data_transfer_listener = Some(dts.clone());
2045            } else {
2046                let mut rc = RequestContext::default();
2047                rc.data_transfer_listener = Some(dts.clone());
2048                request.request_context = Some(rc);
2049            }
2050        } else if let Some(ref adts) = self.async_data_transfer_listener {
2051            if request.request_context.is_some() {
2052                request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
2053            } else {
2054                let mut rc = RequestContext::default();
2055                rc.async_data_transfer_listener = Some(adts.clone());
2056                request.request_context = Some(rc);
2057            }
2058        }
2059
2060        if self.pre_hash_crc64ecma > 0 {
2061            if request.request_context.is_some() {
2062                request.request_context.as_mut().unwrap().init_crc64 = Some(self.pre_hash_crc64ecma);
2063            } else {
2064                let mut rc = RequestContext::default();
2065                rc.init_crc64 = Some(self.pre_hash_crc64ecma);
2066                request.request_context = Some(rc);
2067            }
2068        }
2069        let header = &mut request.header;
2070        set_http_basic_header(header, config_holder.disable_encoding_meta, self);
2071        set_acl_header(header, self);
2072        request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
2073        set_misc_header(header, self);
2074        if self.traffic_limit > 0 {
2075            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
2076        }
2077        map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
2078        map_insert(header, HEADER_IF_NONE_MATCH, &self.if_none_match);
2079        if self.object_expires >= 0 {
2080            header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
2081        }
2082        map_insert(header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
2083        let mut query = HashMap::with_capacity(2);
2084        query.insert("append", "".to_string());
2085        query.insert(QUERY_OFFSET, self.offset.to_string());
2086        request.query = Some(query);
2087        Ok(request)
2088    }
2089}
2090
2091impl Default for AppendObjectBasicInput {
2092    fn default() -> Self {
2093        Self {
2094            generic_input: Default::default(),
2095            bucket: "".to_string(),
2096            key: "".to_string(),
2097            offset: 0,
2098            content_length: -1,
2099            cache_control: "".to_string(),
2100            content_disposition: "".to_string(),
2101            content_encoding: "".to_string(),
2102            content_language: "".to_string(),
2103            content_type: "".to_string(),
2104            expires: None,
2105            acl: None,
2106            grant_full_control: "".to_string(),
2107            grant_read: "".to_string(),
2108            grant_read_acp: "".to_string(),
2109            grant_write: "".to_string(),
2110            grant_write_acp: "".to_string(),
2111            meta: Default::default(),
2112            website_redirect_location: "".to_string(),
2113            storage_class: None,
2114            traffic_limit: 0,
2115            if_match: "".to_string(),
2116            if_none_match: "".to_string(),
2117            pre_hash_crc64ecma: 0,
2118            object_expires: -1,
2119            rate_limiter: None,
2120            data_transfer_listener: None,
2121            async_data_transfer_listener: None,
2122            notification_custom_parameters: "".to_string(),
2123        }
2124    }
2125}
2126
2127#[derive(Debug, HttpBasicHeader, AclHeader, MiscHeader, GenericInput)]
2128#[enable_content_length]
2129#[handle_content]
2130#[use_inner]
2131pub struct AppendObjectInput<B>
2132{
2133    pub(crate) inner: AppendObjectBasicInput,
2134    pub(crate) content: Arc<RefCell<Option<B>>>,
2135}
2136
2137unsafe impl<B> Sync for AppendObjectInput<B> {}
2138unsafe impl<B> Send for AppendObjectInput<B> {}
2139
2140impl<B> InputDescriptor for AppendObjectInput<B>
2141{
2142    fn operation(&self) -> &str {
2143        "AppendObject"
2144    }
2145    fn bucket(&self) -> Result<&str, TosError> {
2146        Ok(&self.inner.bucket)
2147    }
2148
2149    fn key(&self) -> Result<&str, TosError> {
2150        Ok(&self.inner.key)
2151    }
2152}
2153
2154impl<B> InputTranslator<B> for AppendObjectInput<B>
2155{
2156    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
2157        let mut request = self.inner.trans(config_holder)?;
2158        request.operation = self.operation();
2159        request.body = self.content.take();
2160        Ok(request)
2161    }
2162}
2163
2164impl<B> AppendObjectInput<B>
2165{
2166    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
2167        let mut input = Self::default();
2168        input.inner.bucket = bucket.into();
2169        input.inner.key = key.into();
2170        input
2171    }
2172    pub fn new_with_offset(bucket: impl Into<String>, key: impl Into<String>, offset: i64) -> Self {
2173        let mut input = Self::default();
2174        input.inner.bucket = bucket.into();
2175        input.inner.key = key.into();
2176        input.inner.offset = offset;
2177        input
2178    }
2179    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl Into<B>) -> Self {
2180        let mut input = Self::default();
2181        input.inner.bucket = bucket.into();
2182        input.inner.key = key.into();
2183        input.set_content(content);
2184        input
2185    }
2186    pub fn new_with_offset_content(bucket: impl Into<String>, key: impl Into<String>, offset: i64, content: impl Into<B>) -> Self {
2187        let mut input = Self::default();
2188        input.inner.bucket = bucket.into();
2189        input.inner.key = key.into();
2190        input.inner.offset = offset;
2191        input.set_content(content);
2192        input
2193    }
2194    pub fn bucket(&self) -> &str {
2195        &self.inner.bucket
2196    }
2197    pub fn key(&self) -> &str {
2198        &self.inner.key
2199    }
2200    pub fn offset(&self) -> i64 {
2201        self.inner.offset
2202    }
2203    pub fn content(&self) -> Ref<Option<B>> {
2204        self.content.borrow()
2205    }
2206    pub fn meta(&self) -> &HashMap<String, String> {
2207        &self.inner.meta
2208    }
2209    pub fn traffic_limit(&self) -> i64 {
2210        self.inner.traffic_limit
2211    }
2212    pub fn if_match(&self) -> &str {
2213        &self.inner.if_match
2214    }
2215    pub fn if_none_match(&self) -> &str {
2216        &self.inner.if_none_match
2217    }
2218    pub fn pre_hash_crc64ecma(&self) -> u64 {
2219        self.inner.pre_hash_crc64ecma
2220    }
2221    pub fn object_expires(&self) -> i64 {
2222        self.inner.object_expires
2223    }
2224    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
2225        &self.inner.rate_limiter
2226    }
2227    pub fn notification_custom_parameters(&self) -> &str {
2228        &self.inner.notification_custom_parameters
2229    }
2230    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
2231        self.inner.bucket = bucket.into();
2232    }
2233    pub fn set_key(&mut self, key: impl Into<String>) {
2234        self.inner.key = key.into();
2235    }
2236    pub fn set_offset(&mut self, offset: i64) {
2237        self.inner.offset = offset;
2238    }
2239    pub fn set_content(&mut self, content: impl Into<B>) {
2240        self.content = Arc::new(RefCell::new(Some(content.into())));
2241    }
2242    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
2243        self.inner.meta = meta.into();
2244    }
2245    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
2246        self.inner.traffic_limit = traffic_limit;
2247    }
2248    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
2249        self.inner.if_match = if_match.into();
2250    }
2251    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
2252        self.inner.if_none_match = if_none_match.into();
2253    }
2254    pub fn set_pre_hash_crc64ecma(&mut self, pre_hash_crc64ecma: u64) {
2255        self.inner.pre_hash_crc64ecma = pre_hash_crc64ecma;
2256    }
2257    pub fn set_object_expires(&mut self, object_expires: i64) {
2258        self.inner.object_expires = object_expires;
2259    }
2260    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
2261        self.inner.rate_limiter = Some(rate_limiter.into());
2262    }
2263    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
2264        self.inner.notification_custom_parameters = notification_custom_parameters.into();
2265    }
2266}
2267
2268impl<B> Default for AppendObjectInput<B>
2269{
2270    fn default() -> Self {
2271        Self {
2272            inner: Default::default(),
2273            content: Arc::new(RefCell::new(None)),
2274        }
2275    }
2276}
2277
2278impl<B> DataTransferListener for AppendObjectInput<B> {
2279    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
2280        &self.inner.data_transfer_listener
2281    }
2282
2283    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
2284        self.inner.data_transfer_listener = Some(listener.into());
2285    }
2286}
2287
2288#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
2289pub struct AppendObjectOutput {
2290    pub(crate) request_info: RequestInfo,
2291    pub(crate) next_append_offset: i64,
2292    pub(crate) hash_crc64ecma: u64,
2293}
2294
2295impl OutputParser for AppendObjectOutput {
2296    fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
2297        let hash_crc64ecma = get_header_value_from_str::<u64>(response.headers(), HEADER_HASH_CRC64ECMA, 0)?;
2298        if let Some(ref rc) = request.request_context {
2299            if let Some(calc_hash_crc64ecma) = rc.crc64 {
2300                if calc_hash_crc64ecma != hash_crc64ecma {
2301                    return Err(TosError::client_error(format!("expect crc64 {hash_crc64ecma}, actual crc64 {calc_hash_crc64ecma}")));
2302                }
2303            }
2304        }
2305        let mut result = Self::default();
2306        result.next_append_offset = get_header_value_from_str::<i64>(response.headers(), HEADER_NEXT_APPEND_OFFSET, 0)?;
2307        result.hash_crc64ecma = hash_crc64ecma;
2308        result.request_info = request_info;
2309        Ok(result)
2310    }
2311}
2312
2313impl AppendObjectOutput {
2314    pub fn next_append_offset(&self) -> i64 {
2315        self.next_append_offset
2316    }
2317    pub fn hash_crc64ecma(&self) -> u64 {
2318        self.hash_crc64ecma
2319    }
2320}
2321
2322#[derive(Debug, Default, HttpBasicHeader, AclHeader, MiscHeader, GenericInput)]
2323#[enable_content_length]
2324#[use_inner]
2325pub struct AppendObjectFromBufferInput {
2326    pub(crate) inner: AppendObjectBasicInput,
2327    pub(crate) content: Option<MultiBytes>,
2328}
2329
2330impl InputDescriptor for AppendObjectFromBufferInput {
2331    fn operation(&self) -> &str {
2332        "AppendObjectFromBuffer"
2333    }
2334    fn bucket(&self) -> Result<&str, TosError> {
2335        Ok(&self.inner.bucket)
2336    }
2337    fn key(&self) -> Result<&str, TosError> {
2338        Ok(&self.inner.key)
2339    }
2340}
2341
2342impl<B> InputTranslator<B> for AppendObjectFromBufferInput
2343where
2344    B: BuildMultiBufferReader,
2345{
2346    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
2347        let mut request = self.inner.trans(config_holder)?;
2348        request.operation = self.operation();
2349        if let Some(content) = &self.content {
2350            let (body, len) = B::new(content.clone())?;
2351            request.body = Some(body);
2352            if self.inner.content_length < 0 {
2353                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
2354            }
2355        }
2356        Ok(request)
2357    }
2358}
2359
2360impl DataTransferListener for AppendObjectFromBufferInput {
2361    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
2362        &self.inner.data_transfer_listener
2363    }
2364
2365    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
2366        self.inner.data_transfer_listener = Some(listener.into());
2367    }
2368}
2369
2370impl AppendObjectFromBufferInput {
2371    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
2372        let mut input = Self::default();
2373        input.inner.bucket = bucket.into();
2374        input.inner.key = key.into();
2375        input
2376    }
2377    pub fn new_with_offset(bucket: impl Into<String>, key: impl Into<String>, offset: i64) -> Self {
2378        let mut input = Self::default();
2379        input.inner.bucket = bucket.into();
2380        input.inner.key = key.into();
2381        input.inner.offset = offset;
2382        input
2383    }
2384    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl AsRef<[u8]>) -> Self {
2385        let mut input = Self::default();
2386        input.inner.bucket = bucket.into();
2387        input.inner.key = key.into();
2388        input.set_content(content);
2389        input
2390    }
2391    pub fn new_with_offset_content(bucket: impl Into<String>, key: impl Into<String>, offset: i64, content: impl AsRef<[u8]>) -> Self {
2392        let mut input = Self::default();
2393        input.inner.bucket = bucket.into();
2394        input.inner.key = key.into();
2395        input.inner.offset = offset;
2396        input.set_content(content);
2397        input
2398    }
2399    pub fn bucket(&self) -> &str {
2400        &self.inner.bucket
2401    }
2402    pub fn key(&self) -> &str {
2403        &self.inner.key
2404    }
2405    pub fn offset(&self) -> i64 {
2406        self.inner.offset
2407    }
2408    pub fn content(&self) -> Option<impl Iterator<Item=&Bytes>> {
2409        match &self.content {
2410            None => None,
2411            Some(x) => Some(x.inner.iter()),
2412        }
2413    }
2414    pub fn meta(&self) -> &HashMap<String, String> {
2415        &self.inner.meta
2416    }
2417    pub fn traffic_limit(&self) -> i64 {
2418        self.inner.traffic_limit
2419    }
2420    pub fn if_match(&self) -> &str {
2421        &self.inner.if_match
2422    }
2423    pub fn if_none_match(&self) -> &str {
2424        &self.inner.if_none_match
2425    }
2426    pub fn pre_hash_crc64ecma(&self) -> u64 {
2427        self.inner.pre_hash_crc64ecma
2428    }
2429    pub fn object_expires(&self) -> i64 {
2430        self.inner.object_expires
2431    }
2432    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
2433        &self.inner.rate_limiter
2434    }
2435    pub fn notification_custom_parameters(&self) -> &str {
2436        &self.inner.notification_custom_parameters
2437    }
2438    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
2439        self.inner.bucket = bucket.into();
2440    }
2441    pub fn set_key(&mut self, key: impl Into<String>) {
2442        self.inner.key = key.into();
2443    }
2444    pub fn set_offset(&mut self, offset: i64) {
2445        self.inner.offset = offset;
2446    }
2447    pub fn set_content_with_bytes_list(&mut self, bytes_list: impl Iterator<Item=impl Into<Bytes>>) {
2448        let mut list = LinkedList::new();
2449        let mut size = 0;
2450        for item in bytes_list {
2451            let item = item.into();
2452            size += item.len();
2453            list.push_back(item);
2454        }
2455        self.content = Some(MultiBytes::new(list, size));
2456    }
2457    pub fn set_content(&mut self, content: impl AsRef<[u8]>) {
2458        let item = content.as_ref().to_owned();
2459        let size = item.len();
2460        let mut list = LinkedList::new();
2461        list.push_back(Bytes::from(item));
2462        self.content = Some(MultiBytes::new(list, size));
2463    }
2464    pub fn append_content(&mut self, content: impl AsRef<[u8]>) {
2465        if let Some(contents) = &mut self.content {
2466            contents.push(Bytes::from(content.as_ref().to_owned()));
2467        } else {
2468            self.set_content(content);
2469        }
2470    }
2471    pub fn set_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
2472        let item = content.into();
2473        let size = item.len();
2474        let mut list = LinkedList::new();
2475        list.push_back(Bytes::from(item));
2476        self.content = Some(MultiBytes::new(list, size));
2477    }
2478    pub fn append_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
2479        if let Some(contents) = &mut self.content {
2480            contents.push(Bytes::from(content.into()));
2481        } else {
2482            self.set_content_nocopy(content);
2483        }
2484    }
2485    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
2486        self.inner.meta = meta.into();
2487    }
2488    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
2489        self.inner.traffic_limit = traffic_limit;
2490    }
2491    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
2492        self.inner.if_match = if_match.into();
2493    }
2494    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
2495        self.inner.if_none_match = if_none_match.into();
2496    }
2497    pub fn set_pre_hash_crc64ecma(&mut self, pre_hash_crc64ecma: u64) {
2498        self.inner.pre_hash_crc64ecma = pre_hash_crc64ecma;
2499    }
2500    pub fn set_object_expires(&mut self, object_expires: i64) {
2501        self.inner.object_expires = object_expires;
2502    }
2503    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
2504        self.inner.rate_limiter = Some(rate_limiter.into());
2505    }
2506    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
2507        self.inner.notification_custom_parameters = notification_custom_parameters.into();
2508    }
2509}
2510#[derive(Debug, HttpBasicHeader, AclHeader, MiscHeader, GenericInput)]
2511#[enable_content_length]
2512#[use_inner]
2513pub struct AppendObjectFromFileInput {
2514    pub(crate) inner: AppendObjectBasicInput,
2515    pub(crate) file_path: String,
2516}
2517
2518impl InputDescriptor for AppendObjectFromFileInput {
2519    fn operation(&self) -> &str {
2520        "AppendObjectFromFile"
2521    }
2522
2523    fn bucket(&self) -> Result<&str, TosError> {
2524        Ok(&self.inner.bucket)
2525    }
2526
2527    fn key(&self) -> Result<&str, TosError> {
2528        Ok(&self.inner.key)
2529    }
2530}
2531
2532impl<B> InputTranslator<B> for AppendObjectFromFileInput
2533where
2534    B: BuildFileReader,
2535{
2536    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
2537        let mut request = self.inner.trans(config_holder)?;
2538        request.operation = self.operation();
2539        if self.file_path != "" {
2540            let (body, len) = B::new(&self.file_path)?;
2541            request.body = Some(body);
2542            if let Some(l) = len {
2543                if self.inner.content_length < 0 {
2544                    request.header.insert(HEADER_CONTENT_LENGTH, l.to_string());
2545                }
2546            }
2547        }
2548        Ok(request)
2549    }
2550}
2551
2552impl DataTransferListener for AppendObjectFromFileInput {
2553    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
2554        &self.inner.data_transfer_listener
2555    }
2556
2557    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
2558        self.inner.data_transfer_listener = Some(listener.into());
2559    }
2560}
2561
2562impl AppendObjectFromFileInput {
2563    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
2564        let mut input = Self::default();
2565        input.inner.bucket = bucket.into();
2566        input.inner.key = key.into();
2567        input
2568    }
2569    pub fn new_with_file_path(bucket: impl Into<String>, key: impl Into<String>, file_path: impl Into<String>) -> Self {
2570        let mut input = Self::default();
2571        input.inner.bucket = bucket.into();
2572        input.inner.key = key.into();
2573        input.file_path = file_path.into();
2574        input
2575    }
2576    pub fn new_with_offset(bucket: impl Into<String>, key: impl Into<String>, offset: i64) -> Self {
2577        let mut input = Self::default();
2578        input.inner.bucket = bucket.into();
2579        input.inner.key = key.into();
2580        input.inner.offset = offset;
2581        input
2582    }
2583    pub fn new_with_offset_file_path(bucket: impl Into<String>, key: impl Into<String>, offset: i64, file_path: impl Into<String>) -> Self {
2584        let mut input = Self::default();
2585        input.inner.bucket = bucket.into();
2586        input.inner.key = key.into();
2587        input.inner.offset = offset;
2588        input.file_path = file_path.into();
2589        input
2590    }
2591    pub fn bucket(&self) -> &str {
2592        &self.inner.bucket
2593    }
2594    pub fn key(&self) -> &str {
2595        &self.inner.key
2596    }
2597    pub fn file_path(&self) -> &str {
2598        &self.file_path
2599    }
2600    pub fn meta(&self) -> &HashMap<String, String> {
2601        &self.inner.meta
2602    }
2603    pub fn traffic_limit(&self) -> i64 {
2604        self.inner.traffic_limit
2605    }
2606    pub fn if_match(&self) -> &str {
2607        &self.inner.if_match
2608    }
2609    pub fn if_none_match(&self) -> &str {
2610        &self.inner.if_none_match
2611    }
2612    pub fn object_expires(&self) -> i64 {
2613        self.inner.object_expires
2614    }
2615    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
2616        &self.inner.rate_limiter
2617    }
2618    pub fn notification_custom_parameters(&self) -> &str {
2619        &self.inner.notification_custom_parameters
2620    }
2621    pub fn offset(&self) -> i64 {
2622        self.inner.offset
2623    }
2624    pub fn pre_hash_crc64ecma(&self) -> u64 {
2625        self.inner.pre_hash_crc64ecma
2626    }
2627    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
2628        self.inner.bucket = bucket.into();
2629    }
2630    pub fn set_key(&mut self, key: impl Into<String>) {
2631        self.inner.key = key.into();
2632    }
2633    pub fn set_file_path(&mut self, file_path: impl Into<String>) {
2634        self.file_path = file_path.into();
2635    }
2636    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
2637        self.inner.meta = meta.into();
2638    }
2639    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
2640        self.inner.traffic_limit = traffic_limit;
2641    }
2642    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
2643        self.inner.if_match = if_match.into();
2644    }
2645    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
2646        self.inner.if_none_match = if_none_match.into();
2647    }
2648    pub fn set_object_expires(&mut self, object_expires: i64) {
2649        self.inner.object_expires = object_expires;
2650    }
2651    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
2652        self.inner.rate_limiter = Some(rate_limiter.into());
2653    }
2654    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
2655        self.inner.notification_custom_parameters = notification_custom_parameters.into();
2656    }
2657    pub fn set_offset(&mut self, offset: i64) {
2658        self.inner.offset = offset;
2659    }
2660    pub fn set_pre_hash_crc64ecma(&mut self, pre_hash_crc64ecma: u64) {
2661        self.inner.pre_hash_crc64ecma = pre_hash_crc64ecma;
2662    }
2663}
2664
2665impl Default for AppendObjectFromFileInput {
2666    fn default() -> Self {
2667        Self {
2668            inner: Default::default(),
2669            file_path: "".to_string(),
2670        }
2671    }
2672}
2673
2674#[derive(Debug, Clone, PartialEq, ListCommonQuery, GenericInput)]
2675pub struct ListObjectsInput {
2676    pub(crate) generic_input: GenericInput,
2677    pub(crate) bucket: String,
2678    pub(crate) prefix: String,
2679    pub(crate) delimiter: String,
2680    pub(crate) marker: String,
2681    pub(crate) max_keys: isize,
2682    pub(crate) encoding_type: String,
2683    pub(crate) fetch_meta: bool,
2684}
2685
2686impl Default for ListObjectsInput {
2687    fn default() -> Self {
2688        Self {
2689            generic_input: Default::default(),
2690            bucket: "".to_string(),
2691            prefix: "".to_string(),
2692            delimiter: "".to_string(),
2693            marker: "".to_string(),
2694            max_keys: -1,
2695            encoding_type: "".to_string(),
2696            fetch_meta: false,
2697        }
2698    }
2699}
2700
2701impl ListObjectsInput {
2702    pub fn new(bucket: impl Into<String>) -> Self {
2703        let mut input = Self::default();
2704        input.bucket = bucket.into();
2705        input
2706    }
2707
2708    pub fn bucket(&self) -> &str {
2709        &self.bucket
2710    }
2711    pub fn marker(&self) -> &str {
2712        &self.marker
2713    }
2714    pub fn max_keys(&self) -> isize {
2715        self.max_keys
2716    }
2717    pub fn fetch_meta(&self) -> bool {
2718        self.fetch_meta
2719    }
2720    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
2721        self.bucket = bucket.into();
2722    }
2723    pub fn set_marker(&mut self, marker: impl Into<String>) {
2724        self.marker = marker.into();
2725    }
2726    pub fn set_max_keys(&mut self, max_keys: isize) {
2727        self.max_keys = max_keys;
2728    }
2729    pub fn set_fetch_meta(&mut self, fetch_meta: bool) {
2730        self.fetch_meta = fetch_meta;
2731    }
2732}
2733
2734impl InputDescriptor for ListObjectsInput {
2735    fn operation(&self) -> &str {
2736        "ListObjects"
2737    }
2738    fn bucket(&self) -> Result<&str, TosError> {
2739        Ok(&self.bucket)
2740    }
2741}
2742
2743impl<B> InputTranslator<B> for ListObjectsInput {
2744    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
2745        let mut request = self.trans_bucket()?;
2746        request.method = HttpMethodGet;
2747        let mut query = HashMap::with_capacity(6);
2748        set_list_common_query(&mut query, self);
2749        map_insert(&mut query, QUERY_MARKER, &self.marker);
2750        if self.max_keys >= 0 {
2751            query.insert(QUERY_MAX_KEYS, self.max_keys.to_string());
2752        }
2753        if self.fetch_meta {
2754            query.insert(QUERY_FETCH_META, self.fetch_meta.to_string());
2755        }
2756        request.query = Some(query);
2757        Ok(request)
2758    }
2759}
2760
2761#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
2762pub struct ListObjectsOutput {
2763    #[serde(skip)]
2764    pub(crate) request_info: RequestInfo,
2765    #[serde(default)]
2766    #[serde(rename = "Name")]
2767    pub(crate) name: String,
2768    #[serde(default)]
2769    #[serde(rename = "Prefix")]
2770    pub(crate) prefix: String,
2771    #[serde(default)]
2772    #[serde(rename = "Marker")]
2773    pub(crate) marker: String,
2774    #[serde(default)]
2775    #[serde(rename = "MaxKeys")]
2776    pub(crate) max_keys: isize,
2777    #[serde(default)]
2778    #[serde(rename = "Delimiter")]
2779    pub(crate) delimiter: String,
2780    #[serde(default)]
2781    #[serde(rename = "IsTruncated")]
2782    pub(crate) is_truncated: bool,
2783    #[serde(default)]
2784    #[serde(rename = "EncodingType")]
2785    pub(crate) encoding_type: String,
2786    #[serde(default)]
2787    #[serde(rename = "NextMarker")]
2788    pub(crate) next_marker: String,
2789    #[serde(default)]
2790    #[serde(rename = "CommonPrefixes")]
2791    pub(crate) common_prefixes: Vec<ListedCommonPrefix>,
2792    #[serde(default)]
2793    #[serde(rename = "Contents")]
2794    pub(crate) contents: Vec<ListedObject>,
2795}
2796
2797impl OutputParser for ListObjectsOutput {
2798    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
2799        let mut result = parse_json::<Self>(response)?;
2800        for content in &mut result.contents {
2801            if let Some(x) = content.last_modified_string.take() {
2802                content.last_modified = parse_date_time_iso8601(&x)?;
2803            }
2804
2805            if let Some(x) = content.user_meta.take() {
2806                let mut meta = HashMap::with_capacity(x.len());
2807                for item in x {
2808                    if let Ok(dk) = urlencoding::decode(&item.key[HEADER_PREFIX_META.len()..]) {
2809                        if let Ok(dv) = urlencoding::decode(item.value.as_str()) {
2810                            meta.insert(dk.to_string(), dv.to_string());
2811                        }
2812                    }
2813                }
2814                content.meta = meta;
2815            }
2816        }
2817        for common_prefix in &mut result.common_prefixes {
2818            if let Some(x) = common_prefix.last_modified_string.take() {
2819                common_prefix.last_modified = parse_date_time_iso8601(&x)?;
2820            }
2821        }
2822        result.request_info = request_info;
2823        Ok(result)
2824    }
2825}
2826
2827impl ListObjectsOutput {
2828    pub fn name(&self) -> &str {
2829        &self.name
2830    }
2831    pub fn prefix(&self) -> &str {
2832        &self.prefix
2833    }
2834    pub fn marker(&self) -> &str {
2835        &self.marker
2836    }
2837    pub fn max_keys(&self) -> isize {
2838        self.max_keys
2839    }
2840    pub fn delimiter(&self) -> &str {
2841        &self.delimiter
2842    }
2843    pub fn is_truncated(&self) -> bool {
2844        self.is_truncated
2845    }
2846    pub fn encoding_type(&self) -> &str {
2847        &self.encoding_type
2848    }
2849    pub fn next_marker(&self) -> &str {
2850        &self.next_marker
2851    }
2852    pub fn common_prefixes(&self) -> &Vec<ListedCommonPrefix> {
2853        &self.common_prefixes
2854    }
2855    pub fn contents(&self) -> &Vec<ListedObject> {
2856        &self.contents
2857    }
2858}
2859
2860
2861#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
2862pub struct ListedObject {
2863    #[serde(default)]
2864    #[serde(rename = "Key")]
2865    pub(crate) key: String,
2866    #[serde(default)]
2867    #[serde(rename = "LastModified")]
2868    pub(crate) last_modified_string: Option<String>,
2869    #[serde(skip)]
2870    pub(crate) last_modified: Option<DateTime<Utc>>,
2871    #[serde(default)]
2872    #[serde(rename = "ETag")]
2873    pub(crate) etag: String,
2874    #[serde(default)]
2875    #[serde(rename = "Size")]
2876    pub(crate) size: i64,
2877    #[serde(default)]
2878    #[serde(rename = "Owner")]
2879    pub(crate) owner: Owner,
2880    #[serde(default)]
2881    #[serde(rename = "StorageClass")]
2882    pub(crate) storage_class: Option<StorageClassType>,
2883    #[serde(default)]
2884    #[serde(rename = "HashCrc64ecma")]
2885    pub(crate) hash_crc64ecma: String,
2886    #[serde(default)]
2887    #[serde(rename = "UserMeta")]
2888    pub(crate) user_meta: Option<Vec<MetaItem>>,
2889    #[serde(skip)]
2890    pub(crate) meta: HashMap<String, String>,
2891    #[serde(default)]
2892    #[serde(rename = "Type")]
2893    pub(crate) object_type: String,
2894    #[serde(default)]
2895    #[serde(rename = "HashCrc32c")]
2896    pub(crate) hash_crc32c: Option<String>,
2897}
2898
2899#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
2900pub(crate) struct MetaItem {
2901    #[serde(default)]
2902    #[serde(rename = "Key")]
2903    pub(crate) key: String,
2904    #[serde(default)]
2905    #[serde(rename = "Value")]
2906    pub(crate) value: String,
2907}
2908
2909
2910impl ListedObject {
2911    pub fn key(&self) -> &str {
2912        &self.key
2913    }
2914    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
2915        self.last_modified
2916    }
2917    pub fn etag(&self) -> &str {
2918        &self.etag
2919    }
2920    pub fn size(&self) -> i64 {
2921        self.size
2922    }
2923    pub fn owner(&self) -> &Owner {
2924        &self.owner
2925    }
2926    pub fn storage_class(&self) -> &Option<StorageClassType> {
2927        &self.storage_class
2928    }
2929    pub fn hash_crc64ecma(&self) -> u64 {
2930        self.hash_crc64ecma.parse::<u64>().unwrap_or_else(|_| 0)
2931    }
2932    pub fn meta(&self) -> &HashMap<String, String> {
2933        &self.meta
2934    }
2935
2936    pub fn object_type(&self) -> &str {
2937        &self.object_type
2938    }
2939
2940    pub fn hash_crc32c(&self) -> Option<u32> {
2941        match &self.hash_crc32c {
2942            None => None,
2943            Some(hash_crc32c) => Some(hash_crc32c.parse::<u32>().unwrap_or_else(|_| 0))
2944        }
2945    }
2946}
2947
2948#[derive(Debug, Clone, PartialEq, ListCommonQuery, GenericInput)]
2949pub struct ListObjectsType2Input {
2950    pub(crate) generic_input: GenericInput,
2951    pub(crate) bucket: String,
2952    pub(crate) prefix: String,
2953    pub(crate) delimiter: String,
2954    pub(crate) start_after: String,
2955    pub(crate) continuation_token: String,
2956    pub(crate) max_keys: isize,
2957    pub(crate) encoding_type: String,
2958    pub(crate) list_only_once: bool,
2959    pub(crate) fetch_meta: bool,
2960}
2961
2962impl Default for ListObjectsType2Input {
2963    fn default() -> Self {
2964        Self {
2965            generic_input: Default::default(),
2966            bucket: "".to_string(),
2967            prefix: "".to_string(),
2968            delimiter: "".to_string(),
2969            start_after: "".to_string(),
2970            continuation_token: "".to_string(),
2971            max_keys: -1,
2972            encoding_type: "".to_string(),
2973            list_only_once: false,
2974            fetch_meta: false,
2975        }
2976    }
2977}
2978
2979impl ListObjectsType2Input {
2980    pub fn new(bucket: impl Into<String>) -> Self {
2981        let mut input = Self::default();
2982        input.bucket = bucket.into();
2983        input
2984    }
2985    pub fn bucket(&self) -> &str {
2986        &self.bucket
2987    }
2988    pub fn start_after(&self) -> &str {
2989        &self.start_after
2990    }
2991    pub fn continuation_token(&self) -> &str {
2992        &self.continuation_token
2993    }
2994    pub fn max_keys(&self) -> isize {
2995        self.max_keys
2996    }
2997    pub fn list_only_once(&self) -> bool {
2998        self.list_only_once
2999    }
3000    pub fn fetch_meta(&self) -> bool {
3001        self.fetch_meta
3002    }
3003    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
3004        self.bucket = bucket.into();
3005    }
3006    pub fn set_start_after(&mut self, start_after: impl Into<String>) {
3007        self.start_after = start_after.into();
3008    }
3009    pub fn set_continuation_token(&mut self, continuation_token: impl Into<String>) {
3010        self.continuation_token = continuation_token.into();
3011    }
3012    pub fn set_max_keys(&mut self, max_keys: isize) {
3013        self.max_keys = max_keys;
3014    }
3015    pub fn set_list_only_once(&mut self, list_only_once: bool) {
3016        self.list_only_once = list_only_once;
3017    }
3018    pub fn set_fetch_meta(&mut self, fetch_meta: bool) {
3019        self.fetch_meta = fetch_meta;
3020    }
3021}
3022
3023impl InputDescriptor for ListObjectsType2Input {
3024    fn operation(&self) -> &str {
3025        "ListObjectsType2"
3026    }
3027    fn bucket(&self) -> Result<&str, TosError> {
3028        Ok(&self.bucket)
3029    }
3030}
3031
3032impl<B> InputTranslator<B> for ListObjectsType2Input {
3033    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
3034        let mut request = self.trans_bucket()?;
3035        request.method = HttpMethodGet;
3036        let mut query = HashMap::with_capacity(9);
3037        set_list_common_query(&mut query, self);
3038        map_insert(&mut query, QUERY_START_AFTER, &self.start_after);
3039        map_insert(&mut query, QUERY_CONTINUATION_TOKEN, &self.continuation_token);
3040        if self.max_keys >= 0 {
3041            query.insert(QUERY_MAX_KEYS, self.max_keys.to_string());
3042        }
3043        if self.fetch_meta {
3044            query.insert(QUERY_FETCH_META, self.fetch_meta.to_string());
3045        }
3046        query.insert("list-type", 2.to_string());
3047        query.insert(QUERY_FETCH_OWNER, true.to_string());
3048        request.query = Some(query);
3049        Ok(request)
3050    }
3051}
3052
3053
3054#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
3055pub struct ListObjectsType2Output {
3056    #[serde(skip)]
3057    pub(crate) request_info: RequestInfo,
3058    #[serde(default)]
3059    #[serde(rename = "Name")]
3060    pub(crate) name: String,
3061    #[serde(default)]
3062    #[serde(rename = "Prefix")]
3063    pub(crate) prefix: String,
3064    #[serde(default)]
3065    #[serde(rename = "StartAfter")]
3066    pub(crate) start_after: String,
3067    #[serde(default)]
3068    #[serde(rename = "ContinuationToken")]
3069    pub(crate) continuation_token: String,
3070    #[serde(default)]
3071    #[serde(rename = "MaxKeys")]
3072    pub(crate) max_keys: isize,
3073    #[serde(default)]
3074    #[serde(rename = "Delimiter")]
3075    pub(crate) delimiter: String,
3076    #[serde(default)]
3077    #[serde(rename = "IsTruncated")]
3078    pub(crate) is_truncated: bool,
3079    #[serde(default)]
3080    #[serde(rename = "EncodingType")]
3081    pub(crate) encoding_type: String,
3082    #[serde(default)]
3083    #[serde(rename = "KeyCount")]
3084    pub(crate) key_count: isize,
3085    #[serde(default)]
3086    #[serde(rename = "NextContinuationToken")]
3087    pub(crate) next_continuation_token: String,
3088    #[serde(default)]
3089    #[serde(rename = "CommonPrefixes")]
3090    pub(crate) common_prefixes: Vec<ListedCommonPrefix>,
3091    #[serde(default)]
3092    #[serde(rename = "Contents")]
3093    pub(crate) contents: Vec<ListedObject>,
3094}
3095
3096impl ListObjectsType2Output {
3097    pub fn name(&self) -> &str {
3098        &self.name
3099    }
3100    pub fn prefix(&self) -> &str {
3101        &self.prefix
3102    }
3103    pub fn start_after(&self) -> &str {
3104        &self.start_after
3105    }
3106    pub fn continuation_token(&self) -> &str {
3107        &self.continuation_token
3108    }
3109    pub fn max_keys(&self) -> isize {
3110        self.max_keys
3111    }
3112    pub fn delimiter(&self) -> &str {
3113        &self.delimiter
3114    }
3115    pub fn is_truncated(&self) -> bool {
3116        self.is_truncated
3117    }
3118    pub fn encoding_type(&self) -> &str {
3119        &self.encoding_type
3120    }
3121    pub fn key_count(&self) -> isize {
3122        self.key_count
3123    }
3124    pub fn next_continuation_token(&self) -> &str {
3125        &self.next_continuation_token
3126    }
3127    pub fn common_prefixes(&self) -> &Vec<ListedCommonPrefix> {
3128        &self.common_prefixes
3129    }
3130    pub fn contents(&self) -> &Vec<ListedObject> {
3131        &self.contents
3132    }
3133}
3134
3135impl OutputParser for ListObjectsType2Output {
3136    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
3137        let mut result = parse_json::<Self>(response)?;
3138        for content in &mut result.contents {
3139            if let Some(x) = content.last_modified_string.take() {
3140                content.last_modified = parse_date_time_iso8601(&x)?;
3141            }
3142
3143            if let Some(x) = content.user_meta.take() {
3144                let mut meta = HashMap::with_capacity(x.len());
3145                for item in x {
3146                    if let Ok(dk) = urlencoding::decode(&item.key[HEADER_PREFIX_META.len()..]) {
3147                        if let Ok(dv) = urlencoding::decode(item.value.as_str()) {
3148                            meta.insert(dk.to_string(), dv.to_string());
3149                        }
3150                    }
3151                }
3152                content.meta = meta;
3153            }
3154        }
3155        for common_prefix in &mut result.common_prefixes {
3156            if let Some(x) = common_prefix.last_modified_string.take() {
3157                common_prefix.last_modified = parse_date_time_iso8601(&x)?;
3158            }
3159        }
3160        result.request_info = request_info;
3161        Ok(result)
3162    }
3163}
3164
3165#[derive(Debug, Clone, PartialEq, ListCommonQuery, GenericInput)]
3166pub struct ListObjectVersionsInput {
3167    pub(crate) generic_input: GenericInput,
3168    pub(crate) bucket: String,
3169    pub(crate) prefix: String,
3170    pub(crate) delimiter: String,
3171    pub(crate) key_marker: String,
3172    pub(crate) version_id_marker: String,
3173    pub(crate) max_keys: isize,
3174    pub(crate) encoding_type: String,
3175    pub(crate) fetch_meta: bool,
3176}
3177
3178impl Default for ListObjectVersionsInput {
3179    fn default() -> Self {
3180        Self {
3181            generic_input: Default::default(),
3182            bucket: "".to_string(),
3183            prefix: "".to_string(),
3184            delimiter: "".to_string(),
3185            key_marker: "".to_string(),
3186            version_id_marker: "".to_string(),
3187            max_keys: -1,
3188            encoding_type: "".to_string(),
3189            fetch_meta: false,
3190        }
3191    }
3192}
3193
3194impl ListObjectVersionsInput {
3195    pub fn new(bucket: impl Into<String>) -> Self {
3196        let mut input = Self::default();
3197        input.bucket = bucket.into();
3198        input
3199    }
3200    pub fn bucket(&self) -> &str {
3201        &self.bucket
3202    }
3203    pub fn key_marker(&self) -> &str {
3204        &self.key_marker
3205    }
3206    pub fn version_id_marker(&self) -> &str {
3207        &self.version_id_marker
3208    }
3209    pub fn max_keys(&self) -> isize {
3210        self.max_keys
3211    }
3212    pub fn fetch_meta(&self) -> bool {
3213        self.fetch_meta
3214    }
3215    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
3216        self.bucket = bucket.into();
3217    }
3218    pub fn set_key_marker(&mut self, key_marker: impl Into<String>) {
3219        self.key_marker = key_marker.into();
3220    }
3221    pub fn set_version_id_marker(&mut self, version_id_marker: impl Into<String>) {
3222        self.version_id_marker = version_id_marker.into();
3223    }
3224    pub fn set_max_keys(&mut self, max_keys: isize) {
3225        self.max_keys = max_keys;
3226    }
3227    pub fn set_fetch_meta(&mut self, fetch_meta: bool) {
3228        self.fetch_meta = fetch_meta;
3229    }
3230}
3231
3232impl InputDescriptor for ListObjectVersionsInput {
3233    fn operation(&self) -> &str {
3234        "ListObjectVersions"
3235    }
3236    fn bucket(&self) -> Result<&str, TosError> {
3237        Ok(&self.bucket)
3238    }
3239}
3240
3241impl<B> InputTranslator<B> for ListObjectVersionsInput {
3242    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
3243        let mut request = self.trans_bucket()?;
3244        request.method = HttpMethodGet;
3245        let mut query = HashMap::with_capacity(8);
3246        query.insert("versions", "".to_string());
3247        set_list_common_query(&mut query, self);
3248        map_insert(&mut query, QUERY_KEY_MARKER, &self.key_marker);
3249        map_insert(&mut query, QUERY_VERSION_ID_MARKER, &self.version_id_marker);
3250        if self.max_keys >= 0 {
3251            query.insert(QUERY_MAX_KEYS, self.max_keys.to_string());
3252        }
3253        if self.fetch_meta {
3254            query.insert(QUERY_FETCH_META, self.fetch_meta.to_string());
3255        }
3256        request.query = Some(query);
3257        Ok(request)
3258    }
3259}
3260
3261#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
3262pub struct ListObjectVersionsOutput {
3263    #[serde(skip)]
3264    pub(crate) request_info: RequestInfo,
3265    #[serde(default)]
3266    #[serde(rename = "Name")]
3267    pub(crate) name: String,
3268    #[serde(default)]
3269    #[serde(rename = "Prefix")]
3270    pub(crate) prefix: String,
3271    #[serde(default)]
3272    #[serde(rename = "KeyMarker")]
3273    pub(crate) key_marker: String,
3274    #[serde(default)]
3275    #[serde(rename = "VersionIdMarker")]
3276    pub(crate) version_id_marker: String,
3277    #[serde(default)]
3278    #[serde(rename = "MaxKeys")]
3279    pub(crate) max_keys: isize,
3280    #[serde(default)]
3281    #[serde(rename = "Delimiter")]
3282    pub(crate) delimiter: String,
3283    #[serde(default)]
3284    #[serde(rename = "IsTruncated")]
3285    pub(crate) is_truncated: bool,
3286    #[serde(default)]
3287    #[serde(rename = "EncodingType")]
3288    pub(crate) encoding_type: String,
3289    #[serde(default)]
3290    #[serde(rename = "NextKeyMarker")]
3291    pub(crate) next_key_marker: String,
3292    #[serde(default)]
3293    #[serde(rename = "NextVersionIdMarker")]
3294    pub(crate) next_version_id_marker: String,
3295    #[serde(default)]
3296    #[serde(rename = "CommonPrefixes")]
3297    pub(crate) common_prefixes: Vec<ListedCommonPrefix>,
3298    #[serde(default)]
3299    #[serde(rename = "Versions")]
3300    pub(crate) versions: Vec<ListedObjectVersion>,
3301    #[serde(default)]
3302    #[serde(rename = "DeleteMarkers")]
3303    pub(crate) delete_markers: Vec<ListedDeleteMarker>,
3304}
3305
3306impl ListObjectVersionsOutput {
3307    pub fn name(&self) -> &str {
3308        &self.name
3309    }
3310    pub fn prefix(&self) -> &str {
3311        &self.prefix
3312    }
3313    pub fn key_marker(&self) -> &str {
3314        &self.key_marker
3315    }
3316    pub fn version_id_marker(&self) -> &str {
3317        &self.version_id_marker
3318    }
3319    pub fn max_keys(&self) -> isize {
3320        self.max_keys
3321    }
3322    pub fn delimiter(&self) -> &str {
3323        &self.delimiter
3324    }
3325    pub fn is_truncated(&self) -> bool {
3326        self.is_truncated
3327    }
3328    pub fn encoding_type(&self) -> &str {
3329        &self.encoding_type
3330    }
3331    pub fn next_key_marker(&self) -> &str {
3332        &self.next_key_marker
3333    }
3334    pub fn next_version_id_marker(&self) -> &str {
3335        &self.next_version_id_marker
3336    }
3337    pub fn common_prefixes(&self) -> &Vec<ListedCommonPrefix> {
3338        &self.common_prefixes
3339    }
3340    pub fn versions(&self) -> &Vec<ListedObjectVersion> {
3341        &self.versions
3342    }
3343    pub fn delete_markers(&self) -> &Vec<ListedDeleteMarker> {
3344        &self.delete_markers
3345    }
3346}
3347
3348impl OutputParser for ListObjectVersionsOutput {
3349    fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
3350        let mut result = parse_json::<Self>(response)?;
3351        for version in &mut result.versions {
3352            if let Some(x) = version.last_modified_string.take() {
3353                version.last_modified = parse_date_time_iso8601(&x)?;
3354            }
3355
3356            if let Some(x) = version.user_meta.take() {
3357                let mut meta = HashMap::with_capacity(x.len());
3358                for item in x {
3359                    if let Ok(dk) = urlencoding::decode(&item.key[HEADER_PREFIX_META.len()..]) {
3360                        if let Ok(dv) = urlencoding::decode(item.value.as_str()) {
3361                            meta.insert(dk.to_string(), dv.to_string());
3362                        }
3363                    }
3364                }
3365                version.meta = meta;
3366            }
3367        }
3368
3369        for delete_marker in &mut result.delete_markers {
3370            if let Some(x) = delete_marker.last_modified_string.take() {
3371                delete_marker.last_modified = parse_date_time_iso8601(&x)?;
3372            }
3373        }
3374
3375        result.request_info = request_info;
3376        Ok(result)
3377    }
3378}
3379
3380#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
3381pub struct ListedObjectVersion {
3382    #[serde(default)]
3383    #[serde(rename = "Key")]
3384    pub(crate) key: String,
3385    #[serde(default)]
3386    #[serde(rename = "LastModified")]
3387    pub(crate) last_modified_string: Option<String>,
3388    #[serde(skip)]
3389    pub(crate) last_modified: Option<DateTime<Utc>>,
3390    #[serde(default)]
3391    #[serde(rename = "ETag")]
3392    pub(crate) etag: String,
3393    #[serde(default)]
3394    #[serde(rename = "IsLatest")]
3395    pub(crate) is_latest: bool,
3396    #[serde(default)]
3397    #[serde(rename = "Size")]
3398    pub(crate) size: i64,
3399    #[serde(default)]
3400    #[serde(rename = "Owner")]
3401    pub(crate) owner: Owner,
3402    #[serde(default)]
3403    #[serde(rename = "StorageClass")]
3404    pub(crate) storage_class: Option<StorageClassType>,
3405    #[serde(default)]
3406    #[serde(rename = "VersionId")]
3407    pub(crate) version_id: String,
3408    #[serde(default)]
3409    #[serde(rename = "HashCrc64ecma")]
3410    pub(crate) hash_crc64ecma: String,
3411    #[serde(default)]
3412    #[serde(rename = "UserMeta")]
3413    pub(crate) user_meta: Option<Vec<MetaItem>>,
3414    #[serde(skip)]
3415    pub(crate) meta: HashMap<String, String>,
3416    #[serde(default)]
3417    #[serde(rename = "Type")]
3418    pub(crate) object_type: String,
3419}
3420
3421impl ListedObjectVersion {
3422    pub fn key(&self) -> &str {
3423        &self.key
3424    }
3425    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
3426        self.last_modified
3427    }
3428    pub fn etag(&self) -> &str {
3429        &self.etag
3430    }
3431    pub fn is_latest(&self) -> bool {
3432        self.is_latest
3433    }
3434    pub fn size(&self) -> i64 {
3435        self.size
3436    }
3437    pub fn owner(&self) -> &Owner {
3438        &self.owner
3439    }
3440    pub fn storage_class(&self) -> &Option<StorageClassType> {
3441        &self.storage_class
3442    }
3443    pub fn version_id(&self) -> &str {
3444        &self.version_id
3445    }
3446    pub fn hash_crc64ecma(&self) -> u64 {
3447        self.hash_crc64ecma.parse::<u64>().unwrap_or_else(|_| 0)
3448    }
3449    pub fn meta(&self) -> &HashMap<String, String> {
3450        &self.meta
3451    }
3452    pub fn object_type(&self) -> &str {
3453        &self.object_type
3454    }
3455}
3456
3457#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
3458pub struct ListedDeleteMarker {
3459    #[serde(default)]
3460    #[serde(rename = "Key")]
3461    pub(crate) key: String,
3462    #[serde(default)]
3463    #[serde(rename = "LastModified")]
3464    pub(crate) last_modified_string: Option<String>,
3465    #[serde(skip)]
3466    pub(crate) last_modified: Option<DateTime<Utc>>,
3467    #[serde(default)]
3468    #[serde(rename = "IsLatest")]
3469    pub(crate) is_latest: bool,
3470    #[serde(default)]
3471    #[serde(rename = "Owner")]
3472    pub(crate) owner: Owner,
3473    #[serde(default)]
3474    #[serde(rename = "VersionId")]
3475    pub(crate) version_id: String,
3476}
3477
3478impl ListedDeleteMarker {
3479    pub fn key(&self) -> &str {
3480        &self.key
3481    }
3482    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
3483        self.last_modified
3484    }
3485    pub fn is_latest(&self) -> bool {
3486        self.is_latest
3487    }
3488    pub fn owner(&self) -> &Owner {
3489        &self.owner
3490    }
3491    pub fn version_id(&self) -> &str {
3492        &self.version_id
3493    }
3494}
3495
3496#[derive(
3497    Debug,
3498    Clone,
3499    HttpBasicHeader,
3500    AclHeader,
3501    SseHeader,
3502    SsecHeader,
3503    MiscHeader,
3504    CallbackHeader,
3505    GenericInput
3506)]
3507#[enable_content_length]
3508pub(crate) struct PutObjectBasicInput {
3509    pub(crate) generic_input: GenericInput,
3510    pub(crate) bucket: String,
3511    pub(crate) key: String,
3512    pub(crate) content_md5: String,
3513    pub(crate) content_sha256: String,
3514    pub(crate) content_length: i64,
3515    pub(crate) cache_control: String,
3516    pub(crate) content_disposition: String,
3517    pub(crate) content_encoding: String,
3518    pub(crate) content_language: String,
3519    pub(crate) content_type: String,
3520    pub(crate) expires: Option<DateTime<Utc>>,
3521
3522    pub(crate) acl: Option<ACLType>,
3523    pub(crate) grant_full_control: String,
3524    pub(crate) grant_read: String,
3525    pub(crate) grant_read_acp: String,
3526    pub(crate) grant_write: String,
3527    pub(crate) grant_write_acp: String,
3528
3529    pub(crate) ssec_algorithm: String,
3530    pub(crate) ssec_key: String,
3531    pub(crate) ssec_key_md5: String,
3532    pub(crate) server_side_encryption: String,
3533    pub(crate) server_side_encryption_key_id: String,
3534
3535    pub(crate) meta: HashMap<String, String>,
3536    pub(crate) website_redirect_location: String,
3537    pub(crate) storage_class: Option<StorageClassType>,
3538    pub(crate) traffic_limit: i64,
3539    pub(crate) callback: String,
3540    pub(crate) callback_var: String,
3541    pub(crate) forbid_overwrite: bool,
3542    pub(crate) if_match: String,
3543    pub(crate) if_none_match: String,
3544
3545    pub(crate) tagging: String,
3546    pub(crate) object_expires: i64,
3547    pub(crate) rate_limiter: Option<Arc<RateLimiter>>,
3548    pub(crate) data_transfer_listener: Option<Sender<DataTransferStatus>>,
3549    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
3550    pub(crate) notification_custom_parameters: String,
3551}
3552
3553impl Default for PutObjectBasicInput {
3554    fn default() -> Self {
3555        Self {
3556            generic_input: Default::default(),
3557            bucket: "".to_string(),
3558            key: "".to_string(),
3559            content_md5: "".to_string(),
3560            content_sha256: "".to_string(),
3561            content_length: -1,
3562            cache_control: "".to_string(),
3563            content_disposition: "".to_string(),
3564            content_encoding: "".to_string(),
3565            content_language: "".to_string(),
3566            content_type: "".to_string(),
3567            expires: None,
3568            acl: None,
3569            grant_full_control: "".to_string(),
3570            grant_read: "".to_string(),
3571            grant_read_acp: "".to_string(),
3572            grant_write: "".to_string(),
3573            grant_write_acp: "".to_string(),
3574            ssec_algorithm: "".to_string(),
3575            ssec_key: "".to_string(),
3576            ssec_key_md5: "".to_string(),
3577            server_side_encryption: "".to_string(),
3578            server_side_encryption_key_id: "".to_string(),
3579            meta: Default::default(),
3580            website_redirect_location: "".to_string(),
3581            storage_class: None,
3582            traffic_limit: 0,
3583            callback: "".to_string(),
3584            callback_var: "".to_string(),
3585            forbid_overwrite: false,
3586            if_match: "".to_string(),
3587            if_none_match: "".to_string(),
3588            tagging: "".to_string(),
3589            object_expires: -1,
3590            rate_limiter: None,
3591            data_transfer_listener: None,
3592            async_data_transfer_listener: None,
3593            notification_custom_parameters: "".to_string(),
3594        }
3595    }
3596}
3597
3598impl InputDescriptor for PutObjectBasicInput {
3599    fn operation(&self) -> &str {
3600        "PutObject"
3601    }
3602    fn bucket(&self) -> Result<&str, TosError> {
3603        Ok(&self.bucket)
3604    }
3605
3606    fn key(&self) -> Result<&str, TosError> {
3607        Ok(&self.key)
3608    }
3609}
3610
3611impl<B> InputTranslator<B> for PutObjectBasicInput {
3612    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
3613        let mut request = self.trans_key()?;
3614        request.method = HttpMethodPut;
3615
3616        if let Some(ref rl) = self.rate_limiter {
3617            let mut rc = RequestContext::default();
3618            rc.rate_limiter = Some(rl.clone());
3619            request.request_context = Some(rc);
3620        }
3621
3622        if let Some(ref dts) = self.data_transfer_listener {
3623            if request.request_context.is_some() {
3624                request.request_context.as_mut().unwrap().data_transfer_listener = Some(dts.clone());
3625            } else {
3626                let mut rc = RequestContext::default();
3627                rc.data_transfer_listener = Some(dts.clone());
3628                request.request_context = Some(rc);
3629            }
3630        } else if let Some(ref adts) = self.async_data_transfer_listener {
3631            if request.request_context.is_some() {
3632                request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
3633            } else {
3634                let mut rc = RequestContext::default();
3635                rc.async_data_transfer_listener = Some(adts.clone());
3636                request.request_context = Some(rc);
3637            }
3638        }
3639
3640        let header = &mut request.header;
3641        set_http_basic_header(header, config_holder.disable_encoding_meta, self);
3642        set_acl_header(header, self);
3643        set_sse_header(header, self)?;
3644        set_ssec_header(header, &self.server_side_encryption, self)?;
3645        request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
3646        set_misc_header(header, self);
3647        set_callback_header(header, self);
3648        map_insert(header, HEADER_CONTENT_MD5, &self.content_md5);
3649        map_insert(header, HEADER_CONTENT_SHA256, &self.content_sha256);
3650        if self.forbid_overwrite {
3651            header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
3652        }
3653        if self.traffic_limit > 0 {
3654            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
3655        }
3656        map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
3657        map_insert(header, HEADER_IF_NONE_MATCH, &self.if_none_match);
3658
3659        if self.tagging != "" {
3660            header.insert(HEADER_TAGGING, self.tagging.clone());
3661        }
3662        if self.object_expires >= 0 {
3663            header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
3664        }
3665        map_insert(header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
3666        Ok(request)
3667    }
3668}
3669
3670// AclHeader
3671#[derive(
3672    Debug,
3673    HttpBasicHeader,
3674    AclHeader,
3675    SseHeader,
3676    SsecHeader,
3677    MiscHeader,
3678    CallbackHeader,
3679    GenericInput
3680)]
3681#[enable_content_length]
3682#[handle_content]
3683#[use_inner]
3684pub struct PutObjectInput<B>
3685{
3686    pub(crate) inner: PutObjectBasicInput,
3687    pub(crate) content: Arc<RefCell<Option<B>>>,
3688}
3689
3690unsafe impl<B> Sync for PutObjectInput<B> {}
3691
3692unsafe impl<B> Send for PutObjectInput<B> {}
3693
3694impl<B> InputDescriptor for PutObjectInput<B>
3695{
3696    fn operation(&self) -> &str {
3697        "PutObject"
3698    }
3699    fn bucket(&self) -> Result<&str, TosError> {
3700        Ok(&self.inner.bucket)
3701    }
3702
3703    fn key(&self) -> Result<&str, TosError> {
3704        Ok(&self.inner.key)
3705    }
3706}
3707
3708impl<B> InputTranslator<B> for PutObjectInput<B>
3709{
3710    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
3711        let mut request = self.inner.trans(config_holder)?;
3712        request.operation = self.operation();
3713        request.body = self.content.take();
3714        Ok(request)
3715    }
3716}
3717
3718impl<B> Default for PutObjectInput<B>
3719{
3720    fn default() -> Self {
3721        Self {
3722            inner: Default::default(),
3723            content: Arc::new(RefCell::new(None)),
3724        }
3725    }
3726}
3727
3728impl<B> DataTransferListener for PutObjectInput<B> {
3729    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
3730        &self.inner.data_transfer_listener
3731    }
3732
3733    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
3734        self.inner.data_transfer_listener = Some(listener.into());
3735    }
3736}
3737
3738impl<B> PutObjectInput<B>
3739{
3740    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
3741        let mut input = Self::default();
3742        input.inner.bucket = bucket.into();
3743        input.inner.key = key.into();
3744        input
3745    }
3746    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl Into<B>) -> Self {
3747        let mut input = Self::default();
3748        input.inner.bucket = bucket.into();
3749        input.inner.key = key.into();
3750        input.set_content(content);
3751        input
3752    }
3753    pub fn bucket(&self) -> &str {
3754        &self.inner.bucket
3755    }
3756    pub fn key(&self) -> &str {
3757        &self.inner.key
3758    }
3759    pub fn content(&self) -> Ref<Option<B>> {
3760        self.content.borrow()
3761    }
3762    pub fn content_md5(&self) -> &str {
3763        &self.inner.content_md5
3764    }
3765    pub fn content_sha256(&self) -> &str {
3766        &self.inner.content_sha256
3767    }
3768    pub fn meta(&self) -> &HashMap<String, String> {
3769        &self.inner.meta
3770    }
3771    pub fn traffic_limit(&self) -> i64 {
3772        self.inner.traffic_limit
3773    }
3774    pub fn forbid_overwrite(&self) -> bool {
3775        self.inner.forbid_overwrite
3776    }
3777    pub fn if_match(&self) -> &str {
3778        &self.inner.if_match
3779    }
3780    pub fn if_none_match(&self) -> &str {
3781        &self.inner.if_none_match
3782    }
3783    pub fn tagging(&self) -> &str {
3784        &self.inner.tagging
3785    }
3786    pub fn object_expires(&self) -> i64 {
3787        self.inner.object_expires
3788    }
3789    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
3790        &self.inner.rate_limiter
3791    }
3792    pub fn notification_custom_parameters(&mut self) -> &str {
3793        &self.inner.notification_custom_parameters
3794    }
3795    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
3796        self.inner.bucket = bucket.into();
3797    }
3798    pub fn set_key(&mut self, key: impl Into<String>) {
3799        self.inner.key = key.into();
3800    }
3801    pub fn set_content(&mut self, content: impl Into<B>) {
3802        self.content = Arc::new(RefCell::new(Some(content.into())));
3803    }
3804    pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
3805        self.inner.content_md5 = content_md5.into();
3806    }
3807    pub fn set_content_sha256(&mut self, content_sha256: impl Into<String>) {
3808        self.inner.content_sha256 = content_sha256.into();
3809    }
3810    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
3811        self.inner.meta = meta.into();
3812    }
3813    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
3814        self.inner.traffic_limit = traffic_limit;
3815    }
3816    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
3817        self.inner.forbid_overwrite = forbid_overwrite;
3818    }
3819    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
3820        self.inner.if_match = if_match.into();
3821    }
3822    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
3823        self.inner.if_none_match = if_none_match.into();
3824    }
3825    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
3826        self.inner.tagging = tagging.into();
3827    }
3828    pub fn set_object_expires(&mut self, object_expires: i64) {
3829        self.inner.object_expires = object_expires;
3830    }
3831    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
3832        self.inner.rate_limiter = Some(rate_limiter.into());
3833    }
3834    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
3835        self.inner.notification_custom_parameters = notification_custom_parameters.into();
3836    }
3837}
3838
3839
3840#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
3841pub struct PutObjectOutput {
3842    pub(crate) request_info: RequestInfo,
3843    pub(crate) etag: String,
3844    pub(crate) version_id: String,
3845    pub(crate) ssec_algorithm: String,
3846    pub(crate) ssec_key_md5: String,
3847    pub(crate) hash_crc64ecma: u64,
3848    pub(crate) callback_result: String,
3849    pub(crate) server_side_encryption: String,
3850    pub(crate) server_side_encryption_key_id: String,
3851}
3852
3853impl OutputParser for PutObjectOutput {
3854    fn parse_by_ref<B>(request: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
3855        let hash_crc64ecma = get_header_value_from_str::<u64>(response.headers(), HEADER_HASH_CRC64ECMA, 0)?;
3856        if let Some(ref rc) = request.request_context {
3857            if let Some(calc_hash_crc64ecma) = rc.crc64 {
3858                if calc_hash_crc64ecma != hash_crc64ecma {
3859                    return Err(TosError::client_error(format!("expect crc64 {hash_crc64ecma}, actual crc64 {calc_hash_crc64ecma}")));
3860                }
3861            }
3862        }
3863
3864        let mut result = Self::default();
3865        if get_map_value_str(&request.header, HEADER_CALLBACK) != "" { // callback
3866            let buf = read_response(response)?;
3867            if request_info.status_code == 203 {
3868                if let Ok(error_response) = parse_json_by_buf::<ErrorResponse>(buf.as_slice()) {
3869                    return Err(TosError::server_error_with_code(error_response.code, error_response.ec, error_response.key, error_response.message,
3870                                                                error_response.host_id, error_response.resource, request_info));
3871                }
3872            }
3873            result.callback_result = parse_response_string_by_buf(buf)?;
3874        }
3875        result.etag = get_header_value(response.headers(), HEADER_ETAG);
3876        result.version_id = get_header_value(response.headers(), HEADER_VERSION_ID);
3877        result.ssec_algorithm = get_header_value(response.headers(), HEADER_SSEC_ALGORITHM);
3878        result.ssec_key_md5 = get_header_value(response.headers(), HEADER_SSEC_KEY_MD5);
3879        result.hash_crc64ecma = hash_crc64ecma;
3880        result.server_side_encryption = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION);
3881        result.server_side_encryption_key_id = get_header_value(response.headers(), HEADER_SERVER_SIDE_ENCRYPTION_KMS_KEY_ID);
3882        result.request_info = request_info;
3883        Ok(result)
3884    }
3885}
3886
3887impl PutObjectOutput {
3888    pub fn etag(&self) -> &str {
3889        &self.etag
3890    }
3891    pub fn version_id(&self) -> &str {
3892        &self.version_id
3893    }
3894    pub fn ssec_algorithm(&self) -> &str {
3895        &self.ssec_algorithm
3896    }
3897    pub fn ssec_key_md5(&self) -> &str {
3898        &self.ssec_key_md5
3899    }
3900    pub fn hash_crc64ecma(&self) -> u64 {
3901        self.hash_crc64ecma
3902    }
3903    pub fn callback_result(&self) -> &str {
3904        &self.callback_result
3905    }
3906    pub fn server_side_encryption(&self) -> &str {
3907        &self.server_side_encryption
3908    }
3909    pub fn server_side_encryption_key_id(&self) -> &str {
3910        &self.server_side_encryption_key_id
3911    }
3912}
3913
3914#[derive(
3915    Debug,
3916    HttpBasicHeader,
3917    AclHeader,
3918    SseHeader,
3919    SsecHeader,
3920    MiscHeader,
3921    CallbackHeader,
3922    GenericInput
3923)]
3924#[enable_content_length]
3925#[use_inner]
3926pub struct PutObjectFromBufferInput {
3927    pub(crate) inner: PutObjectBasicInput,
3928    pub(crate) content: Option<MultiBytes>,
3929}
3930
3931impl InputDescriptor for PutObjectFromBufferInput {
3932    fn operation(&self) -> &str {
3933        "PutObjectFromBuffer"
3934    }
3935    fn bucket(&self) -> Result<&str, TosError> {
3936        Ok(&self.inner.bucket)
3937    }
3938
3939    fn key(&self) -> Result<&str, TosError> {
3940        Ok(&self.inner.key)
3941    }
3942}
3943
3944impl<B> InputTranslator<B> for PutObjectFromBufferInput
3945where
3946    B: BuildMultiBufferReader,
3947{
3948    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
3949        let mut request = self.inner.trans(config_holder)?;
3950        request.operation = self.operation();
3951        if let Some(content) = &self.content {
3952            let (body, len) = B::new(content.clone())?;
3953            request.body = Some(body);
3954            if self.inner.content_length < 0 {
3955                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
3956            }
3957        }
3958        Ok(request)
3959    }
3960}
3961
3962impl PutObjectFromBufferInput {
3963    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
3964        let mut input = Self::default();
3965        input.inner.bucket = bucket.into();
3966        input.inner.key = key.into();
3967        input
3968    }
3969    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl AsRef<[u8]>) -> Self {
3970        let mut input = Self::default();
3971        input.inner.bucket = bucket.into();
3972        input.inner.key = key.into();
3973        input.set_content(content);
3974        input
3975    }
3976    pub fn bucket(&self) -> &str {
3977        &self.inner.bucket
3978    }
3979    pub fn key(&self) -> &str {
3980        &self.inner.key
3981    }
3982    pub fn content(&self) -> Option<impl Iterator<Item=&Bytes>> {
3983        match &self.content {
3984            None => None,
3985            Some(x) => Some(x.inner.iter()),
3986        }
3987    }
3988    pub fn content_md5(&self) -> &str {
3989        &self.inner.content_md5
3990    }
3991    pub fn content_sha256(&self) -> &str {
3992        &self.inner.content_sha256
3993    }
3994    pub fn meta(&self) -> &HashMap<String, String> {
3995        &self.inner.meta
3996    }
3997    pub fn traffic_limit(&self) -> i64 {
3998        self.inner.traffic_limit
3999    }
4000    pub fn forbid_overwrite(&self) -> bool {
4001        self.inner.forbid_overwrite
4002    }
4003    pub fn if_match(&self) -> &str {
4004        &self.inner.if_match
4005    }
4006    pub fn if_none_match(&self) -> &str {
4007        &self.inner.if_none_match
4008    }
4009    pub fn tagging(&self) -> &str {
4010        &self.inner.tagging
4011    }
4012    pub fn object_expires(&self) -> i64 {
4013        self.inner.object_expires
4014    }
4015    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
4016        &self.inner.rate_limiter
4017    }
4018    pub fn notification_custom_parameters(&mut self) -> &str {
4019        &self.inner.notification_custom_parameters
4020    }
4021    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4022        self.inner.bucket = bucket.into();
4023    }
4024    pub fn set_key(&mut self, key: impl Into<String>) {
4025        self.inner.key = key.into();
4026    }
4027    pub fn set_content_with_bytes_list(&mut self, bytes_list: impl Iterator<Item=impl Into<Bytes>>) {
4028        let mut list = LinkedList::new();
4029        let mut size = 0;
4030        for item in bytes_list {
4031            let item = item.into();
4032            size += item.len();
4033            list.push_back(item);
4034        }
4035        self.content = Some(MultiBytes::new(list, size));
4036    }
4037    pub fn set_content(&mut self, content: impl AsRef<[u8]>) {
4038        let item = content.as_ref().to_owned();
4039        let size = item.len();
4040        let mut list = LinkedList::new();
4041        list.push_back(Bytes::from(item));
4042        self.content = Some(MultiBytes::new(list, size));
4043    }
4044    pub fn append_content(&mut self, content: impl AsRef<[u8]>) {
4045        if let Some(contents) = &mut self.content {
4046            contents.push(Bytes::from(content.as_ref().to_owned()));
4047        } else {
4048            self.set_content(content);
4049        }
4050    }
4051    pub fn set_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
4052        let item = content.into();
4053        let size = item.len();
4054        let mut list = LinkedList::new();
4055        list.push_back(Bytes::from(item));
4056        self.content = Some(MultiBytes::new(list, size));
4057    }
4058
4059    pub fn append_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
4060        if let Some(contents) = &mut self.content {
4061            contents.push(Bytes::from(content.into()));
4062        } else {
4063            self.set_content_nocopy(content);
4064        }
4065    }
4066
4067    pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
4068        self.inner.content_md5 = content_md5.into();
4069    }
4070    pub fn set_content_sha256(&mut self, content_sha256: impl Into<String>) {
4071        self.inner.content_sha256 = content_sha256.into();
4072    }
4073    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
4074        self.inner.meta = meta.into();
4075    }
4076    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
4077        self.inner.traffic_limit = traffic_limit;
4078    }
4079    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
4080        self.inner.forbid_overwrite = forbid_overwrite;
4081    }
4082    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
4083        self.inner.if_match = if_match.into();
4084    }
4085    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
4086        self.inner.if_none_match = if_none_match.into();
4087    }
4088    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
4089        self.inner.tagging = tagging.into();
4090    }
4091    pub fn set_object_expires(&mut self, object_expires: i64) {
4092        self.inner.object_expires = object_expires;
4093    }
4094    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
4095        self.inner.rate_limiter = Some(rate_limiter.into());
4096    }
4097    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
4098        self.inner.notification_custom_parameters = notification_custom_parameters.into();
4099    }
4100}
4101
4102impl Default for PutObjectFromBufferInput {
4103    fn default() -> Self {
4104        Self {
4105            inner: Default::default(),
4106            content: None,
4107        }
4108    }
4109}
4110
4111impl DataTransferListener for PutObjectFromBufferInput {
4112    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
4113        &self.inner.data_transfer_listener
4114    }
4115
4116    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
4117        self.inner.data_transfer_listener = Some(listener.into());
4118    }
4119}
4120
4121#[derive(
4122    Debug,
4123    HttpBasicHeader,
4124    AclHeader,
4125    SseHeader,
4126    SsecHeader,
4127    MiscHeader,
4128    CallbackHeader,
4129    GenericInput
4130)]
4131#[enable_content_length]
4132#[use_inner]
4133pub struct PutObjectFromFileInput {
4134    pub(crate) inner: PutObjectBasicInput,
4135    pub(crate) file_path: String,
4136}
4137
4138impl InputDescriptor for PutObjectFromFileInput {
4139    fn operation(&self) -> &str {
4140        "PutObjectFromFile"
4141    }
4142
4143    fn bucket(&self) -> Result<&str, TosError> {
4144        Ok(&self.inner.bucket)
4145    }
4146
4147    fn key(&self) -> Result<&str, TosError> {
4148        Ok(&self.inner.key)
4149    }
4150}
4151
4152impl<B> InputTranslator<B> for PutObjectFromFileInput
4153where
4154    B: BuildFileReader,
4155{
4156    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4157        let mut request = self.inner.trans(config_holder)?;
4158        request.operation = self.operation();
4159        if self.file_path != "" {
4160            let (body, len) = B::new(&self.file_path)?;
4161            request.body = Some(body);
4162            if let Some(l) = len {
4163                if self.inner.content_length < 0 {
4164                    request.header.insert(HEADER_CONTENT_LENGTH, l.to_string());
4165                }
4166            }
4167        }
4168        Ok(request)
4169    }
4170}
4171
4172impl DataTransferListener for PutObjectFromFileInput {
4173    fn data_transfer_listener(&self) -> &Option<Sender<DataTransferStatus>> {
4174        &self.inner.data_transfer_listener
4175    }
4176
4177    fn set_data_transfer_listener(&mut self, listener: impl Into<Sender<DataTransferStatus>>) {
4178        self.inner.data_transfer_listener = Some(listener.into());
4179    }
4180}
4181
4182impl PutObjectFromFileInput {
4183    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4184        let mut input = Self::default();
4185        input.inner.bucket = bucket.into();
4186        input.inner.key = key.into();
4187        input
4188    }
4189    pub fn new_with_file_path(bucket: impl Into<String>, key: impl Into<String>, file_path: impl Into<String>) -> Self {
4190        let mut input = Self::default();
4191        input.inner.bucket = bucket.into();
4192        input.inner.key = key.into();
4193        input.file_path = file_path.into();
4194        input
4195    }
4196    pub fn bucket(&self) -> &str {
4197        &self.inner.bucket
4198    }
4199    pub fn key(&self) -> &str {
4200        &self.inner.key
4201    }
4202    pub fn file_path(&self) -> &str {
4203        &self.file_path
4204    }
4205    pub fn content_md5(&self) -> &str {
4206        &self.inner.content_md5
4207    }
4208    pub fn content_sha256(&self) -> &str {
4209        &self.inner.content_sha256
4210    }
4211    pub fn meta(&self) -> &HashMap<String, String> {
4212        &self.inner.meta
4213    }
4214    pub fn traffic_limit(&self) -> i64 {
4215        self.inner.traffic_limit
4216    }
4217    pub fn forbid_overwrite(&self) -> bool {
4218        self.inner.forbid_overwrite
4219    }
4220    pub fn if_match(&self) -> &str {
4221        &self.inner.if_match
4222    }
4223    pub fn if_none_match(&self) -> &str {
4224        &self.inner.if_none_match
4225    }
4226    pub fn tagging(&self) -> &str {
4227        &self.inner.tagging
4228    }
4229    pub fn object_expires(&self) -> i64 {
4230        self.inner.object_expires
4231    }
4232    pub fn rate_limiter(&self) -> &Option<Arc<RateLimiter>> {
4233        &self.inner.rate_limiter
4234    }
4235    pub fn notification_custom_parameters(&mut self) -> &str {
4236        &self.inner.notification_custom_parameters
4237    }
4238    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4239        self.inner.bucket = bucket.into();
4240    }
4241    pub fn set_key(&mut self, key: impl Into<String>) {
4242        self.inner.key = key.into();
4243    }
4244    pub fn set_file_path(&mut self, file_path: impl Into<String>) {
4245        self.file_path = file_path.into();
4246    }
4247    pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
4248        self.inner.content_md5 = content_md5.into();
4249    }
4250    pub fn set_content_sha256(&mut self, content_sha256: impl Into<String>) {
4251        self.inner.content_sha256 = content_sha256.into();
4252    }
4253    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
4254        self.inner.meta = meta.into();
4255    }
4256    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
4257        self.inner.traffic_limit = traffic_limit;
4258    }
4259    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
4260        self.inner.forbid_overwrite = forbid_overwrite;
4261    }
4262    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
4263        self.inner.if_match = if_match.into();
4264    }
4265    pub fn set_if_none_match(&mut self, if_none_match: impl Into<String>) {
4266        self.inner.if_none_match = if_none_match.into();
4267    }
4268    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
4269        self.inner.tagging = tagging.into();
4270    }
4271    pub fn set_object_expires(&mut self, object_expires: i64) {
4272        self.inner.object_expires = object_expires;
4273    }
4274    pub fn set_rate_limiter(&mut self, rate_limiter: impl Into<Arc<RateLimiter>>) {
4275        self.inner.rate_limiter = Some(rate_limiter.into());
4276    }
4277    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
4278        self.inner.notification_custom_parameters = notification_custom_parameters.into();
4279    }
4280}
4281
4282impl Default for PutObjectFromFileInput {
4283    fn default() -> Self {
4284        Self {
4285            inner: Default::default(),
4286            file_path: "".to_string(),
4287        }
4288    }
4289}
4290
4291#[derive(Debug, Clone, PartialEq, Default, AclHeader, Serialize, GenericInput)]
4292pub struct PutObjectACLInput {
4293    #[serde(skip)]
4294    pub(crate) generic_input: GenericInput,
4295    #[serde(skip)]
4296    pub(crate) bucket: String,
4297    #[serde(skip)]
4298    pub(crate) key: String,
4299    #[serde(skip)]
4300    pub(crate) version_id: String,
4301    #[serde(skip)]
4302    pub(crate) acl: Option<ACLType>,
4303    #[serde(skip)]
4304    pub(crate) grant_full_control: String,
4305    #[serde(skip)]
4306    pub(crate) grant_read: String,
4307    #[serde(skip)]
4308    pub(crate) grant_read_acp: String,
4309    #[serde(skip)]
4310    pub(crate) grant_write: String,
4311    #[serde(skip)]
4312    pub(crate) grant_write_acp: String,
4313    #[serde(rename = "Owner")]
4314    pub(crate) owner: Owner,
4315    #[serde(rename = "Grants")]
4316    pub(crate) grants: Vec<Grant>,
4317    #[serde(rename = "BucketOwnerEntrusted")]
4318    #[serde(skip_serializing_if = "<&bool as std::ops::Not>::not")]
4319    pub(crate) bucket_owner_entrusted: bool,
4320    #[serde(rename = "IsDefault")]
4321    #[serde(skip_serializing_if = "<&bool as std::ops::Not>::not")]
4322    pub(crate) is_default: bool,
4323}
4324
4325impl InputDescriptor for PutObjectACLInput {
4326    fn operation(&self) -> &str {
4327        "PutObjectACL"
4328    }
4329
4330    fn bucket(&self) -> Result<&str, TosError> {
4331        Ok(&self.bucket)
4332    }
4333
4334    fn key(&self) -> Result<&str, TosError> {
4335        Ok(&self.key)
4336    }
4337}
4338
4339impl<B> InputTranslator<B> for PutObjectACLInput
4340where
4341    B: BuildBufferReader,
4342{
4343    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4344        let mut request = self.trans_key()?;
4345        request.method = HttpMethodPut;
4346        if self.acl.is_some() && self.grants.len() > 0 {
4347            return Err(TosError::client_error("both acl and grants are set for put object acl"));
4348        }
4349
4350        if self.acl.is_some() {
4351            set_acl_header(&mut request.header, self);
4352        } else if self.grants.len() == 0 {
4353            return Err(TosError::client_error("neither acl nor grants is set for put object acl"));
4354        } else if self.owner.id == "" {
4355            return Err(TosError::client_error("empty owner id for put object acl"));
4356        } else {
4357            match serde_json::to_string(self) {
4358                Err(e) => return Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
4359                Ok(json) => {
4360                    let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
4361                    request.body = Some(body);
4362                    request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
4363                }
4364            }
4365        }
4366
4367        let mut query = HashMap::with_capacity(2);
4368        query.insert("acl", "".to_string());
4369        map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
4370
4371        request.query = Some(query);
4372        Ok(request)
4373    }
4374}
4375
4376impl PutObjectACLInput {
4377    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4378        let mut input = Self::default();
4379        input.bucket = bucket.into();
4380        input.key = key.into();
4381        input
4382    }
4383
4384    pub fn new_with_acl(bucket: impl Into<String>, key: impl Into<String>, acl: impl Into<ACLType>) -> Self {
4385        let mut input = Self::default();
4386        input.bucket = bucket.into();
4387        input.key = key.into();
4388        input.acl = Some(acl.into());
4389        input
4390    }
4391    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
4392        let mut input = Self::default();
4393        input.bucket = bucket.into();
4394        input.key = key.into();
4395        input.version_id = version_id.into();
4396        input
4397    }
4398    pub fn bucket(&self) -> &str {
4399        &self.bucket
4400    }
4401    pub fn key(&self) -> &str {
4402        &self.key
4403    }
4404    pub fn version_id(&self) -> &str {
4405        &self.version_id
4406    }
4407    pub fn owner(&self) -> &Owner {
4408        &self.owner
4409    }
4410    pub fn grants(&self) -> &Vec<Grant> {
4411        &self.grants
4412    }
4413    pub fn bucket_owner_entrusted(&self) -> bool {
4414        self.bucket_owner_entrusted
4415    }
4416    pub fn is_default(&self) -> bool {
4417        self.is_default
4418    }
4419    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4420        self.bucket = bucket.into();
4421    }
4422    pub fn set_key(&mut self, key: impl Into<String>) {
4423        self.key = key.into();
4424    }
4425    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
4426        self.version_id = version_id.into();
4427    }
4428    pub fn set_owner(&mut self, owner: impl Into<Owner>) {
4429        self.owner = owner.into();
4430    }
4431    pub fn set_grants(&mut self, grants: impl Into<Vec<Grant>>) {
4432        self.grants = grants.into();
4433    }
4434    pub fn set_bucket_owner_entrusted(&mut self, bucket_owner_entrusted: bool) {
4435        self.bucket_owner_entrusted = bucket_owner_entrusted;
4436    }
4437
4438    pub fn set_is_default(&mut self, is_default: bool) {
4439        self.is_default = is_default;
4440    }
4441}
4442
4443#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
4444pub struct PutObjectACLOutput {
4445    pub(crate) request_info: RequestInfo,
4446}
4447
4448impl OutputParser for PutObjectACLOutput {
4449    fn parse_by_ref<B>(_: &HttpRequest<B>, _: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
4450        Ok(Self { request_info })
4451    }
4452}
4453
4454#[derive(Debug, Clone, PartialEq, Default, HttpBasicHeader, GenericInput)]
4455pub struct SetObjectMetaInput {
4456    pub(crate) generic_input: GenericInput,
4457    pub(crate) bucket: String,
4458    pub(crate) key: String,
4459    pub(crate) version_id: String,
4460    pub(crate) content_length: i64,
4461    pub(crate) cache_control: String,
4462    pub(crate) content_disposition: String,
4463    pub(crate) content_encoding: String,
4464    pub(crate) content_language: String,
4465    pub(crate) content_type: String,
4466    pub(crate) expires: Option<DateTime<Utc>>,
4467    pub(crate) meta: HashMap<String, String>,
4468    pub(crate) metadata_directive: Option<MetadataDirectiveType>,
4469}
4470
4471impl InputDescriptor for SetObjectMetaInput {
4472    fn operation(&self) -> &str {
4473        "SetObjectMeta"
4474    }
4475    fn bucket(&self) -> Result<&str, TosError> {
4476        Ok(&self.bucket)
4477    }
4478
4479    fn key(&self) -> Result<&str, TosError> {
4480        Ok(&self.key)
4481    }
4482}
4483
4484impl<B> InputTranslator<B> for SetObjectMetaInput {
4485    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4486        let mut request = self.trans_key()?;
4487        request.method = HttpMethodPost;
4488        let header = &mut request.header;
4489        set_http_basic_header(header, config_holder.disable_encoding_meta, self);
4490        request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
4491        if let Some(metadata_directive) = &self.metadata_directive {
4492            header.insert(HEADER_METADATA_DIRECTIVE, metadata_directive.as_str().to_string());
4493        }
4494        let mut query = HashMap::with_capacity(2);
4495        query.insert("metadata", "".to_string());
4496        map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
4497        request.query = Some(query);
4498        Ok(request)
4499    }
4500}
4501
4502impl SetObjectMetaInput {
4503    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4504        let mut input = Self::default();
4505        input.bucket = bucket.into();
4506        input.key = key.into();
4507        input.content_length = -1;
4508        input
4509    }
4510    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
4511        let mut input = Self::default();
4512        input.bucket = bucket.into();
4513        input.key = key.into();
4514        input.version_id = version_id.into();
4515        input.content_length = -1;
4516        input
4517    }
4518
4519    pub fn bucket(&self) -> &str {
4520        &self.bucket
4521    }
4522    pub fn key(&self) -> &str {
4523        &self.key
4524    }
4525    pub fn version_id(&self) -> &str {
4526        &self.version_id
4527    }
4528    pub fn meta(&self) -> &HashMap<String, String> {
4529        &self.meta
4530    }
4531    pub fn metadata_directive(&self) -> &Option<MetadataDirectiveType> {
4532        &self.metadata_directive
4533    }
4534    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4535        self.bucket = bucket.into();
4536    }
4537    pub fn set_key(&mut self, key: impl Into<String>) {
4538        self.key = key.into();
4539    }
4540    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
4541        self.version_id = version_id.into();
4542    }
4543    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
4544        self.meta = meta.into();
4545    }
4546    pub fn set_metadata_directive(&mut self, metadata_directive: impl Into<MetadataDirectiveType>) {
4547        self.metadata_directive = Some(metadata_directive.into());
4548    }
4549}
4550
4551#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
4552pub struct SetObjectMetaOutput {
4553    pub(crate) request_info: RequestInfo,
4554}
4555
4556impl OutputParser for SetObjectMetaOutput {
4557    fn parse_by_ref<B>(_: &HttpRequest<B>, _: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
4558        Ok(Self { request_info })
4559    }
4560}
4561#[derive(Debug, Clone, PartialEq, Default, Serialize, GenericInput)]
4562pub struct PutObjectTaggingInput {
4563    #[serde(skip)]
4564    pub(crate) generic_input: GenericInput,
4565    #[serde(skip)]
4566    pub(crate) bucket: String,
4567    #[serde(skip)]
4568    pub(crate) key: String,
4569    #[serde(skip)]
4570    pub(crate) version_id: String,
4571    #[serde(rename = "TagSet")]
4572    pub(crate) tag_set: TagSet,
4573}
4574
4575impl PutObjectTaggingInput {
4576    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4577        let mut input = Self::default();
4578        input.bucket = bucket.into();
4579        input.key = key.into();
4580        input
4581    }
4582    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
4583        let mut input = Self::default();
4584        input.bucket = bucket.into();
4585        input.key = key.into();
4586        input.version_id = version_id.into();
4587        input
4588    }
4589
4590    pub fn bucket(&self) -> &str {
4591        &self.bucket
4592    }
4593
4594    pub fn key(&self) -> &str {
4595        &self.key
4596    }
4597
4598    pub fn version_id(&self) -> &str {
4599        &self.version_id
4600    }
4601
4602    pub fn tag_set(&self) -> &TagSet {
4603        &self.tag_set
4604    }
4605
4606    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4607        self.bucket = bucket.into();
4608    }
4609
4610    pub fn set_key(&mut self, key: impl Into<String>) {
4611        self.key = key.into();
4612    }
4613
4614    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
4615        self.version_id = version_id.into();
4616    }
4617
4618    pub fn set_tag_set(&mut self, tag_set: impl Into<TagSet>) {
4619        self.tag_set = tag_set.into();
4620    }
4621}
4622
4623impl InputDescriptor for PutObjectTaggingInput {
4624    fn operation(&self) -> &str {
4625        "PutObjectTagging"
4626    }
4627
4628    fn bucket(&self) -> Result<&str, TosError> {
4629        Ok(&self.bucket)
4630    }
4631
4632    fn key(&self) -> Result<&str, TosError> {
4633        Ok(&self.key)
4634    }
4635}
4636
4637impl<B> InputTranslator<B> for PutObjectTaggingInput
4638where
4639    B: BuildBufferReader,
4640{
4641    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4642        match serde_json::to_string(self) {
4643            Err(e) => Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
4644            Ok(json) => {
4645                let mut request = self.trans_key()?;
4646                request.method = HttpMethodPut;
4647                let mut query = HashMap::with_capacity(2);
4648                query.insert("tagging", "".to_string());
4649                map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
4650                request.query = Some(query);
4651                request.header.insert(HEADER_CONTENT_MD5, base64_md5(&json));
4652                let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
4653                request.body = Some(body);
4654                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
4655                Ok(request)
4656            }
4657        }
4658    }
4659}
4660
4661#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
4662pub struct PutObjectTaggingOutput {
4663    pub(crate) request_info: RequestInfo,
4664    pub(crate) version_id: String,
4665}
4666#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
4667pub struct GetObjectTaggingInput {
4668    pub(crate) generic_input: GenericInput,
4669    pub(crate) bucket: String,
4670    pub(crate) key: String,
4671    pub(crate) version_id: String,
4672}
4673
4674impl GetObjectTaggingInput {
4675    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4676        let mut input = Self::default();
4677        input.bucket = bucket.into();
4678        input.key = key.into();
4679        input
4680    }
4681    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
4682        let mut input = Self::default();
4683        input.bucket = bucket.into();
4684        input.key = key.into();
4685        input.version_id = version_id.into();
4686        input
4687    }
4688
4689    pub fn bucket(&self) -> &str {
4690        &self.bucket
4691    }
4692
4693    pub fn key(&self) -> &str {
4694        &self.key
4695    }
4696
4697    pub fn version_id(&self) -> &str {
4698        &self.version_id
4699    }
4700
4701    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4702        self.bucket = bucket.into();
4703    }
4704
4705    pub fn set_key(&mut self, key: impl Into<String>) {
4706        self.key = key.into();
4707    }
4708
4709    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
4710        self.version_id = version_id.into();
4711    }
4712}
4713
4714impl InputDescriptor for GetObjectTaggingInput {
4715    fn operation(&self) -> &str {
4716        "GetObjectTagging"
4717    }
4718
4719    fn bucket(&self) -> Result<&str, TosError> {
4720        Ok(&self.bucket)
4721    }
4722
4723    fn key(&self) -> Result<&str, TosError> {
4724        Ok(&self.key)
4725    }
4726}
4727
4728impl<B> InputTranslator<B> for GetObjectTaggingInput {
4729    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4730        let mut request = self.trans_key()?;
4731        request.method = HttpMethodGet;
4732        let mut query = HashMap::with_capacity(2);
4733        query.insert("tagging", "".to_string());
4734        if self.version_id != "" {
4735            query.insert(QUERY_VERSION_ID, self.version_id.clone());
4736        }
4737        request.query = Some(query);
4738        Ok(request)
4739    }
4740}
4741
4742#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
4743pub struct GetObjectTaggingOutput {
4744    #[serde(skip)]
4745    pub(crate) request_info: RequestInfo,
4746    #[serde(skip)]
4747    pub(crate) version_id: String,
4748    #[serde(rename = "TagSet")]
4749    pub(crate) tag_set: TagSet,
4750}
4751
4752impl GetObjectTaggingOutput {
4753    pub fn version_id(&self) -> &str {
4754        &self.version_id
4755    }
4756
4757    pub fn tag_set(&self) -> &TagSet {
4758        &self.tag_set
4759    }
4760}
4761#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
4762pub struct DeleteObjectTaggingInput {
4763    pub(crate) generic_input: GenericInput,
4764    pub(crate) bucket: String,
4765    pub(crate) key: String,
4766    pub(crate) version_id: String,
4767}
4768
4769impl DeleteObjectTaggingInput {
4770    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4771        let mut input = Self::default();
4772        input.bucket = bucket.into();
4773        input.key = key.into();
4774        input
4775    }
4776    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
4777        let mut input = Self::default();
4778        input.bucket = bucket.into();
4779        input.key = key.into();
4780        input.version_id = version_id.into();
4781        input
4782    }
4783
4784    pub fn bucket(&self) -> &str {
4785        &self.bucket
4786    }
4787
4788    pub fn key(&self) -> &str {
4789        &self.key
4790    }
4791
4792    pub fn version_id(&self) -> &str {
4793        &self.version_id
4794    }
4795
4796    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
4797        self.bucket = bucket.into();
4798    }
4799
4800    pub fn set_key(&mut self, key: impl Into<String>) {
4801        self.key = key.into();
4802    }
4803
4804    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
4805        self.version_id = version_id.into();
4806    }
4807}
4808
4809impl InputDescriptor for DeleteObjectTaggingInput {
4810    fn operation(&self) -> &str {
4811        "DeleteObjectTagging"
4812    }
4813
4814    fn bucket(&self) -> Result<&str, TosError> {
4815        Ok(&self.bucket)
4816    }
4817
4818    fn key(&self) -> Result<&str, TosError> {
4819        Ok(&self.key)
4820    }
4821}
4822
4823impl<B> InputTranslator<B> for DeleteObjectTaggingInput {
4824    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
4825        let mut request = self.trans_key()?;
4826        request.method = HttpMethodDelete;
4827        let mut query = HashMap::with_capacity(2);
4828        query.insert("tagging", "".to_string());
4829        if self.version_id != "" {
4830            query.insert(QUERY_VERSION_ID, self.version_id.clone());
4831        }
4832        request.query = Some(query);
4833        Ok(request)
4834    }
4835}
4836
4837#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
4838pub struct DeleteObjectTaggingOutput {
4839    pub(crate) request_info: RequestInfo,
4840    pub(crate) version_id: String,
4841}
4842
4843#[derive(
4844    Debug,
4845    Clone,
4846    HttpBasicHeader,
4847    AclHeader,
4848    SseHeader,
4849    SsecHeader,
4850    MiscHeader,
4851    ObjectLock,
4852    IfMatch,
4853    Serialize,
4854    GenericInput,
4855)]
4856pub struct FetchObjectInput {
4857    #[serde(skip)]
4858    pub(crate) generic_input: GenericInput,
4859    #[serde(skip)]
4860    pub(crate) bucket: String,
4861    #[serde(rename = "Object")]
4862    pub(crate) key: String,
4863    #[serde(rename = "URL")]
4864    pub(crate) url: String,
4865    #[serde(rename = "IgnoreSameKey")]
4866    #[serde(skip_serializing_if = "<&bool as std::ops::Not>::not")]
4867    pub(crate) ignore_same_key: bool,
4868    #[serde(rename = "ContentMD5")]
4869    #[serde(skip_serializing_if = "String::is_empty")]
4870    pub(crate) content_md5: String,
4871    #[serde(skip)]
4872    pub(crate) content_length: i64,
4873    #[serde(skip)]
4874    pub(crate) cache_control: String,
4875    #[serde(skip)]
4876    pub(crate) content_disposition: String,
4877    #[serde(skip)]
4878    pub(crate) content_encoding: String,
4879    #[serde(skip)]
4880    pub(crate) content_language: String,
4881    #[serde(skip)]
4882    pub(crate) content_type: String,
4883    #[serde(skip)]
4884    pub(crate) expires: Option<DateTime<Utc>>,
4885    #[serde(skip)]
4886    pub(crate) acl: Option<ACLType>,
4887    #[serde(skip)]
4888    pub(crate) grant_full_control: String,
4889    #[serde(skip)]
4890    pub(crate) grant_read: String,
4891    #[serde(skip)]
4892    pub(crate) grant_read_acp: String,
4893    #[serde(skip)]
4894    pub(crate) grant_write: String,
4895    #[serde(skip)]
4896    pub(crate) grant_write_acp: String,
4897    #[serde(skip)]
4898    pub(crate) ssec_algorithm: String,
4899    #[serde(skip)]
4900    pub(crate) ssec_key: String,
4901    #[serde(skip)]
4902    pub(crate) ssec_key_md5: String,
4903    #[serde(skip)]
4904    pub(crate) server_side_encryption: String,
4905    #[serde(skip)]
4906    pub(crate) server_side_encryption_key_id: String,
4907    #[serde(skip)]
4908    pub(crate) meta: HashMap<String, String>,
4909    #[serde(skip)]
4910    pub(crate) website_redirect_location: String,
4911    #[serde(skip)]
4912    pub(crate) storage_class: Option<StorageClassType>,
4913    #[serde(skip)]
4914    pub(crate) traffic_limit: i64,
4915    #[serde(skip)]
4916    pub(crate) forbid_overwrite: bool,
4917    #[serde(skip)]
4918    pub(crate) if_match: String,
4919    #[serde(skip)]
4920    pub(crate) if_none_match: String,
4921    #[serde(skip)]
4922    pub(crate) tagging: String,
4923    #[serde(skip)]
4924    pub(crate) notification_custom_parameters: String,
4925    #[serde(skip)]
4926    pub(crate) detect_mime_type: bool,
4927    #[serde(skip)]
4928    pub(crate) object_expires: i64,
4929    #[serde(skip)]
4930    pub(crate) object_lock_mode: Option<ObjectLockModeType>,
4931    #[serde(skip)]
4932    pub(crate) object_lock_retain_util_date: Option<DateTime<Utc>>,
4933}
4934
4935impl Default for FetchObjectInput {
4936    fn default() -> Self {
4937        Self {
4938            generic_input: Default::default(),
4939            bucket: "".to_string(),
4940            key: "".to_string(),
4941            url: "".to_string(),
4942            ignore_same_key: false,
4943            content_md5: "".to_string(),
4944            content_length: -1,
4945            cache_control: "".to_string(),
4946            content_disposition: "".to_string(),
4947            content_encoding: "".to_string(),
4948            content_language: "".to_string(),
4949            content_type: "".to_string(),
4950            expires: None,
4951            acl: None,
4952            grant_full_control: "".to_string(),
4953            grant_read: "".to_string(),
4954            grant_read_acp: "".to_string(),
4955            grant_write: "".to_string(),
4956            grant_write_acp: "".to_string(),
4957            ssec_algorithm: "".to_string(),
4958            ssec_key: "".to_string(),
4959            ssec_key_md5: "".to_string(),
4960            server_side_encryption: "".to_string(),
4961            server_side_encryption_key_id: "".to_string(),
4962            meta: Default::default(),
4963            website_redirect_location: "".to_string(),
4964            storage_class: None,
4965            traffic_limit: 0,
4966            forbid_overwrite: false,
4967            if_match: "".to_string(),
4968            if_none_match: "".to_string(),
4969            tagging: "".to_string(),
4970            notification_custom_parameters: "".to_string(),
4971            detect_mime_type: false,
4972            object_expires: -1,
4973            object_lock_mode: None,
4974            object_lock_retain_util_date: None,
4975        }
4976    }
4977}
4978
4979impl FetchObjectInput
4980{
4981    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
4982        let mut input = Self::default();
4983        input.bucket = bucket.into();
4984        input.key = key.into();
4985        input
4986    }
4987    pub fn new_with_url(bucket: impl Into<String>, key: impl Into<String>, url: impl Into<String>) -> Self {
4988        let mut input = Self::default();
4989        input.bucket = bucket.into();
4990        input.key = key.into();
4991        input.url = url.into();
4992        input
4993    }
4994    pub fn bucket(&self) -> &str {
4995        &self.bucket
4996    }
4997    pub fn key(&self) -> &str {
4998        &self.key
4999    }
5000
5001    pub fn url(&self) -> &str {
5002        &self.url
5003    }
5004
5005    pub fn ignore_same_key(&self) -> bool {
5006        self.ignore_same_key
5007    }
5008
5009    pub fn content_md5(&self) -> &str {
5010        &self.content_md5
5011    }
5012    pub fn meta(&self) -> &HashMap<String, String> {
5013        &self.meta
5014    }
5015    pub fn traffic_limit(&self) -> i64 {
5016        self.traffic_limit
5017    }
5018    pub fn forbid_overwrite(&self) -> bool {
5019        self.forbid_overwrite
5020    }
5021    pub fn tagging(&self) -> &str {
5022        &self.tagging
5023    }
5024
5025    pub fn notification_custom_parameters(&self) -> &str {
5026        &self.notification_custom_parameters
5027    }
5028
5029    pub fn detect_mime_type(&self) -> bool {
5030        self.detect_mime_type
5031    }
5032
5033    pub fn object_expires(&self) -> i64 {
5034        self.object_expires
5035    }
5036    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
5037        self.bucket = bucket.into();
5038    }
5039    pub fn set_key(&mut self, key: impl Into<String>) {
5040        self.key = key.into();
5041    }
5042
5043    pub fn set_url(&mut self, url: impl Into<String>) {
5044        self.url = url.into();
5045    }
5046
5047    pub fn set_ignore_same_key(&mut self, ignore_same_key: bool) {
5048        self.ignore_same_key = ignore_same_key;
5049    }
5050
5051    pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
5052        self.content_md5 = content_md5.into();
5053    }
5054    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
5055        self.meta = meta.into();
5056    }
5057    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
5058        self.traffic_limit = traffic_limit;
5059    }
5060    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
5061        self.forbid_overwrite = forbid_overwrite;
5062    }
5063    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
5064        self.tagging = tagging.into();
5065    }
5066
5067    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
5068        self.notification_custom_parameters = notification_custom_parameters.into();
5069    }
5070
5071    pub fn set_detect_mime_type(&mut self, detect_mime_type: bool) {
5072        self.detect_mime_type = detect_mime_type;
5073    }
5074
5075    pub fn set_object_expires(&mut self, object_expires: i64) {
5076        self.object_expires = object_expires;
5077    }
5078}
5079
5080impl InputDescriptor for FetchObjectInput {
5081    fn operation(&self) -> &str {
5082        "FetchObject"
5083    }
5084    fn bucket(&self) -> Result<&str, TosError> {
5085        Ok(&self.bucket)
5086    }
5087
5088    fn key(&self) -> Result<&str, TosError> {
5089        Ok(&self.key)
5090    }
5091}
5092
5093impl<B> InputTranslator<B> for FetchObjectInput
5094where
5095    B: BuildBufferReader,
5096{
5097    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
5098        if self.url == "" {
5099            return Err(TosError::client_error("empty url"));
5100        }
5101
5102        match serde_json::to_string(self) {
5103            Err(e) => Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
5104            Ok(json) => {
5105                let mut request = self.trans_key()?;
5106                request.method = HttpMethodPost;
5107                let header = &mut request.header;
5108                header.insert(HEADER_CONTENT_MD5, base64_md5(&json));
5109                let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
5110                request.body = Some(body);
5111                header.insert(HEADER_CONTENT_LENGTH, len.to_string());
5112                set_http_basic_header_for_fetch(header, config_holder.disable_encoding_meta, self);
5113                set_acl_header(header, self);
5114                set_sse_header(header, self)?;
5115                set_ssec_header(header, &self.server_side_encryption, self)?;
5116                set_if_match_header(header, self);
5117                set_object_lock_header(header, self);
5118                request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
5119                set_misc_header_for_fetch(header, self);
5120                if self.forbid_overwrite {
5121                    header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
5122                }
5123                if self.traffic_limit > 0 {
5124                    header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
5125                }
5126                if self.tagging != "" {
5127                    header.insert(HEADER_TAGGING, self.tagging.clone());
5128                }
5129
5130                if self.object_expires >= 0 {
5131                    header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
5132                }
5133                if self.notification_custom_parameters != "" {
5134                    header.insert(HEADER_NOTIFICATION_CUSTOM_PARAMETERS, self.notification_custom_parameters.to_string());
5135                }
5136                if self.detect_mime_type {
5137                    header.insert(HEADER_FETCH_DETECT_MIME_TYPE, "true".to_string());
5138                }
5139                request.query = Some(HashMap::from([("fetch", "".to_string())]));
5140                Ok(request)
5141            }
5142        }
5143    }
5144}
5145
5146#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
5147pub struct FetchObjectOutput {
5148    pub(crate) request_info: RequestInfo,
5149    pub(crate) etag: String,
5150    pub(crate) version_id: String,
5151    pub(crate) ssec_algorithm: String,
5152    pub(crate) ssec_key_md5: String,
5153    pub(crate) server_side_encryption: String,
5154    pub(crate) server_side_encryption_key_id: String,
5155    pub(crate) source_content_type: String,
5156    pub(crate) source_content_length: i64,
5157    pub(crate) md5: String,
5158}
5159
5160impl FetchObjectOutput {
5161    pub fn etag(&self) -> &str {
5162        &self.etag
5163    }
5164
5165    pub fn version_id(&self) -> &str {
5166        &self.version_id
5167    }
5168
5169    pub fn ssec_algorithm(&self) -> &str {
5170        &self.ssec_algorithm
5171    }
5172
5173    pub fn ssec_key_md5(&self) -> &str {
5174        &self.ssec_key_md5
5175    }
5176
5177    pub fn server_side_encryption(&self) -> &str {
5178        &self.server_side_encryption
5179    }
5180
5181    pub fn server_side_encryption_key_id(&self) -> &str {
5182        &self.server_side_encryption_key_id
5183    }
5184
5185    pub fn source_content_type(&self) -> &str {
5186        &self.source_content_type
5187    }
5188
5189    pub fn source_content_length(&self) -> i64 {
5190        self.source_content_length
5191    }
5192
5193    pub fn md5(&self) -> &str {
5194        &self.md5
5195    }
5196}
5197
5198#[derive(
5199    Debug,
5200    Clone,
5201    HttpBasicHeader,
5202    AclHeader,
5203    SseHeader,
5204    SsecHeader,
5205    MiscHeader,
5206    ObjectLock,
5207    IfMatch,
5208    Serialize,
5209    GenericInput
5210)]
5211pub struct PutFetchTaskInput {
5212    #[serde(skip)]
5213    pub(crate) generic_input: GenericInput,
5214    #[serde(skip)]
5215    pub(crate) bucket: String,
5216    #[serde(rename = "Object")]
5217    pub(crate) key: String,
5218    #[serde(rename = "URL")]
5219    pub(crate) url: String,
5220    #[serde(rename = "IgnoreSameKey")]
5221    #[serde(skip_serializing_if = "<&bool as std::ops::Not>::not")]
5222    pub(crate) ignore_same_key: bool,
5223    #[serde(rename = "ContentMD5")]
5224    #[serde(skip_serializing_if = "String::is_empty")]
5225    pub(crate) content_md5: String,
5226    #[serde(rename = "CallbackUrl")]
5227    #[serde(skip_serializing_if = "String::is_empty")]
5228    pub(crate) callback_url: String,
5229    #[serde(rename = "CallbackHost")]
5230    #[serde(skip_serializing_if = "String::is_empty")]
5231    pub(crate) callback_host: String,
5232    #[serde(rename = "CallbackBodyType")]
5233    #[serde(skip_serializing_if = "String::is_empty")]
5234    pub(crate) callback_body_type: String,
5235    #[serde(rename = "CallbackBody")]
5236    #[serde(skip_serializing_if = "String::is_empty")]
5237    pub(crate) callback_body: String,
5238    #[serde(skip)]
5239    pub(crate) content_length: i64,
5240    #[serde(skip)]
5241    pub(crate) cache_control: String,
5242    #[serde(skip)]
5243    pub(crate) content_disposition: String,
5244    #[serde(skip)]
5245    pub(crate) content_encoding: String,
5246    #[serde(skip)]
5247    pub(crate) content_language: String,
5248    #[serde(skip)]
5249    pub(crate) content_type: String,
5250    #[serde(skip)]
5251    pub(crate) expires: Option<DateTime<Utc>>,
5252    #[serde(skip)]
5253    pub(crate) acl: Option<ACLType>,
5254    #[serde(skip)]
5255    pub(crate) grant_full_control: String,
5256    #[serde(skip)]
5257    pub(crate) grant_read: String,
5258    #[serde(skip)]
5259    pub(crate) grant_read_acp: String,
5260    #[serde(skip)]
5261    pub(crate) grant_write: String,
5262    #[serde(skip)]
5263    pub(crate) grant_write_acp: String,
5264    #[serde(skip)]
5265    pub(crate) ssec_algorithm: String,
5266    #[serde(skip)]
5267    pub(crate) ssec_key: String,
5268    #[serde(skip)]
5269    pub(crate) ssec_key_md5: String,
5270    #[serde(skip)]
5271    pub(crate) server_side_encryption: String,
5272    #[serde(skip)]
5273    pub(crate) server_side_encryption_key_id: String,
5274    #[serde(skip)]
5275    pub(crate) meta: HashMap<String, String>,
5276    #[serde(skip)]
5277    pub(crate) website_redirect_location: String,
5278    #[serde(skip)]
5279    pub(crate) storage_class: Option<StorageClassType>,
5280    #[serde(skip)]
5281    pub(crate) traffic_limit: i64,
5282    #[serde(skip)]
5283    pub(crate) forbid_overwrite: bool,
5284    #[serde(skip)]
5285    pub(crate) if_match: String,
5286    #[serde(skip)]
5287    pub(crate) if_none_match: String,
5288    #[serde(skip)]
5289    pub(crate) tagging: String,
5290    #[serde(skip)]
5291    pub(crate) notification_custom_parameters: String,
5292    #[serde(skip)]
5293    pub(crate) detect_mime_type: bool,
5294    #[serde(skip)]
5295    pub(crate) object_expires: i64,
5296    #[serde(skip)]
5297    pub(crate) object_lock_mode: Option<ObjectLockModeType>,
5298    #[serde(skip)]
5299    pub(crate) object_lock_retain_util_date: Option<DateTime<Utc>>,
5300}
5301
5302impl Default for PutFetchTaskInput {
5303    fn default() -> Self {
5304        Self {
5305            generic_input: Default::default(),
5306            bucket: "".to_string(),
5307            key: "".to_string(),
5308            url: "".to_string(),
5309            ignore_same_key: false,
5310            content_md5: "".to_string(),
5311            callback_url: "".to_string(),
5312            callback_host: "".to_string(),
5313            callback_body_type: "".to_string(),
5314            callback_body: "".to_string(),
5315            content_length: -1,
5316            cache_control: "".to_string(),
5317            content_disposition: "".to_string(),
5318            content_encoding: "".to_string(),
5319            content_language: "".to_string(),
5320            content_type: "".to_string(),
5321            expires: None,
5322            acl: None,
5323            grant_full_control: "".to_string(),
5324            grant_read: "".to_string(),
5325            grant_read_acp: "".to_string(),
5326            grant_write: "".to_string(),
5327            grant_write_acp: "".to_string(),
5328            ssec_algorithm: "".to_string(),
5329            ssec_key: "".to_string(),
5330            ssec_key_md5: "".to_string(),
5331            server_side_encryption: "".to_string(),
5332            server_side_encryption_key_id: "".to_string(),
5333            meta: Default::default(),
5334            website_redirect_location: "".to_string(),
5335            storage_class: None,
5336            traffic_limit: 0,
5337            forbid_overwrite: false,
5338            if_match: "".to_string(),
5339            if_none_match: "".to_string(),
5340            tagging: "".to_string(),
5341            notification_custom_parameters: "".to_string(),
5342            detect_mime_type: false,
5343            object_expires: -1,
5344            object_lock_mode: None,
5345            object_lock_retain_util_date: None,
5346        }
5347    }
5348}
5349
5350impl PutFetchTaskInput {
5351    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
5352        let mut input = Self::default();
5353        input.bucket = bucket.into();
5354        input.key = key.into();
5355        input
5356    }
5357    pub fn new_with_url(bucket: impl Into<String>, key: impl Into<String>, url: impl Into<String>) -> Self {
5358        let mut input = Self::default();
5359        input.bucket = bucket.into();
5360        input.key = key.into();
5361        input.url = url.into();
5362        input
5363    }
5364    pub fn bucket(&self) -> &str {
5365        &self.bucket
5366    }
5367    pub fn key(&self) -> &str {
5368        &self.key
5369    }
5370
5371    pub fn url(&self) -> &str {
5372        &self.url
5373    }
5374
5375    pub fn ignore_same_key(&self) -> bool {
5376        self.ignore_same_key
5377    }
5378
5379    pub fn content_md5(&self) -> &str {
5380        &self.content_md5
5381    }
5382    pub fn callback_url(&self) -> &str {
5383        &self.callback_url
5384    }
5385
5386    pub fn callback_host(&self) -> &str {
5387        &self.callback_host
5388    }
5389
5390    pub fn callback_body_type(&self) -> &str {
5391        &self.callback_body_type
5392    }
5393
5394    pub fn callback_body(&self) -> &str {
5395        &self.callback_body
5396    }
5397
5398    pub fn meta(&self) -> &HashMap<String, String> {
5399        &self.meta
5400    }
5401    pub fn traffic_limit(&self) -> i64 {
5402        self.traffic_limit
5403    }
5404    pub fn forbid_overwrite(&self) -> bool {
5405        self.forbid_overwrite
5406    }
5407    pub fn tagging(&self) -> &str {
5408        &self.tagging
5409    }
5410
5411    pub fn notification_custom_parameters(&self) -> &str {
5412        &self.notification_custom_parameters
5413    }
5414
5415    pub fn detect_mime_type(&self) -> bool {
5416        self.detect_mime_type
5417    }
5418
5419    pub fn object_expires(&self) -> i64 {
5420        self.object_expires
5421    }
5422    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
5423        self.bucket = bucket.into();
5424    }
5425    pub fn set_key(&mut self, key: impl Into<String>) {
5426        self.key = key.into();
5427    }
5428
5429    pub fn set_url(&mut self, url: impl Into<String>) {
5430        self.url = url.into();
5431    }
5432
5433    pub fn set_ignore_same_key(&mut self, ignore_same_key: bool) {
5434        self.ignore_same_key = ignore_same_key;
5435    }
5436    pub fn set_content_md5(&mut self, content_md5: impl Into<String>) {
5437        self.content_md5 = content_md5.into();
5438    }
5439
5440    pub fn set_callback_url(&mut self, callback_url: impl Into<String>) {
5441        self.callback_url = callback_url.into();
5442    }
5443
5444    pub fn set_callback_host(&mut self, callback_host: impl Into<String>) {
5445        self.callback_host = callback_host.into();
5446    }
5447
5448    pub fn set_callback_body_type(&mut self, callback_body_type: impl Into<String>) {
5449        self.callback_body_type = callback_body_type.into();
5450    }
5451
5452    pub fn set_callback_body(&mut self, callback_body: impl Into<String>) {
5453        self.callback_body = callback_body.into();
5454    }
5455    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
5456        self.meta = meta.into();
5457    }
5458    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
5459        self.traffic_limit = traffic_limit;
5460    }
5461    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
5462        self.forbid_overwrite = forbid_overwrite;
5463    }
5464    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
5465        self.tagging = tagging.into();
5466    }
5467
5468    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
5469        self.notification_custom_parameters = notification_custom_parameters.into();
5470    }
5471
5472    pub fn set_detect_mime_type(&mut self, detect_mime_type: bool) {
5473        self.detect_mime_type = detect_mime_type;
5474    }
5475
5476    pub fn set_object_expires(&mut self, object_expires: i64) {
5477        self.object_expires = object_expires;
5478    }
5479}
5480
5481impl InputDescriptor for PutFetchTaskInput {
5482    fn operation(&self) -> &str {
5483        "PutFetchTask"
5484    }
5485
5486    fn bucket(&self) -> Result<&str, TosError> {
5487        Ok(&self.bucket)
5488    }
5489
5490    fn key(&self) -> Result<&str, TosError> {
5491        Ok(&self.key)
5492    }
5493}
5494
5495impl<B> InputTranslator<B> for PutFetchTaskInput
5496where
5497    B: BuildBufferReader,
5498{
5499    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
5500        if self.url == "" {
5501            return Err(TosError::client_error("empty url"));
5502        }
5503
5504        match serde_json::to_string(self) {
5505            Err(e) => Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
5506            Ok(json) => {
5507                let mut request = self.trans_key()?;
5508                request.method = HttpMethodPost;
5509                let header = &mut request.header;
5510                header.insert(HEADER_CONTENT_MD5, base64_md5(&json));
5511                let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
5512                request.body = Some(body);
5513                header.insert(HEADER_CONTENT_LENGTH, len.to_string());
5514                set_http_basic_header_for_fetch(header, config_holder.disable_encoding_meta, self);
5515                set_acl_header(header, self);
5516                set_sse_header(header, self)?;
5517                set_ssec_header(header, &self.server_side_encryption, self)?;
5518                set_if_match_header(header, self);
5519                set_object_lock_header(header, self);
5520                request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
5521                set_misc_header_for_fetch(header, self);
5522                if self.forbid_overwrite {
5523                    header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
5524                }
5525                if self.traffic_limit > 0 {
5526                    header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
5527                }
5528                if self.tagging != "" {
5529                    header.insert(HEADER_TAGGING, self.tagging.clone());
5530                }
5531
5532                if self.object_expires >= 0 {
5533                    header.insert(HEADER_OBJECT_EXPIRES, self.object_expires.to_string());
5534                }
5535                if self.notification_custom_parameters != "" {
5536                    header.insert(HEADER_NOTIFICATION_CUSTOM_PARAMETERS, self.notification_custom_parameters.to_string());
5537                }
5538                if self.detect_mime_type {
5539                    header.insert(HEADER_FETCH_DETECT_MIME_TYPE, "true".to_string());
5540                }
5541                request.query = Some(HashMap::from([("fetchTask", "".to_string())]));
5542                Ok(request)
5543            }
5544        }
5545    }
5546}
5547#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
5548pub struct PutFetchTaskOutput {
5549    #[serde(skip)]
5550    pub(crate) request_info: RequestInfo,
5551    #[serde(rename = "TaskId")]
5552    pub(crate) task_id: String,
5553}
5554impl PutFetchTaskOutput {
5555    pub fn task_id(&self) -> &str {
5556        &self.task_id
5557    }
5558}
5559#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
5560pub struct GetFetchTaskInput {
5561    pub(crate) generic_input: GenericInput,
5562    pub(crate) bucket: String,
5563    pub(crate) task_id: String,
5564}
5565
5566impl GetFetchTaskInput {
5567    pub fn new(bucket: impl Into<String>, task_id: impl Into<String>) -> Self {
5568        Self {
5569            generic_input: Default::default(),
5570            bucket: bucket.into(),
5571            task_id: task_id.into(),
5572        }
5573    }
5574
5575    pub fn bucket(&self) -> &str {
5576        &self.bucket
5577    }
5578
5579    pub fn task_id(&self) -> &str {
5580        &self.task_id
5581    }
5582
5583    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
5584        self.bucket = bucket.into();
5585    }
5586
5587    pub fn set_task_id(&mut self, task_id: impl Into<String>) {
5588        self.task_id = task_id.into();
5589    }
5590}
5591
5592impl InputDescriptor for GetFetchTaskInput {
5593    fn operation(&self) -> &str {
5594        "GetFetchTask"
5595    }
5596
5597    fn bucket(&self) -> Result<&str, TosError> {
5598        Ok(&self.bucket)
5599    }
5600}
5601
5602impl<B> InputTranslator<B> for GetFetchTaskInput {
5603    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
5604        if self.task_id == "" {
5605            return Err(TosError::client_error("empty task id"));
5606        }
5607
5608        let mut request = self.trans_bucket()?;
5609        request.method = HttpMethodGet;
5610        let mut query = HashMap::with_capacity(2);
5611        query.insert("fetchTask", "".to_string());
5612        map_insert(&mut query, QUERY_TASK_ID, &self.task_id);
5613        request.query = Some(query);
5614        Ok(request)
5615    }
5616}
5617
5618#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
5619pub struct GetFetchTaskOutput {
5620    #[serde(skip)]
5621    pub(crate) request_info: RequestInfo,
5622    #[serde(rename = "State")]
5623    #[serde(default)]
5624    pub(crate) state: String,
5625    #[serde(rename = "Err")]
5626    #[serde(default)]
5627    pub(crate) err: String,
5628    #[serde(rename = "Task")]
5629    pub(crate) task: Option<FetchTask>,
5630}
5631impl GetFetchTaskOutput {
5632    pub fn state(&self) -> &str {
5633        &self.state
5634    }
5635
5636    pub fn err(&self) -> &str {
5637        &self.err
5638    }
5639
5640    pub fn task(&self) -> &Option<FetchTask> {
5641        &self.task
5642    }
5643}
5644#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
5645pub struct FetchTask {
5646    #[serde(rename = "URL")]
5647    #[serde(default)]
5648    pub(crate) url: String,
5649    #[serde(rename = "IgnoreSameKey")]
5650    #[serde(default)]
5651    pub(crate) ignore_same_key: bool,
5652    #[serde(rename = "ContentMD5")]
5653    #[serde(default)]
5654    pub(crate) content_md5: String,
5655    #[serde(rename = "Bucket")]
5656    #[serde(default)]
5657    pub(crate) bucket: String,
5658    #[serde(rename = "Key")]
5659    #[serde(default)]
5660    pub(crate) key: String,
5661    #[serde(rename = "CallbackUrl")]
5662    #[serde(default)]
5663    pub(crate) callback_url: String,
5664    #[serde(rename = "CallbackHost")]
5665    #[serde(default)]
5666    pub(crate) callback_host: String,
5667    #[serde(rename = "CallbackBodyType")]
5668    #[serde(default)]
5669    pub(crate) callback_body_type: String,
5670    #[serde(rename = "CallbackBody")]
5671    #[serde(default)]
5672    pub(crate) callback_body: String,
5673    #[serde(rename = "StorageClass")]
5674    pub(crate) storage_class: Option<StorageClassType>,
5675    #[serde(rename = "Acl")]
5676    pub(crate) acl: Option<ACLType>,
5677    #[serde(rename = "GrantFullControl")]
5678    #[serde(default)]
5679    pub(crate) grant_fullcontrol: String,
5680    #[serde(rename = "GrantRead")]
5681    #[serde(default)]
5682    pub(crate) grant_read: String,
5683    #[serde(rename = "GrantReadAcp")]
5684    #[serde(default)]
5685    pub(crate) grant_read_acp: String,
5686    #[serde(rename = "GrantWrite")]
5687    #[serde(default)]
5688    pub(crate) grant_write: String,
5689    #[serde(rename = "GrantWriteAcp")]
5690    #[serde(default)]
5691    pub(crate) grant_write_acp: String,
5692    #[serde(rename = "SSECAlgorithm")]
5693    #[serde(default)]
5694    pub(crate) ssec_algorithm: String,
5695    #[serde(rename = "SSECKey")]
5696    #[serde(default)]
5697    pub(crate) ssec_key: String,
5698    #[serde(rename = "SSECKeyMd5")]
5699    #[serde(default)]
5700    pub(crate) ssec_key_md5: String,
5701    #[serde(rename = "UserMeta")]
5702    #[serde(default)]
5703    pub(crate) user_meta: Vec<UserMeta>,
5704    #[serde(skip)]
5705    pub(crate) meta: HashMap<String, String>,
5706}
5707
5708impl FetchTask {
5709    pub fn url(&self) -> &str {
5710        &self.url
5711    }
5712
5713    pub fn ignore_same_key(&self) -> bool {
5714        self.ignore_same_key
5715    }
5716
5717    pub fn content_md5(&self) -> &str {
5718        &self.content_md5
5719    }
5720
5721    pub fn bucket(&self) -> &str {
5722        &self.bucket
5723    }
5724
5725    pub fn key(&self) -> &str {
5726        &self.key
5727    }
5728    pub fn callback_body(&self) -> &str {
5729        &self.callback_body
5730    }
5731
5732    pub fn callback_body_type(&self) -> &str {
5733        &self.callback_body_type
5734    }
5735
5736    pub fn callback_host(&self) -> &str {
5737        &self.callback_host
5738    }
5739
5740    pub fn callback_url(&self) -> &str {
5741        &self.callback_url
5742    }
5743    pub fn storage_class(&self) -> &Option<StorageClassType> {
5744        &self.storage_class
5745    }
5746
5747    pub fn acl(&self) -> &Option<ACLType> {
5748        &self.acl
5749    }
5750
5751    pub fn grant_fullcontrol(&self) -> &str {
5752        &self.grant_fullcontrol
5753    }
5754
5755    pub fn grant_read(&self) -> &str {
5756        &self.grant_read
5757    }
5758
5759    pub fn grant_read_acp(&self) -> &str {
5760        &self.grant_read_acp
5761    }
5762
5763    pub fn grant_write(&self) -> &str {
5764        &self.grant_write
5765    }
5766
5767    pub fn grant_write_acp(&self) -> &str {
5768        &self.grant_write_acp
5769    }
5770
5771    pub fn ssec_algorithm(&self) -> &str {
5772        &self.ssec_algorithm
5773    }
5774
5775    pub fn ssec_key(&self) -> &str {
5776        &self.ssec_key
5777    }
5778
5779    pub fn ssec_key_md5(&self) -> &str {
5780        &self.ssec_key_md5
5781    }
5782
5783    pub fn meta(&self) -> &HashMap<String, String> {
5784        &self.meta
5785    }
5786}
5787#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
5788pub struct RenameObjectInput {
5789    pub(crate) generic_input: GenericInput,
5790    pub(crate) bucket: String,
5791    pub(crate) key: String,
5792    pub(crate) new_key: String,
5793    pub(crate) recursive_mkdir: bool,
5794    pub(crate) forbid_overwrite: bool,
5795    pub(crate) notification_custom_parameters: String,
5796}
5797
5798impl RenameObjectInput {
5799    pub fn new(bucket: impl Into<String>, key: impl Into<String>, new_key: impl Into<String>) -> Self {
5800        Self {
5801            generic_input: Default::default(),
5802            bucket: bucket.into(),
5803            key: key.into(),
5804            new_key: new_key.into(),
5805            recursive_mkdir: false,
5806            forbid_overwrite: false,
5807            notification_custom_parameters: "".to_string(),
5808        }
5809    }
5810
5811    pub fn bucket(&self) -> &str {
5812        &self.bucket
5813    }
5814
5815    pub fn key(&self) -> &str {
5816        &self.key
5817    }
5818
5819    pub fn new_key(&self) -> &str {
5820        &self.new_key
5821    }
5822
5823    pub fn recursive_mkdir(&self) -> bool {
5824        self.recursive_mkdir
5825    }
5826
5827    pub fn forbid_overwrite(&self) -> bool {
5828        self.forbid_overwrite
5829    }
5830
5831    pub fn notification_custom_parameters(&self) -> &str {
5832        &self.notification_custom_parameters
5833    }
5834
5835    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
5836        self.bucket = bucket.into();
5837    }
5838
5839    pub fn set_key(&mut self, key: impl Into<String>) {
5840        self.key = key.into();
5841    }
5842
5843    pub fn set_new_key(&mut self, new_key: impl Into<String>) {
5844        self.new_key = new_key.into();
5845    }
5846
5847    pub fn set_recursive_mkdir(&mut self, recursive_mkdir: bool) {
5848        self.recursive_mkdir = recursive_mkdir;
5849    }
5850
5851    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
5852        self.forbid_overwrite = forbid_overwrite;
5853    }
5854
5855    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
5856        self.notification_custom_parameters = notification_custom_parameters.into();
5857    }
5858}
5859
5860impl InputDescriptor for RenameObjectInput {
5861    fn operation(&self) -> &str {
5862        "RenameObject"
5863    }
5864
5865    fn bucket(&self) -> Result<&str, TosError> {
5866        Ok(&self.bucket)
5867    }
5868
5869    fn key(&self) -> Result<&str, TosError> {
5870        Ok(&self.key)
5871    }
5872}
5873
5874impl<B> InputTranslator<B> for RenameObjectInput {
5875    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
5876        if self.new_key == "" {
5877            return Err(TosError::client_error("empty new key"));
5878        }
5879        let mut request = self.trans_key()?;
5880        request.method = HttpMethodPut;
5881        if self.recursive_mkdir {
5882            request.header.insert(HEADER_RECURSIVE_MKDIR, self.recursive_mkdir.to_string());
5883        }
5884        if self.forbid_overwrite {
5885            request.header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
5886        }
5887        map_insert(&mut request.header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
5888        let mut query = HashMap::with_capacity(2);
5889        query.insert("rename", "".to_string());
5890        query.insert("name", self.new_key.to_string());
5891        request.query = Some(query);
5892        Ok(request)
5893    }
5894}
5895
5896#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
5897pub struct RenameObjectOutput {
5898    pub(crate) request_info: RequestInfo,
5899}
5900#[derive(Debug, Clone, PartialEq, Default, Serialize, GenericInput)]
5901pub struct RestoreObjectInput {
5902    #[serde(skip)]
5903    pub(crate) generic_input: GenericInput,
5904    #[serde(skip)]
5905    pub(crate) bucket: String,
5906    #[serde(skip)]
5907    pub(crate) key: String,
5908    #[serde(skip)]
5909    pub(crate) version_id: String,
5910    #[serde(rename = "Days")]
5911    #[serde(skip_serializing_if = "is_non_positive")]
5912    pub(crate) days: isize,
5913    #[serde(rename = "RestoreJobParameters")]
5914    #[serde(skip_serializing_if = "Option::is_none")]
5915    pub(crate) restore_job_parameters: Option<RestoreJobParameters>,
5916    #[serde(skip)]
5917    pub(crate) notification_custom_parameters: String,
5918}
5919impl RestoreObjectInput {
5920    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
5921        Self {
5922            generic_input: Default::default(),
5923            bucket: bucket.into(),
5924            key: key.into(),
5925            version_id: "".to_string(),
5926            days: 0,
5927            restore_job_parameters: None,
5928            notification_custom_parameters: "".to_string(),
5929        }
5930    }
5931    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
5932        Self {
5933            generic_input: Default::default(),
5934            bucket: bucket.into(),
5935            key: key.into(),
5936            version_id: version_id.into(),
5937            days: 0,
5938            restore_job_parameters: None,
5939            notification_custom_parameters: "".to_string(),
5940        }
5941    }
5942
5943    pub fn bucket(&self) -> &str {
5944        &self.bucket
5945    }
5946
5947    pub fn key(&self) -> &str {
5948        &self.key
5949    }
5950
5951    pub fn version_id(&self) -> &str {
5952        &self.version_id
5953    }
5954
5955    pub fn days(&self) -> isize {
5956        self.days
5957    }
5958
5959    pub fn restore_job_parameters(&self) -> &Option<RestoreJobParameters> {
5960        &self.restore_job_parameters
5961    }
5962
5963    pub fn notification_custom_parameters(&self) -> &str {
5964        &self.notification_custom_parameters
5965    }
5966
5967    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
5968        self.bucket = bucket.into();
5969    }
5970
5971    pub fn set_key(&mut self, key: impl Into<String>) {
5972        self.key = key.into();
5973    }
5974
5975    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
5976        self.version_id = version_id.into();
5977    }
5978
5979    pub fn set_days(&mut self, days: isize) {
5980        self.days = days;
5981    }
5982
5983    pub fn set_restore_job_parameters(&mut self, restore_job_parameters: impl Into<RestoreJobParameters>) {
5984        self.restore_job_parameters = Some(restore_job_parameters.into());
5985    }
5986
5987    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
5988        self.notification_custom_parameters = notification_custom_parameters.into();
5989    }
5990}
5991
5992impl InputDescriptor for RestoreObjectInput {
5993    fn operation(&self) -> &str {
5994        "RestoreObject"
5995    }
5996
5997    fn bucket(&self) -> Result<&str, TosError> {
5998        Ok(&self.bucket)
5999    }
6000
6001    fn key(&self) -> Result<&str, TosError> {
6002        Ok(&self.key)
6003    }
6004}
6005
6006impl<B> InputTranslator<B> for RestoreObjectInput
6007where
6008    B: BuildBufferReader,
6009{
6010    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6011        match serde_json::to_string(self) {
6012            Err(e) => Err(TosError::client_error_with_cause("trans json error", GenericError::JsonError(e.to_string()))),
6013            Ok(json) => {
6014                let mut request = self.trans_key()?;
6015                request.method = HttpMethodPost;
6016                map_insert(&mut request.header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
6017                let mut query = HashMap::with_capacity(2);
6018                query.insert("restore", "".to_string());
6019                map_insert(&mut query, QUERY_VERSION_ID, &self.version_id);
6020                request.query = Some(query);
6021                request.header.insert(HEADER_CONTENT_MD5, base64_md5(&json));
6022                let (body, len) = B::new(Bytes::from(json.into_bytes()))?;
6023                request.body = Some(body);
6024                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
6025                Ok(request)
6026            }
6027        }
6028    }
6029}
6030
6031
6032#[derive(Debug, Clone, PartialEq, Default, Serialize)]
6033pub struct RestoreJobParameters {
6034    #[serde(rename = "Tier")]
6035    #[serde(default)]
6036    pub(crate) tier: TierType,
6037}
6038
6039impl RestoreJobParameters {
6040    pub fn new(tier: impl Into<TierType>) -> Self {
6041        Self {
6042            tier: tier.into(),
6043        }
6044    }
6045
6046    pub fn tier(&self) -> &TierType {
6047        &self.tier
6048    }
6049
6050    pub fn set_tier(&mut self, tier: impl Into<TierType>) {
6051        self.tier = tier.into();
6052    }
6053}
6054#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
6055pub struct RestoreObjectOutput {
6056    pub(crate) request_info: RequestInfo,
6057}
6058
6059#[derive(
6060    Debug,
6061    Clone,
6062    HttpBasicHeader,
6063    AclHeader,
6064    GenericInput
6065)]
6066pub struct PutSymlinkInput {
6067    pub(crate) generic_input: GenericInput,
6068    pub(crate) bucket: String,
6069    pub(crate) key: String,
6070    pub(crate) symlink_target_key: String,
6071    pub(crate) symlink_target_bucket: String,
6072
6073    pub(crate) content_length: i64,
6074    pub(crate) cache_control: String,
6075    pub(crate) content_disposition: String,
6076    pub(crate) content_encoding: String,
6077    pub(crate) content_language: String,
6078    pub(crate) content_type: String,
6079    pub(crate) expires: Option<DateTime<Utc>>,
6080
6081    pub(crate) acl: Option<ACLType>,
6082    pub(crate) grant_full_control: String,
6083    pub(crate) grant_read: String,
6084    pub(crate) grant_read_acp: String,
6085    pub(crate) grant_write: String,
6086    pub(crate) grant_write_acp: String,
6087
6088    pub(crate) storage_class: Option<StorageClassType>,
6089    pub(crate) meta: HashMap<String, String>,
6090    pub(crate) forbid_overwrite: bool,
6091    pub(crate) tagging: String,
6092}
6093
6094impl PutSymlinkInput {
6095    pub fn new(bucket: impl Into<String>, key: impl Into<String>, symlink_target_key: impl Into<String>) -> Self {
6096        Self {
6097            generic_input: Default::default(),
6098            bucket: bucket.into(),
6099            key: key.into(),
6100            symlink_target_key: symlink_target_key.into(),
6101            symlink_target_bucket: "".to_string(),
6102            content_length: -1,
6103            cache_control: "".to_string(),
6104            content_disposition: "".to_string(),
6105            content_encoding: "".to_string(),
6106            content_language: "".to_string(),
6107            content_type: "".to_string(),
6108            expires: None,
6109            acl: None,
6110            grant_full_control: "".to_string(),
6111            grant_read: "".to_string(),
6112            grant_read_acp: "".to_string(),
6113            grant_write: "".to_string(),
6114            grant_write_acp: "".to_string(),
6115            storage_class: None,
6116            meta: Default::default(),
6117            forbid_overwrite: false,
6118            tagging: "".to_string(),
6119        }
6120    }
6121
6122    pub fn bucket(&self) -> &str {
6123        &self.bucket
6124    }
6125
6126    pub fn key(&self) -> &str {
6127        &self.key
6128    }
6129
6130    pub fn symlink_target_key(&self) -> &str {
6131        &self.symlink_target_key
6132    }
6133
6134    pub fn symlink_target_bucket(&self) -> &str {
6135        &self.symlink_target_bucket
6136    }
6137
6138    pub fn storage_class(&self) -> &Option<StorageClassType> {
6139        &self.storage_class
6140    }
6141
6142    pub fn meta(&self) -> &HashMap<String, String> {
6143        &self.meta
6144    }
6145
6146    pub fn forbid_overwrite(&self) -> bool {
6147        self.forbid_overwrite
6148    }
6149
6150    pub fn tagging(&self) -> &str {
6151        &self.tagging
6152    }
6153
6154    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6155        self.bucket = bucket.into();
6156    }
6157
6158    pub fn set_key(&mut self, key: impl Into<String>) {
6159        self.key = key.into();
6160    }
6161
6162    pub fn set_symlink_target_key(&mut self, symlink_target_key: impl Into<String>) {
6163        self.symlink_target_key = symlink_target_key.into();
6164    }
6165
6166    pub fn set_symlink_target_bucket(&mut self, symlink_target_bucket: impl Into<String>) {
6167        self.symlink_target_bucket = symlink_target_bucket.into();
6168    }
6169
6170    pub fn set_storage_class(&mut self, storage_class: impl Into<StorageClassType>) {
6171        self.storage_class = Some(storage_class.into());
6172    }
6173
6174    pub fn set_meta(&mut self, meta: impl Into<HashMap<String, String>>) {
6175        self.meta = meta.into();
6176    }
6177
6178    pub fn set_forbid_overwrite(&mut self, forbid_overwrite: bool) {
6179        self.forbid_overwrite = forbid_overwrite;
6180    }
6181
6182    pub fn set_tagging(&mut self, tagging: impl Into<String>) {
6183        self.tagging = tagging.into();
6184    }
6185}
6186
6187impl InputDescriptor for PutSymlinkInput {
6188    fn operation(&self) -> &str {
6189        "PutSymlink"
6190    }
6191
6192    fn bucket(&self) -> Result<&str, TosError> {
6193        Ok(&self.bucket)
6194    }
6195
6196    fn key(&self) -> Result<&str, TosError> {
6197        Ok(&self.key)
6198    }
6199}
6200
6201impl<B> InputTranslator<B> for PutSymlinkInput {
6202    fn trans(&self, config_holder: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6203        if self.symlink_target_key == "" {
6204            return Err(TosError::client_error("empty symlink target key"));
6205        }
6206
6207        let mut request = self.trans_key()?;
6208        request.method = HttpMethodPut;
6209        let header = &mut request.header;
6210        set_http_basic_header(header, config_holder.disable_encoding_meta, self);
6211        set_acl_header(header, self);
6212        request.meta = trans_meta(&self.meta, config_holder.disable_encoding_meta);
6213        if let Some(storage_class) = &self.storage_class {
6214            header.insert(HEADER_STORAGE_CLASS, storage_class.as_str().to_string());
6215        }
6216        if self.forbid_overwrite {
6217            header.insert(HEADER_FORBID_OVERWRITE, self.forbid_overwrite.to_string());
6218        }
6219        map_insert(header, HEADER_TAGGING, &self.tagging);
6220        map_insert(header, HEADER_SYMLINK_TARGET, url_encode_with_safe(&self.symlink_target_key, "/").as_str());
6221        map_insert(header, HEADER_SYMLINK_BUCKET, &self.symlink_target_bucket);
6222        let mut query = HashMap::with_capacity(2);
6223        query.insert("symlink", "".to_string());
6224        request.query = Some(query);
6225        Ok(request)
6226    }
6227}
6228#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
6229pub struct PutSymlinkOutput {
6230    pub(crate) request_info: RequestInfo,
6231    pub(crate) version_id: String,
6232}
6233
6234impl PutSymlinkOutput {
6235    pub fn version_id(&self) -> &str {
6236        &self.version_id
6237    }
6238}
6239
6240#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
6241pub struct GetSymlinkInput {
6242    pub(crate) generic_input: GenericInput,
6243    pub(crate) bucket: String,
6244    pub(crate) key: String,
6245    pub(crate) version_id: String,
6246}
6247
6248impl GetSymlinkInput {
6249    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
6250        Self {
6251            generic_input: Default::default(),
6252            bucket: bucket.into(),
6253            key: key.into(),
6254            version_id: "".to_string(),
6255        }
6256    }
6257    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
6258        Self {
6259            generic_input: Default::default(),
6260            bucket: bucket.into(),
6261            key: key.into(),
6262            version_id: version_id.into(),
6263        }
6264    }
6265    pub fn bucket(&self) -> &str {
6266        &self.bucket
6267    }
6268    pub fn key(&self) -> &str {
6269        &self.key
6270    }
6271    pub fn version_id(&self) -> &str {
6272        &self.version_id
6273    }
6274    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6275        self.bucket = bucket.into();
6276    }
6277    pub fn set_key(&mut self, key: impl Into<String>) {
6278        self.key = key.into();
6279    }
6280    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
6281        self.version_id = version_id.into();
6282    }
6283}
6284
6285impl InputDescriptor for GetSymlinkInput {
6286    fn operation(&self) -> &str {
6287        "GetSymlink"
6288    }
6289    fn bucket(&self) -> Result<&str, TosError> {
6290        Ok(&self.bucket)
6291    }
6292    fn key(&self) -> Result<&str, TosError> {
6293        Ok(&self.key)
6294    }
6295}
6296
6297impl<B> InputTranslator<B> for GetSymlinkInput {
6298    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6299        let mut request = self.trans_key()?;
6300        request.method = HttpMethodGet;
6301        let mut query = HashMap::with_capacity(2);
6302        query.insert("symlink", "".to_string());
6303        if self.version_id != "" {
6304            query.insert(QUERY_VERSION_ID, self.version_id.to_string());
6305        }
6306        request.query = Some(query);
6307        Ok(request)
6308    }
6309}
6310
6311#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
6312pub struct GetSymlinkOutput {
6313    pub(crate) request_info: RequestInfo,
6314    pub(crate) version_id: String,
6315    pub(crate) symlink_target_key: String,
6316    pub(crate) symlink_target_bucket: String,
6317    pub(crate) etag: String,
6318    pub(crate) last_modified: Option<DateTime<Utc>>,
6319}
6320
6321impl GetSymlinkOutput {
6322    pub fn request_info(&self) -> &RequestInfo {
6323        &self.request_info
6324    }
6325
6326    pub fn version_id(&self) -> &str {
6327        &self.version_id
6328    }
6329
6330    pub fn symlink_target_key(&self) -> &str {
6331        &self.symlink_target_key
6332    }
6333
6334    pub fn symlink_target_bucket(&self) -> &str {
6335        &self.symlink_target_bucket
6336    }
6337    pub fn etag(&self) -> &str {
6338        &self.etag
6339    }
6340    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
6341        self.last_modified
6342    }
6343}
6344#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
6345pub struct GetFileStatusInput {
6346    pub(crate) generic_input: GenericInput,
6347    pub(crate) bucket: String,
6348    pub(crate) key: String,
6349}
6350
6351impl GetFileStatusInput {
6352    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
6353        Self {
6354            generic_input: Default::default(),
6355            bucket: bucket.into(),
6356            key: key.into(),
6357        }
6358    }
6359    pub fn bucket(&self) -> &str {
6360        &self.bucket
6361    }
6362    pub fn key(&self) -> &str {
6363        &self.key
6364    }
6365    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6366        self.bucket = bucket.into();
6367    }
6368    pub fn set_key(&mut self, key: impl Into<String>) {
6369        self.key = key.into();
6370    }
6371}
6372
6373impl InputDescriptor for GetFileStatusInput {
6374    fn operation(&self) -> &str {
6375        "GetFileStatus"
6376    }
6377    fn bucket(&self) -> Result<&str, TosError> {
6378        Ok(&self.bucket)
6379    }
6380    fn key(&self) -> Result<&str, TosError> {
6381        Ok(&self.key)
6382    }
6383}
6384
6385impl<B> InputTranslator<B> for GetFileStatusInput {
6386    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6387        let mut request = self.trans_key()?;
6388        request.method = HttpMethodGet;
6389        let mut query = HashMap::with_capacity(2);
6390        query.insert("stat", "".to_string());
6391        request.query = Some(query);
6392        Ok(request)
6393    }
6394}
6395#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
6396pub struct GetFileStatusOutput {
6397    #[serde(skip)]
6398    pub(crate) request_info: RequestInfo,
6399    #[serde(rename = "Key")]
6400    #[serde(default)]
6401    pub(crate) key: String,
6402    #[serde(rename = "Size")]
6403    #[serde(default)]
6404    pub(crate) size: i64,
6405    #[serde(rename = "LastModified")]
6406    #[serde(default)]
6407    pub(crate) last_modified_string: Option<String>,
6408    #[serde(skip)]
6409    pub(crate) last_modified: Option<DateTime<Utc>>,
6410    #[serde(rename = "CRC32")]
6411    #[serde(default)]
6412    pub(crate) crc32: String,
6413    #[serde(rename = "CRC64")]
6414    #[serde(default)]
6415    pub(crate) crc64: String,
6416    #[serde(rename = "ETag")]
6417    #[serde(default)]
6418    pub(crate) etag: String,
6419    #[serde(rename = "Type")]
6420    #[serde(default)]
6421    pub(crate) object_type: String,
6422}
6423
6424impl GetFileStatusOutput {
6425    pub fn key(&self) -> &str {
6426        &self.key
6427    }
6428
6429    pub fn size(&self) -> i64 {
6430        self.size
6431    }
6432
6433    pub fn last_modified(&self) -> Option<DateTime<Utc>> {
6434        self.last_modified
6435    }
6436
6437    pub fn crc32(&self) -> &str {
6438        &self.crc32
6439    }
6440
6441    pub fn crc64(&self) -> &str {
6442        &self.crc64
6443    }
6444
6445    pub fn etag(&self) -> &str {
6446        &self.etag
6447    }
6448
6449    pub fn object_type(&self) -> &str {
6450        &self.object_type
6451    }
6452}
6453#[derive(Debug, Clone, GenericInput)]
6454#[handle_content]
6455pub(crate) struct ModifyObjectInput<B> {
6456    pub(crate) generic_input: GenericInput,
6457    pub(crate) bucket: String,
6458    pub(crate) key: String,
6459    pub(crate) offset: i64,
6460    pub(crate) content: Arc<RefCell<Option<B>>>,
6461
6462    pub(crate) content_length: i64,
6463    pub(crate) traffic_limit: i64,
6464    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
6465    pub(crate) notification_custom_parameters: String,
6466    pub(crate) if_match: String,
6467
6468    pub(crate) pre_hash_crc64ecma: u64,
6469}
6470
6471unsafe impl<B> Sync for ModifyObjectInput<B> {}
6472
6473unsafe impl<B> Send for ModifyObjectInput<B> {}
6474
6475impl<B> Default for ModifyObjectInput<B> {
6476    fn default() -> Self {
6477        Self {
6478            generic_input: Default::default(),
6479            bucket: "".to_string(),
6480            key: "".to_string(),
6481            offset: 0,
6482            content: Arc::new(RefCell::new(None)),
6483            content_length: -1,
6484            traffic_limit: 0,
6485            async_data_transfer_listener: None,
6486            notification_custom_parameters: "".to_string(),
6487            if_match: "".to_string(),
6488            pre_hash_crc64ecma: 0,
6489        }
6490    }
6491}
6492
6493impl<B> ModifyObjectInput<B>
6494{
6495    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
6496        let mut input = Self::default();
6497        input.bucket = bucket.into();
6498        input.key = key.into();
6499        input
6500    }
6501
6502    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl Into<B>) -> Self {
6503        let mut input = Self::default();
6504        input.bucket = bucket.into();
6505        input.key = key.into();
6506        input.set_content(content);
6507        input
6508    }
6509    pub fn bucket(&self) -> &str {
6510        &self.bucket
6511    }
6512    pub fn key(&self) -> &str {
6513        &self.key
6514    }
6515    pub fn content(&self) -> Ref<Option<B>> {
6516        self.content.borrow()
6517    }
6518
6519    pub fn offset(&self) -> i64 {
6520        self.offset
6521    }
6522
6523    pub fn content_length(&self) -> i64 {
6524        self.content_length
6525    }
6526
6527    pub fn traffic_limit(&self) -> i64 {
6528        self.traffic_limit
6529    }
6530
6531    pub fn notification_custom_parameters(&self) -> &str {
6532        &self.notification_custom_parameters
6533    }
6534    pub fn if_match(&self) -> &str {
6535        &self.if_match
6536    }
6537
6538    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6539        self.bucket = bucket.into();
6540    }
6541
6542    pub fn set_key(&mut self, key: impl Into<String>) {
6543        self.key = key.into();
6544    }
6545
6546    pub fn set_offset(&mut self, offset: i64) {
6547        self.offset = offset;
6548    }
6549
6550    pub fn set_content(&mut self, content: impl Into<B>)
6551    {
6552        self.content = Arc::new(RefCell::new(Some(content.into())));
6553    }
6554
6555    pub fn set_content_length(&mut self, content_length: i64) {
6556        self.content_length = content_length;
6557    }
6558
6559    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
6560        self.traffic_limit = traffic_limit;
6561    }
6562
6563    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
6564        self.notification_custom_parameters = notification_custom_parameters.into();
6565    }
6566
6567    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
6568        self.if_match = if_match.into();
6569    }
6570}
6571
6572impl<B> InputDescriptor for ModifyObjectInput<B> {
6573    fn operation(&self) -> &str {
6574        "ModifyObject"
6575    }
6576
6577    fn bucket(&self) -> Result<&str, TosError> {
6578        Ok(&self.bucket)
6579    }
6580
6581    fn key(&self) -> Result<&str, TosError> {
6582        Ok(&self.key)
6583    }
6584}
6585
6586impl<B> InputTranslator<B> for ModifyObjectInput<B> {
6587    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6588        if self.offset < 0
6589        {
6590            return Err(TosError::client_error("invalid offset for modify object"));
6591        }
6592        let mut request = self.trans_key()?;
6593        request.method = HttpMethodPost;
6594
6595        if let Some(ref adts) = self.async_data_transfer_listener {
6596            if request.request_context.is_some() {
6597                request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
6598            } else {
6599                let mut rc = RequestContext::default();
6600                rc.async_data_transfer_listener = Some(adts.clone());
6601                request.request_context = Some(rc);
6602            }
6603        }
6604
6605        if self.pre_hash_crc64ecma > 0 {
6606            if request.request_context.is_some() {
6607                request.request_context.as_mut().unwrap().init_crc64 = Some(self.pre_hash_crc64ecma);
6608            } else {
6609                let mut rc = RequestContext::default();
6610                rc.init_crc64 = Some(self.pre_hash_crc64ecma);
6611                request.request_context = Some(rc);
6612            }
6613        }
6614
6615        let header = &mut request.header;
6616        if self.content_length >= 0 {
6617            header.insert(HEADER_CONTENT_LENGTH, self.content_length.to_string());
6618        }
6619        if self.traffic_limit > 0 {
6620            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
6621        }
6622        map_insert(header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
6623        map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
6624        let mut query = HashMap::with_capacity(2);
6625        query.insert("modify", "".to_string());
6626        query.insert(QUERY_OFFSET, self.offset.to_string());
6627        request.query = Some(query);
6628        request.body = self.content.take();
6629        Ok(request)
6630    }
6631}
6632#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
6633pub(crate) struct ModifyObjectOutput {
6634    pub(crate) request_info: RequestInfo,
6635    pub(crate) next_modify_offset: i64,
6636    pub(crate) hash_crc64ecma: u64,
6637}
6638
6639impl ModifyObjectOutput {
6640    pub fn next_modify_offset(&self) -> i64 {
6641        self.next_modify_offset
6642    }
6643
6644    pub fn hash_crc64ecma(&self) -> u64 {
6645        self.hash_crc64ecma
6646    }
6647}
6648
6649#[derive(Debug, Clone, GenericInput)]
6650pub(crate) struct ModifyObjectFromBufferInput {
6651    pub(crate) generic_input: GenericInput,
6652    pub(crate) bucket: String,
6653    pub(crate) key: String,
6654    pub(crate) offset: i64,
6655    pub(crate) content: Option<MultiBytes>,
6656
6657    pub(crate) content_length: i64,
6658    pub(crate) traffic_limit: i64,
6659    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
6660    pub(crate) notification_custom_parameters: String,
6661    pub(crate) if_match: String,
6662
6663    pub(crate) pre_hash_crc64ecma: u64,
6664}
6665
6666impl Default for ModifyObjectFromBufferInput {
6667    fn default() -> Self {
6668        Self {
6669            generic_input: Default::default(),
6670            bucket: "".to_string(),
6671            key: "".to_string(),
6672            offset: 0,
6673            content: None,
6674            content_length: -1,
6675            traffic_limit: 0,
6676            async_data_transfer_listener: None,
6677            notification_custom_parameters: "".to_string(),
6678            if_match: "".to_string(),
6679            pre_hash_crc64ecma: 0,
6680        }
6681    }
6682}
6683
6684impl ModifyObjectFromBufferInput {
6685    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
6686        let mut input = Self::default();
6687        input.bucket = bucket.into();
6688        input.key = key.into();
6689        input
6690    }
6691    pub fn new_with_offset(bucket: impl Into<String>, key: impl Into<String>, offset: i64) -> Self {
6692        let mut input = Self::default();
6693        input.bucket = bucket.into();
6694        input.key = key.into();
6695        input.offset = offset;
6696        input
6697    }
6698    pub fn new_with_content(bucket: impl Into<String>, key: impl Into<String>, content: impl AsRef<[u8]>) -> Self {
6699        let mut input = Self::default();
6700        input.bucket = bucket.into();
6701        input.key = key.into();
6702        input.set_content(content);
6703        input
6704    }
6705    pub fn new_with_offset_content(bucket: impl Into<String>, key: impl Into<String>, offset: i64, content: impl AsRef<[u8]>) -> Self {
6706        let mut input = Self::default();
6707        input.bucket = bucket.into();
6708        input.key = key.into();
6709        input.offset = offset;
6710        input.set_content(content);
6711        input
6712    }
6713    pub fn bucket(&self) -> &str {
6714        &self.bucket
6715    }
6716    pub fn key(&self) -> &str {
6717        &self.key
6718    }
6719    pub fn content(&self) -> Option<impl Iterator<Item=&Bytes>> {
6720        match &self.content {
6721            None => None,
6722            Some(x) => Some(x.inner.iter()),
6723        }
6724    }
6725    pub fn offset(&self) -> i64 {
6726        self.offset
6727    }
6728
6729    pub fn content_length(&self) -> i64 {
6730        self.content_length
6731    }
6732
6733    pub fn traffic_limit(&self) -> i64 {
6734        self.traffic_limit
6735    }
6736
6737    pub fn notification_custom_parameters(&self) -> &str {
6738        &self.notification_custom_parameters
6739    }
6740    pub fn if_match(&self) -> &str {
6741        &self.if_match
6742    }
6743
6744    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6745        self.bucket = bucket.into();
6746    }
6747
6748    pub fn set_key(&mut self, key: impl Into<String>) {
6749        self.key = key.into();
6750    }
6751
6752    pub fn set_offset(&mut self, offset: i64) {
6753        self.offset = offset;
6754    }
6755    pub fn set_content_with_bytes_list(&mut self, bytes_list: impl Iterator<Item=impl Into<Bytes>>) {
6756        let mut list = LinkedList::new();
6757        let mut size = 0;
6758        for item in bytes_list {
6759            let item = item.into();
6760            size += item.len();
6761            list.push_back(item);
6762        }
6763        self.content = Some(MultiBytes::new(list, size));
6764    }
6765    pub fn set_content(&mut self, content: impl AsRef<[u8]>) {
6766        let item = content.as_ref().to_owned();
6767        let size = item.len();
6768        let mut list = LinkedList::new();
6769        list.push_back(Bytes::from(item));
6770        self.content = Some(MultiBytes::new(list, size));
6771    }
6772    pub fn append_content(&mut self, content: impl AsRef<[u8]>) {
6773        if let Some(contents) = &mut self.content {
6774            contents.push(Bytes::from(content.as_ref().to_owned()));
6775        } else {
6776            self.set_content(content);
6777        }
6778    }
6779    pub fn set_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
6780        let item = content.into();
6781        let size = item.len();
6782        let mut list = LinkedList::new();
6783        list.push_back(Bytes::from(item));
6784        self.content = Some(MultiBytes::new(list, size));
6785    }
6786
6787    pub fn append_content_nocopy(&mut self, content: impl Into<Vec<u8>>) {
6788        if let Some(contents) = &mut self.content {
6789            contents.push(Bytes::from(content.into()));
6790        } else {
6791            self.set_content_nocopy(content);
6792        }
6793    }
6794    pub fn set_content_length(&mut self, content_length: i64) {
6795        self.content_length = content_length;
6796    }
6797
6798    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
6799        self.traffic_limit = traffic_limit;
6800    }
6801
6802    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
6803        self.notification_custom_parameters = notification_custom_parameters.into();
6804    }
6805    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
6806        self.if_match = if_match.into();
6807    }
6808}
6809
6810impl InputDescriptor for ModifyObjectFromBufferInput {
6811    fn operation(&self) -> &str {
6812        "ModifyObjectFromBuffer"
6813    }
6814    fn bucket(&self) -> Result<&str, TosError> {
6815        Ok(&self.bucket)
6816    }
6817    fn key(&self) -> Result<&str, TosError> {
6818        Ok(&self.key)
6819    }
6820}
6821
6822impl<B> InputTranslator<B> for ModifyObjectFromBufferInput
6823where
6824    B: BuildMultiBufferReader,
6825{
6826    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
6827        if self.offset < 0
6828        {
6829            return Err(TosError::client_error("invalid offset for modify object"));
6830        }
6831        let mut request = self.trans_key()?;
6832        request.method = HttpMethodPost;
6833
6834        if let Some(ref adts) = self.async_data_transfer_listener {
6835            if request.request_context.is_some() {
6836                request.request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
6837            } else {
6838                let mut rc = RequestContext::default();
6839                rc.async_data_transfer_listener = Some(adts.clone());
6840                request.request_context = Some(rc);
6841            }
6842        }
6843
6844        if self.pre_hash_crc64ecma > 0 {
6845            if request.request_context.is_some() {
6846                request.request_context.as_mut().unwrap().init_crc64 = Some(self.pre_hash_crc64ecma);
6847            } else {
6848                let mut rc = RequestContext::default();
6849                rc.init_crc64 = Some(self.pre_hash_crc64ecma);
6850                request.request_context = Some(rc);
6851            }
6852        }
6853
6854        let header = &mut request.header;
6855        if self.content_length >= 0 {
6856            header.insert(HEADER_CONTENT_LENGTH, self.content_length.to_string());
6857        }
6858        if self.traffic_limit > 0 {
6859            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
6860        }
6861        map_insert(header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
6862        map_insert(header, HEADER_X_IF_MATCH, &self.if_match);
6863        let mut query = HashMap::with_capacity(2);
6864        query.insert("modify", "".to_string());
6865        query.insert(QUERY_OFFSET, self.offset.to_string());
6866        request.query = Some(query);
6867        if let Some(content) = &self.content {
6868            let (body, len) = B::new(content.clone())?;
6869            request.body = Some(body);
6870            if self.content_length < 0 {
6871                request.header.insert(HEADER_CONTENT_LENGTH, len.to_string());
6872            }
6873        }
6874        Ok(request)
6875    }
6876}
6877
6878#[derive(Debug, Clone, GenericInput)]
6879pub(crate) struct ModifyObjectFromFileInput {
6880    pub(crate) generic_input: GenericInput,
6881    pub(crate) bucket: String,
6882    pub(crate) key: String,
6883    pub(crate) offset: i64,
6884    pub(crate) file_path: String,
6885
6886    pub(crate) content_length: i64,
6887    pub(crate) traffic_limit: i64,
6888    pub(crate) async_data_transfer_listener: Option<async_channel::Sender<DataTransferStatus>>,
6889    pub(crate) notification_custom_parameters: String,
6890    pub(crate) if_match: String,
6891
6892    pub(crate) pre_hash_crc64ecma: u64,
6893}
6894
6895impl Default for ModifyObjectFromFileInput {
6896    fn default() -> Self {
6897        Self {
6898            generic_input: Default::default(),
6899            bucket: "".to_string(),
6900            key: "".to_string(),
6901            offset: 0,
6902            file_path: "".to_string(),
6903            content_length: -1,
6904            traffic_limit: 0,
6905            async_data_transfer_listener: None,
6906            notification_custom_parameters: "".to_string(),
6907            if_match: "".to_string(),
6908            pre_hash_crc64ecma: 0,
6909        }
6910    }
6911}
6912
6913impl ModifyObjectFromFileInput {
6914    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
6915        let mut input = Self::default();
6916        input.bucket = bucket.into();
6917        input.key = key.into();
6918        input
6919    }
6920    pub fn new_with_offset(bucket: impl Into<String>, key: impl Into<String>, offset: i64) -> Self {
6921        let mut input = Self::default();
6922        input.bucket = bucket.into();
6923        input.key = key.into();
6924        input.offset = offset;
6925        input
6926    }
6927    pub fn new_with_file_path(bucket: impl Into<String>, key: impl Into<String>, file_path: impl Into<String>) -> Self {
6928        let mut input = Self::default();
6929        input.bucket = bucket.into();
6930        input.key = key.into();
6931        input.file_path = file_path.into();
6932        input
6933    }
6934    pub fn new_with_offset_content(bucket: impl Into<String>, key: impl Into<String>, offset: i64, file_path: impl Into<String>) -> Self {
6935        let mut input = Self::default();
6936        input.bucket = bucket.into();
6937        input.key = key.into();
6938        input.offset = offset;
6939        input.file_path = file_path.into();
6940        input
6941    }
6942    pub fn bucket(&self) -> &str {
6943        &self.bucket
6944    }
6945    pub fn key(&self) -> &str {
6946        &self.key
6947    }
6948    pub fn file_path(&self) -> &str {
6949        &self.file_path
6950    }
6951    pub fn offset(&self) -> i64 {
6952        self.offset
6953    }
6954
6955    pub fn content_length(&self) -> i64 {
6956        self.content_length
6957    }
6958
6959    pub fn traffic_limit(&self) -> i64 {
6960        self.traffic_limit
6961    }
6962
6963    pub fn notification_custom_parameters(&self) -> &str {
6964        &self.notification_custom_parameters
6965    }
6966    pub fn if_match(&self) -> &str {
6967        &self.if_match
6968    }
6969
6970    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
6971        self.bucket = bucket.into();
6972    }
6973
6974    pub fn set_key(&mut self, key: impl Into<String>) {
6975        self.key = key.into();
6976    }
6977
6978    pub fn set_offset(&mut self, offset: i64) {
6979        self.offset = offset;
6980    }
6981    pub fn set_file_path(&mut self, file_path: impl Into<String>) {
6982        self.file_path = file_path.into();
6983    }
6984    pub fn set_content_length(&mut self, content_length: i64) {
6985        self.content_length = content_length;
6986    }
6987
6988    pub fn set_traffic_limit(&mut self, traffic_limit: i64) {
6989        self.traffic_limit = traffic_limit;
6990    }
6991
6992    pub fn set_notification_custom_parameters(&mut self, notification_custom_parameters: impl Into<String>) {
6993        self.notification_custom_parameters = notification_custom_parameters.into();
6994    }
6995    pub fn set_if_match(&mut self, if_match: impl Into<String>) {
6996        self.if_match = if_match.into();
6997    }
6998
6999    pub(crate) fn inner_trans<'a>(&self) -> Result<(HttpMethodType, Option<RequestContext<'a>>, HashMap<&'a str, String>,
7000                                                    Option<HashMap<&'a str, String>>,), TosError> {
7001        if self.offset < 0
7002        {
7003            return Err(TosError::client_error("invalid offset for modify object"));
7004        }
7005
7006        let mut request_context: Option<RequestContext<'a>> = None;
7007        if let Some(ref adts) = self.async_data_transfer_listener {
7008            if request_context.is_some() {
7009                request_context.as_mut().unwrap().async_data_transfer_listener = Some(adts.clone());
7010            } else {
7011                let mut rc = RequestContext::default();
7012                rc.async_data_transfer_listener = Some(adts.clone());
7013                request_context = Some(rc);
7014            }
7015        }
7016
7017        if self.pre_hash_crc64ecma > 0 {
7018            if request_context.is_some() {
7019                request_context.as_mut().unwrap().init_crc64 = Some(self.pre_hash_crc64ecma);
7020            } else {
7021                let mut rc = RequestContext::default();
7022                rc.init_crc64 = Some(self.pre_hash_crc64ecma);
7023                request_context = Some(rc);
7024            }
7025        }
7026
7027        let mut header = HashMap::new();
7028        if self.content_length >= 0 {
7029            header.insert(HEADER_CONTENT_LENGTH, self.content_length.to_string());
7030        }
7031        if self.traffic_limit > 0 {
7032            header.insert(HEADER_TRAFFIC_LIMIT, self.traffic_limit.to_string());
7033        }
7034        map_insert(&mut header, HEADER_NOTIFICATION_CUSTOM_PARAMETERS, &self.notification_custom_parameters);
7035        map_insert(&mut header, HEADER_X_IF_MATCH, &self.if_match);
7036        let mut query = HashMap::with_capacity(2);
7037        query.insert("modify", "".to_string());
7038        query.insert(QUERY_OFFSET, self.offset.to_string());
7039        Ok((HttpMethodPost, request_context, header, Some(query)))
7040    }
7041}
7042
7043impl InputDescriptor for ModifyObjectFromFileInput {
7044    fn operation(&self) -> &str {
7045        "ModifyObjectFromFile"
7046    }
7047    fn bucket(&self) -> Result<&str, TosError> {
7048        Ok(&self.bucket)
7049    }
7050    fn key(&self) -> Result<&str, TosError> {
7051        Ok(&self.key)
7052    }
7053}
7054
7055impl<B> InputTranslator<B> for ModifyObjectFromFileInput
7056where
7057    B: BuildFileReader,
7058{
7059    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
7060        let mut request = self.trans_key()?;
7061        let (method, request_context, header, query) = self.inner_trans()?;
7062        request.method = method;
7063        request.request_context = request_context;
7064        request.header = header;
7065        request.query = query;
7066        if self.file_path != "" {
7067            let (body, len) = B::new(&self.file_path)?;
7068            request.body = Some(body);
7069            if let Some(l) = len {
7070                if self.content_length < 0 {
7071                    request.header.insert(HEADER_CONTENT_LENGTH, l.to_string());
7072                }
7073            }
7074        }
7075        Ok(request)
7076    }
7077}
7078
7079#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
7080pub struct DoesObjectExistInput {
7081    pub(crate) generic_input: GenericInput,
7082    pub(crate) bucket: String,
7083    pub(crate) key: String,
7084    pub(crate) version_id: String,
7085    // todo xsj 支持该参数
7086    pub(crate) is_only_in_tos: bool,
7087}
7088
7089impl DoesObjectExistInput {
7090    pub fn new(bucket: impl Into<String>, key: impl Into<String>) -> Self {
7091        Self {
7092            generic_input: Default::default(),
7093            bucket: bucket.into(),
7094            key: key.into(),
7095            version_id: "".to_string(),
7096            is_only_in_tos: false,
7097        }
7098    }
7099
7100    pub fn new_with_version_id(bucket: impl Into<String>, key: impl Into<String>, version_id: impl Into<String>) -> Self {
7101        Self {
7102            generic_input: Default::default(),
7103            bucket: bucket.into(),
7104            key: key.into(),
7105            version_id: version_id.into(),
7106            is_only_in_tos: false,
7107        }
7108    }
7109
7110    pub fn bucket(&self) -> &str {
7111        &self.bucket
7112    }
7113
7114    pub fn key(&self) -> &str {
7115        &self.key
7116    }
7117
7118    pub fn version_id(&self) -> &str {
7119        &self.version_id
7120    }
7121
7122    pub(crate) fn is_only_in_tos(&self) -> bool {
7123        self.is_only_in_tos
7124    }
7125
7126    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
7127        self.bucket = bucket.into();
7128    }
7129
7130    pub fn set_key(&mut self, key: impl Into<String>) {
7131        self.key = key.into();
7132    }
7133
7134    pub fn set_version_id(&mut self, version_id: impl Into<String>) {
7135        self.version_id = version_id.into();
7136    }
7137
7138    pub(crate) fn set_is_only_in_tos(&mut self, is_only_in_tos: bool) {
7139        self.is_only_in_tos = is_only_in_tos;
7140    }
7141}
7142#[derive(Debug, Clone, PartialEq, Default, GenericInput)]
7143pub struct SetObjectTimeInput {
7144    pub(crate) generic_input: GenericInput,
7145    pub(crate) bucket: String,
7146    pub(crate) key: String,
7147    pub(crate) modify_timestamp: DateTime<Utc>,
7148}
7149
7150impl SetObjectTimeInput {
7151    pub fn new(bucket: impl Into<String>, key: impl Into<String>, modify_timestamp: impl Into<DateTime<Utc>>) -> Self {
7152        Self {
7153            generic_input: Default::default(),
7154            bucket: bucket.into(),
7155            key: key.into(),
7156            modify_timestamp: modify_timestamp.into(),
7157        }
7158    }
7159
7160    pub fn bucket(&self) -> &str {
7161        &self.bucket
7162    }
7163
7164    pub fn key(&self) -> &str {
7165        &self.key
7166    }
7167
7168    pub fn modify_timestamp(&self) -> DateTime<Utc> {
7169        self.modify_timestamp
7170    }
7171
7172    pub fn set_bucket(&mut self, bucket: impl Into<String>) {
7173        self.bucket = bucket.into();
7174    }
7175
7176    pub fn set_key(&mut self, key: impl Into<String>) {
7177        self.key = key.into();
7178    }
7179
7180    pub fn set_modify_timestamp(&mut self, modify_timestamp: impl Into<DateTime<Utc>>) {
7181        self.modify_timestamp = modify_timestamp.into();
7182    }
7183}
7184
7185impl InputDescriptor for SetObjectTimeInput {
7186    fn operation(&self) -> &str {
7187        "SetObjectTime"
7188    }
7189
7190    fn bucket(&self) -> Result<&str, TosError> {
7191        Ok(&self.bucket)
7192    }
7193
7194    fn key(&self) -> Result<&str, TosError> {
7195        Ok(&self.key)
7196    }
7197}
7198
7199impl<B> InputTranslator<B> for SetObjectTimeInput {
7200    fn trans(&self, _: Arc<ConfigHolder>) -> Result<HttpRequest<B>, TosError> {
7201        let mut request = self.trans_key()?;
7202        request.method = HttpMethodPost;
7203        let seconds = self.modify_timestamp.timestamp();
7204        let ns = self.modify_timestamp.timestamp_subsec_nanos();
7205        request.header.insert(HEADER_MODIFY_TIMESTAMP, seconds.to_string());
7206        request.header.insert(HEADER_MODIFY_TIMESTAMP_NS, ns.to_string());
7207
7208        let mut query = HashMap::with_capacity(1);
7209        query.insert("time", "".to_string());
7210        request.query = Some(query);
7211        Ok(request)
7212    }
7213}
7214
7215#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
7216pub struct SetObjectTimeOutput {
7217    pub(crate) request_info: RequestInfo,
7218}