@@ -23,12 +23,13 @@ use crate::s3::response::{
2323 CopyObjectInternalResponse , CopyObjectResponse , CreateMultipartUploadResponse ,
2424 StatObjectResponse , UploadPartCopyResponse ,
2525} ;
26+ use crate :: s3:: response_traits:: HasChecksumHeaders ;
2627use crate :: s3:: response_traits:: HasEtagFromBody ;
2728use crate :: s3:: sse:: { Sse , SseCustomerKey } ;
2829use crate :: s3:: types:: { Directive , PartInfo , Retention , S3Api , S3Request , ToS3Request } ;
2930use crate :: s3:: utils:: {
30- UtcTime , check_bucket_name, check_object_name, check_sse, check_ssec, to_http_header_value ,
31- to_iso8601utc, url_encode,
31+ ChecksumAlgorithm , UtcTime , check_bucket_name, check_object_name, check_sse, check_ssec,
32+ to_http_header_value , to_iso8601utc, url_encode,
3233} ;
3334use async_recursion:: async_recursion;
3435use http:: Method ;
@@ -59,6 +60,13 @@ pub struct UploadPartCopy {
5960 part_number : u16 ,
6061 #[ builder( default ) ]
6162 headers : Multimap ,
63+ /// Optional checksum algorithm for data integrity verification during part copy.
64+ ///
65+ /// When specified, the server computes a checksum of the copied part data using
66+ /// this algorithm. Use the same algorithm for all parts in a multipart upload.
67+ /// Supported algorithms: CRC32, CRC32C, SHA1, SHA256, CRC64NVME.
68+ #[ builder( default , setter( into) ) ]
69+ checksum_algorithm : Option < crate :: s3:: utils:: ChecksumAlgorithm > ,
6270}
6371
6472impl S3Api for UploadPartCopy {
@@ -78,6 +86,7 @@ pub type UploadPartCopyBldr = UploadPartCopyBuilder<(
7886 ( String , ) ,
7987 ( ) ,
8088 ( ) ,
89+ ( ) ,
8190) > ;
8291
8392impl ToS3Request for UploadPartCopy {
@@ -100,6 +109,10 @@ impl ToS3Request for UploadPartCopy {
100109 let mut headers: Multimap = self . extra_headers . unwrap_or_default ( ) ;
101110 headers. add_multimap ( self . headers ) ;
102111
112+ if let Some ( algorithm) = self . checksum_algorithm {
113+ headers. add ( X_AMZ_CHECKSUM_ALGORITHM , algorithm. as_str ( ) . to_string ( ) ) ;
114+ }
115+
103116 let mut query_params: Multimap = self . extra_query_params . unwrap_or_default ( ) ;
104117 {
105118 query_params. add ( "partNumber" , self . part_number . to_string ( ) ) ;
@@ -150,6 +163,8 @@ pub struct CopyObjectInternal {
150163 metadata_directive : Option < Directive > ,
151164 #[ builder( default , setter( into) ) ]
152165 tagging_directive : Option < Directive > ,
166+ #[ builder( default , setter( into) ) ]
167+ checksum_algorithm : Option < crate :: s3:: utils:: ChecksumAlgorithm > ,
153168}
154169
155170impl S3Api for CopyObjectInternal {
@@ -175,6 +190,7 @@ pub type CopyObjectInternalBldr = CopyObjectInternalBuilder<(
175190 ( ) ,
176191 ( ) ,
177192 ( ) ,
193+ ( ) ,
178194) > ;
179195
180196impl ToS3Request for CopyObjectInternal {
@@ -261,6 +277,10 @@ impl ToS3Request for CopyObjectInternal {
261277 if let Some ( v) = self . source . ssec {
262278 headers. add_multimap ( v. copy_headers ( ) ) ;
263279 }
280+
281+ if let Some ( algorithm) = self . checksum_algorithm {
282+ headers. add ( X_AMZ_CHECKSUM_ALGORITHM , algorithm. as_str ( ) . to_string ( ) ) ;
283+ }
264284 } ;
265285
266286 Ok ( S3Request :: builder ( )
@@ -310,6 +330,13 @@ pub struct CopyObject {
310330 metadata_directive : Option < Directive > ,
311331 #[ builder( default , setter( into) ) ]
312332 tagging_directive : Option < Directive > ,
333+ /// Optional checksum algorithm for data integrity verification during copy.
334+ ///
335+ /// When specified, the server computes a checksum of the destination object using
336+ /// this algorithm during the copy operation. Supported algorithms: CRC32, CRC32C,
337+ /// SHA1, SHA256, CRC64NVME. The checksum value is included in response headers for verification.
338+ #[ builder( default , setter( into) ) ]
339+ checksum_algorithm : Option < crate :: s3:: utils:: ChecksumAlgorithm > ,
313340}
314341
315342/// Builder type for [`CopyObject`] that is returned by [`MinioClient::copy_object`](crate::s3::client::MinioClient::copy_object).
@@ -331,6 +358,7 @@ pub type CopyObjectBldr = CopyObjectBuilder<(
331358 ( ) ,
332359 ( ) ,
333360 ( ) ,
361+ ( ) ,
334362) > ;
335363
336364impl CopyObject {
@@ -434,6 +462,7 @@ impl CopyObject {
434462 . source ( self . source )
435463 . metadata_directive ( self . metadata_directive )
436464 . tagging_directive ( self . tagging_directive )
465+ . checksum_algorithm ( self . checksum_algorithm )
437466 . build ( )
438467 . send ( )
439468 . await ?;
@@ -472,6 +501,8 @@ pub struct ComposeObjectInternal {
472501 legal_hold : bool ,
473502 #[ builder( default ) ]
474503 sources : Vec < ComposeSource > ,
504+ #[ builder( default , setter( into) ) ]
505+ checksum_algorithm : Option < ChecksumAlgorithm > ,
475506}
476507
477508/// Builder type for [`ComposeObjectInternal`] that is returned by `compose_object_internal` method.
@@ -491,6 +522,7 @@ pub type ComposeObjectInternalBldr = ComposeObjectInternalBuilder<(
491522 ( ) ,
492523 ( ) ,
493524 ( ) ,
525+ ( ) ,
494526) > ;
495527
496528impl ComposeObjectInternal {
@@ -554,6 +586,7 @@ impl ComposeObjectInternal {
554586 . extra_query_params ( self . extra_query_params . clone ( ) )
555587 . region ( self . region . clone ( ) )
556588 . extra_headers ( Some ( headers) )
589+ . checksum_algorithm ( self . checksum_algorithm )
557590 . build ( )
558591 . send ( )
559592 . await
@@ -625,11 +658,10 @@ impl ComposeObjectInternal {
625658 Err ( e) => return ( Err ( e. into ( ) ) , upload_id) ,
626659 } ;
627660
628- parts. push ( PartInfo {
629- number : part_number,
630- etag,
631- size,
632- } ) ;
661+ let checksum = self
662+ . checksum_algorithm
663+ . and_then ( |alg| resp. get_checksum ( alg) . map ( |v| ( alg, v) ) ) ;
664+ parts. push ( PartInfo :: new ( part_number, etag, size, checksum) ) ;
633665 } else {
634666 let part_ranges = calculate_part_ranges ( offset, size, MAX_PART_SIZE ) ;
635667 for ( part_offset, length) in part_ranges {
@@ -661,11 +693,10 @@ impl ComposeObjectInternal {
661693 Err ( e) => return ( Err ( e. into ( ) ) , upload_id) ,
662694 } ;
663695
664- parts. push ( PartInfo {
665- number : part_number,
666- etag,
667- size : length,
668- } ) ;
696+ let checksum = self
697+ . checksum_algorithm
698+ . and_then ( |alg| resp. get_checksum ( alg) . map ( |v| ( alg, v) ) ) ;
699+ parts. push ( PartInfo :: new ( part_number, etag, length, checksum) ) ;
669700 }
670701 }
671702 }
@@ -725,6 +756,8 @@ pub struct ComposeObject {
725756 legal_hold : bool ,
726757 #[ builder( default ) ]
727758 sources : Vec < ComposeSource > ,
759+ #[ builder( default , setter( into) ) ]
760+ checksum_algorithm : Option < ChecksumAlgorithm > ,
728761}
729762
730763/// Builder type for [`ComposeObject`] that is returned by [`MinioClient::compose_object`](crate::s3::client::MinioClient::compose_object).
@@ -744,6 +777,7 @@ pub type ComposeObjectBldr = ComposeObjectBuilder<(
744777 ( ) ,
745778 ( ) ,
746779 ( Vec < ComposeSource > , ) ,
780+ ( ) ,
747781) > ;
748782
749783impl ComposeObject {
@@ -766,6 +800,7 @@ impl ComposeObject {
766800 . retention ( self . retention )
767801 . legal_hold ( self . legal_hold )
768802 . sources ( self . sources )
803+ . checksum_algorithm ( self . checksum_algorithm )
769804 . build ( )
770805 . send ( )
771806 . await ;
0 commit comments