diff --git a/Cargo.lock b/Cargo.lock index 53f9acd0a1..9c2aa4c284 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,6 +400,7 @@ dependencies = [ "azure_core_test", "azure_identity", "azure_storage_blob_test", + "futures", "serde", "time", "tokio", diff --git a/eng/emitter-package.json b/eng/emitter-package.json index 817fd5be76..25892cbbe0 100644 --- a/eng/emitter-package.json +++ b/eng/emitter-package.json @@ -1,17 +1,17 @@ { "main": "dist/src/index.js", "dependencies": { - "@azure-tools/typespec-rust": "0.14.0" + "@azure-tools/typespec-rust": "0.14.1" }, "devDependencies": { - "@azure-tools/typespec-azure-core": "0.55.0", - "@azure-tools/typespec-azure-rulesets": "0.55.0", - "@azure-tools/typespec-client-generator-core": "0.55.1", - "@typespec/compiler": "1.0.0-rc.1", - "@typespec/http": "1.0.0-rc.1", - "@typespec/openapi": "1.0.0-rc.1", - "@typespec/rest": "0.69.0", - "@typespec/versioning": "0.69.0", - "@typespec/xml": "0.69.0" + "@azure-tools/typespec-azure-core": "0.56.0", + "@azure-tools/typespec-azure-rulesets": "0.56.0", + "@azure-tools/typespec-client-generator-core": "0.56.1", + "@typespec/compiler": "1.0.0", + "@typespec/http": "1.0.0", + "@typespec/openapi": "1.0.0", + "@typespec/rest": "0.70.0", + "@typespec/versioning": "0.70.0", + "@typespec/xml": "0.70.0" } -} +} \ No newline at end of file diff --git a/sdk/storage/azure_storage_blob/Cargo.toml b/sdk/storage/azure_storage_blob/Cargo.toml index 9cc1244e34..0280f26bc5 100644 --- a/sdk/storage/azure_storage_blob/Cargo.toml +++ b/sdk/storage/azure_storage_blob/Cargo.toml @@ -18,6 +18,7 @@ categories = ["api-bindings"] [dependencies] async-trait.workspace = true azure_core = { workspace = true, features = ["xml"] } +futures.workspace = true serde.workspace = true time.workspace = true typespec_client_core = { workspace = true, features = ["derive"] } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs index bd76a614cc..cf0a42c751 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -8,13 +8,15 @@ use crate::{ BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, }, - models::{AccessTier, BlockList, BlockListType, BlockLookupList}, + models::{ + AccessTier, BlobClientDeleteOptions, BlobClientDownloadOptions, + BlobClientGetPropertiesOptions, BlobClientSetMetadataOptions, + BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlockBlobClientCommitBlockListOptions, BlockBlobClientUploadOptions, BlockList, + BlockListType, BlockLookupList, + }, pipeline::StorageHeadersPolicy, - BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, - BlobClientOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, - BlobClientSetTierOptions, BlockBlobClient, BlockBlobClientCommitBlockListOptions, - BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, - BlockBlobClientUploadOptions, + BlobClientOptions, BlockBlobClient, }; use azure_core::{ credentials::TokenCredential, diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs index f66ff7a67b..48963a72f7 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs @@ -3,16 +3,20 @@ use crate::{ generated::clients::BlobContainerClient as GeneratedBlobContainerClient, - generated::models::BlobContainerClientGetPropertiesResult, pipeline::StorageHeadersPolicy, - BlobClient, BlobClientOptions, BlobContainerClientCreateOptions, - BlobContainerClientDeleteOptions, BlobContainerClientGetPropertiesOptions, - BlobContainerClientOptions, BlobContainerClientSetMetadataOptions, + generated::models::BlobContainerClientGetPropertiesResult, + models::{ + BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, + BlobContainerClientGetPropertiesOptions, BlobContainerClientListBlobFlatSegmentOptions, + BlobContainerClientSetMetadataOptions, ListBlobsFlatSegmentResponse, + }, + pipeline::StorageHeadersPolicy, + BlobClient, BlobContainerClientOptions, }; use azure_core::{ credentials::TokenCredential, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - Response, Url, + Pager, Response, Url, }, Result, }; @@ -141,4 +145,16 @@ impl BlobContainerClient { ) -> Result> { self.client.get_properties(options).await } + + /// Returns a list of the blobs under the specified container. + /// + /// # Arguments + /// + /// * `options` - Optional configuration for the request. + pub async fn list_blobs( + &self, + options: Option>, + ) -> Result> { + self.client.list_blob_flat_segment(options) + } } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs index bfb1d9a345..9f593c9ec7 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs @@ -3,8 +3,9 @@ use crate::{ generated::clients::BlobServiceClient as GeneratedBlobServiceClient, - models::StorageServiceProperties, pipeline::StorageHeadersPolicy, BlobContainerClient, - BlobContainerClientOptions, BlobServiceClientGetPropertiesOptions, BlobServiceClientOptions, + models::{BlobServiceClientGetPropertiesOptions, StorageServiceProperties}, + pipeline::StorageHeadersPolicy, + BlobContainerClient, BlobServiceClientOptions, }; use azure_core::{ credentials::TokenCredential, diff --git a/sdk/storage/azure_storage_blob/src/clients/block_blob_client.rs b/sdk/storage/azure_storage_blob/src/clients/block_blob_client.rs index cd58b28848..a1d88f2694 100644 --- a/sdk/storage/azure_storage_blob/src/clients/block_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/block_blob_client.rs @@ -8,13 +8,15 @@ use crate::{ BlockBlobClientCommitBlockListResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, }, - models::{BlockList, BlockListType, BlockLookupList, StorageServiceProperties}, + models::{ + BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, + BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlockBlobClientCommitBlockListOptions, BlockBlobClientGetBlockListOptions, + BlockBlobClientStageBlockOptions, BlockBlobClientUploadOptions, BlockList, BlockListType, + BlockLookupList, StorageServiceProperties, + }, pipeline::StorageHeadersPolicy, - BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, - BlobClientOptions, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, - BlobClientSetTierOptions, BlockBlobClientCommitBlockListOptions, - BlockBlobClientGetBlockListOptions, BlockBlobClientOptions, BlockBlobClientStageBlockOptions, - BlockBlobClientUploadOptions, + BlobClientOptions, BlockBlobClientOptions, }; use azure_core::{ credentials::TokenCredential, diff --git a/sdk/storage/azure_storage_blob/src/clients/mod.rs b/sdk/storage/azure_storage_blob/src/clients/mod.rs index 6398608579..2b9367ae2e 100644 --- a/sdk/storage/azure_storage_blob/src/clients/mod.rs +++ b/sdk/storage/azure_storage_blob/src/clients/mod.rs @@ -12,3 +12,7 @@ pub use blob_client::BlobClient; pub use blob_container_client::BlobContainerClient; pub use blob_service_client::BlobServiceClient; pub use block_blob_client::BlockBlobClient; + +pub use crate::generated::clients::{ + BlobClientOptions, BlobContainerClientOptions, BlobServiceClientOptions, BlockBlobClientOptions, +}; diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs index 29c089ddfd..b9dc3e7e94 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/append_blob_client.rs @@ -119,7 +119,7 @@ impl AppendBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/octet-stream"); if let Some(if_match) = options.if_match { @@ -147,7 +147,10 @@ impl AppendBlobClient { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( @@ -216,7 +219,7 @@ impl AppendBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { @@ -275,7 +278,10 @@ impl AppendBlobClient { ); } if let Some(source_content_md5) = options.source_content_md5 { - request.insert_header("x-ms-source-content-md5", source_content_md5); + request.insert_header( + "x-ms-source-content-md5", + base64::encode(source_content_md5), + ); } if let Some(source_if_match) = options.source_if_match { request.insert_header("x-ms-source-if-match", source_if_match); diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs index a2790d6fe3..02e3d89730 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_client.rs @@ -265,10 +265,12 @@ impl BlobClient { /// /// * `lease_id` - Required. A lease ID for the source path. If specified, the source path must have an active lease and the /// lease ID must match. + /// * `proposed_lease_id` - Required. The proposed lease ID for the container. /// * `options` - Optional parameters for the request. pub async fn change_lease( &self, lease_id: String, + proposed_lease_id: String, options: Option>, ) -> Result> { let options = options.unwrap_or_default(); @@ -310,9 +312,7 @@ impl BlobClient { request.insert_header("x-ms-if-tags", if_tags); } request.insert_header("x-ms-lease-id", lease_id); - if let Some(proposed_lease_id) = options.proposed_lease_id { - request.insert_header("x-ms-proposed-lease-id", proposed_lease_id); - } + request.insert_header("x-ms-proposed-lease-id", proposed_lease_id); request.insert_header("x-ms-version", &self.version); self.pipeline.send(&ctx, &mut request).await } @@ -374,7 +374,7 @@ impl BlobClient { request.insert_header("x-ms-copy-source-authorization", copy_source_authorization); } if let Some(copy_source_tags) = options.copy_source_tags { - request.insert_header("x-ms-copy-source-tags", copy_source_tags); + request.insert_header("x-ms-copy-source-tag-option", copy_source_tags); } if let Some(encryption_scope) = options.encryption_scope { request.insert_header("x-ms-encryption-scope", encryption_scope); @@ -406,7 +406,10 @@ impl BlobClient { } } if let Some(source_content_md5) = options.source_content_md5 { - request.insert_header("x-ms-source-content-md5", source_content_md5); + request.insert_header( + "x-ms-source-content-md5", + base64::encode(source_content_md5), + ); } if let Some(source_if_match) = options.source_if_match { request.insert_header("x-ms-source-if-match", source_if_match); @@ -695,6 +698,9 @@ impl BlobClient { range_get_content_md5.to_string(), ); } + if let Some(structured_body_type) = options.structured_body_type { + request.insert_header("x-ms-structured-body", structured_body_type); + } request.insert_header("x-ms-version", &self.version); self.pipeline.send(&ctx, &mut request).await } @@ -1296,14 +1302,17 @@ impl BlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/xml"); if let Some(client_request_id) = options.client_request_id { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(if_tags) = options.if_tags { request.insert_header("x-ms-if-tags", if_tags); @@ -1387,7 +1396,6 @@ impl BlobClient { path = path.replace("{blobName}", &self.blob_name); path = path.replace("{containerName}", &self.container_name); url = url.join(&path)?; - url.query_pairs_mut().append_pair("comp", "copy"); if let Some(timeout) = options.timeout { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs index 788cdd7263..efa44f3924 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_container_client.rs @@ -30,9 +30,10 @@ use azure_core::{ fmt::SafeDebug, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - ClientOptions, Context, Method, Pipeline, Request, RequestContent, Response, Url, + ClientOptions, Context, Method, Pager, PagerResult, Pipeline, Request, RequestContent, + Response, Url, }, - Result, + xml, Result, }; use std::sync::Arc; @@ -491,20 +492,21 @@ impl BlobContainerClient { /// # Arguments /// /// * `options` - Optional parameters for the request. - pub async fn list_blob_flat_segment( + pub fn list_blob_flat_segment( &self, options: Option>, - ) -> Result> { - let options = options.unwrap_or_default(); - let ctx = Context::with_context(&options.method_options.context); - let mut url = self.endpoint.clone(); - url = url.join(&self.container_name)?; - url.query_pairs_mut() + ) -> Result> { + let options = options.unwrap_or_default().into_owned(); + let pipeline = self.pipeline.clone(); + let mut first_url = self.endpoint.clone(); + first_url = first_url.join(&self.container_name)?; + first_url + .query_pairs_mut() .append_pair("comp", "list") .append_key_only("flat") .append_pair("restype", "container"); if let Some(include) = options.include { - url.query_pairs_mut().append_pair( + first_url.query_pairs_mut().append_pair( "include", &include .iter() @@ -514,27 +516,60 @@ impl BlobContainerClient { ); } if let Some(marker) = options.marker { - url.query_pairs_mut().append_pair("marker", &marker); + first_url.query_pairs_mut().append_pair("marker", &marker); } if let Some(maxresults) = options.maxresults { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("maxresults", &maxresults.to_string()); } if let Some(prefix) = options.prefix { - url.query_pairs_mut().append_pair("prefix", &prefix); + first_url.query_pairs_mut().append_pair("prefix", &prefix); } if let Some(timeout) = options.timeout { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/xml"); - request.insert_header("content-type", "application/xml"); - if let Some(client_request_id) = options.client_request_id { - request.insert_header("x-ms-client-request-id", client_request_id); - } - request.insert_header("x-ms-version", &self.version); - self.pipeline.send(&ctx, &mut request).await + let version = self.version.clone(); + Ok(Pager::from_callback(move |marker: Option| { + let mut url = first_url.clone(); + if let Some(marker) = marker { + if url.query_pairs().any(|(name, _)| name.eq("marker")) { + let mut new_url = url.clone(); + new_url + .query_pairs_mut() + .clear() + .extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("marker"))); + url = new_url; + } + url.query_pairs_mut().append_pair("marker", &marker); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/xml"); + request.insert_header("content-type", "application/xml"); + if let Some(client_request_id) = &options.client_request_id { + request.insert_header("x-ms-client-request-id", client_request_id); + } + request.insert_header("x-ms-version", &version); + let ctx = options.method_options.context.clone(); + let pipeline = pipeline.clone(); + async move { + let rsp: Response = + pipeline.send(&ctx, &mut request).await?; + let (status, headers, body) = rsp.deconstruct(); + let bytes = body.collect().await?; + let res: ListBlobsFlatSegmentResponse = xml::read_xml(&bytes)?; + let rsp = Response::from_bytes(status, headers, bytes); + Ok(match res.next_marker { + Some(next_marker) => PagerResult::Continue { + response: rsp, + continuation: next_marker, + }, + None => PagerResult::Complete { response: rsp }, + }) + } + })) } /// The List Blobs operation returns a list of the blobs under the specified container. A delimiter can be used to traverse @@ -546,22 +581,25 @@ impl BlobContainerClient { /// that acts as a placeholder for all blobs whose names begin with the same substring up to the appearance of the delimiter /// character. The delimiter may be a single character or a string. /// * `options` - Optional parameters for the request. - pub async fn list_blob_hierarchy_segment( + pub fn list_blob_hierarchy_segment( &self, delimiter: &str, options: Option>, - ) -> Result> { - let options = options.unwrap_or_default(); - let ctx = Context::with_context(&options.method_options.context); - let mut url = self.endpoint.clone(); - url = url.join(&self.container_name)?; - url.query_pairs_mut() + ) -> Result> { + let options = options.unwrap_or_default().into_owned(); + let pipeline = self.pipeline.clone(); + let mut first_url = self.endpoint.clone(); + first_url = first_url.join(&self.container_name)?; + first_url + .query_pairs_mut() .append_pair("comp", "list") .append_key_only("hierarchy") .append_pair("restype", "container"); - url.query_pairs_mut().append_pair("delimiter", delimiter); + first_url + .query_pairs_mut() + .append_pair("delimiter", delimiter); if let Some(include) = options.include { - url.query_pairs_mut().append_pair( + first_url.query_pairs_mut().append_pair( "include", &include .iter() @@ -571,27 +609,60 @@ impl BlobContainerClient { ); } if let Some(marker) = options.marker { - url.query_pairs_mut().append_pair("marker", &marker); + first_url.query_pairs_mut().append_pair("marker", &marker); } if let Some(maxresults) = options.maxresults { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("maxresults", &maxresults.to_string()); } if let Some(prefix) = options.prefix { - url.query_pairs_mut().append_pair("prefix", &prefix); + first_url.query_pairs_mut().append_pair("prefix", &prefix); } if let Some(timeout) = options.timeout { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/xml"); - request.insert_header("content-type", "application/xml"); - if let Some(client_request_id) = options.client_request_id { - request.insert_header("x-ms-client-request-id", client_request_id); - } - request.insert_header("x-ms-version", &self.version); - self.pipeline.send(&ctx, &mut request).await + let version = self.version.clone(); + Ok(Pager::from_callback(move |marker: Option| { + let mut url = first_url.clone(); + if let Some(marker) = marker { + if url.query_pairs().any(|(name, _)| name.eq("marker")) { + let mut new_url = url.clone(); + new_url + .query_pairs_mut() + .clear() + .extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("marker"))); + url = new_url; + } + url.query_pairs_mut().append_pair("marker", &marker); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/xml"); + request.insert_header("content-type", "application/xml"); + if let Some(client_request_id) = &options.client_request_id { + request.insert_header("x-ms-client-request-id", client_request_id); + } + request.insert_header("x-ms-version", &version); + let ctx = options.method_options.context.clone(); + let pipeline = pipeline.clone(); + async move { + let rsp: Response = + pipeline.send(&ctx, &mut request).await?; + let (status, headers, body) = rsp.deconstruct(); + let bytes = body.collect().await?; + let res: ListBlobsHierarchySegmentResponse = xml::read_xml(&bytes)?; + let rsp = Response::from_bytes(status, headers, bytes); + Ok(match res.next_marker { + Some(next_marker) => PagerResult::Continue { + response: rsp, + continuation: next_marker, + }, + None => PagerResult::Complete { response: rsp }, + }) + } + })) } /// The Release Lease operation frees the lease if it's no longer needed, so that another client can immediately acquire a diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs index f96f1fdc61..82ea7905fe 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/blob_service_client.rs @@ -6,12 +6,11 @@ use crate::generated::{ clients::BlobContainerClient, models::{ - crate_models::{GetUserDelegationKeyRequest, SetPropertiesRequest}, BlobServiceClientFilterBlobsOptions, BlobServiceClientGetAccountInfoOptions, BlobServiceClientGetAccountInfoResult, BlobServiceClientGetPropertiesOptions, BlobServiceClientGetStatisticsOptions, BlobServiceClientGetUserDelegationKeyOptions, BlobServiceClientListContainersSegmentOptions, BlobServiceClientSetPropertiesOptions, - FilterBlobSegment, ListContainersSegmentResponse, StorageServiceProperties, + FilterBlobSegment, KeyInfo, ListContainersSegmentResponse, StorageServiceProperties, StorageServiceStats, UserDelegationKey, }, }; @@ -20,9 +19,10 @@ use azure_core::{ fmt::SafeDebug, http::{ policies::{BearerTokenCredentialPolicy, Policy}, - ClientOptions, Context, Method, Pipeline, Request, RequestContent, Response, Url, + ClientOptions, Context, Method, Pager, PagerResult, Pipeline, Request, RequestContent, + Response, Url, }, - Result, + xml, Result, }; use std::sync::Arc; @@ -240,13 +240,11 @@ impl BlobServiceClient { /// /// # Arguments /// - /// * `start` - The date-time the key is active. - /// * `expiry` - The date-time the key expires. + /// * `key_info` - Key information provided in the request /// * `options` - Optional parameters for the request. pub async fn get_user_delegation_key( &self, - start: String, - expiry: String, + key_info: RequestContent, options: Option>, ) -> Result> { let options = options.unwrap_or_default(); @@ -266,9 +264,7 @@ impl BlobServiceClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &self.version); - let body: RequestContent = - GetUserDelegationKeyRequest { start, expiry }.try_into()?; - request.set_body(body); + request.set_body(key_info); self.pipeline.send(&ctx, &mut request).await } @@ -277,16 +273,16 @@ impl BlobServiceClient { /// # Arguments /// /// * `options` - Optional parameters for the request. - pub async fn list_containers_segment( + pub fn list_containers_segment( &self, options: Option>, - ) -> Result> { - let options = options.unwrap_or_default(); - let ctx = Context::with_context(&options.method_options.context); - let mut url = self.endpoint.clone(); - url.query_pairs_mut().append_pair("comp", "list"); + ) -> Result> { + let options = options.unwrap_or_default().into_owned(); + let pipeline = self.pipeline.clone(); + let mut first_url = self.endpoint.clone(); + first_url.query_pairs_mut().append_pair("comp", "list"); if let Some(include) = options.include { - url.query_pairs_mut().append_pair( + first_url.query_pairs_mut().append_pair( "include", &include .iter() @@ -296,27 +292,60 @@ impl BlobServiceClient { ); } if let Some(marker) = options.marker { - url.query_pairs_mut().append_pair("marker", &marker); + first_url.query_pairs_mut().append_pair("marker", &marker); } if let Some(maxresults) = options.maxresults { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("maxresults", &maxresults.to_string()); } if let Some(prefix) = options.prefix { - url.query_pairs_mut().append_pair("prefix", &prefix); + first_url.query_pairs_mut().append_pair("prefix", &prefix); } if let Some(timeout) = options.timeout { - url.query_pairs_mut() + first_url + .query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } - let mut request = Request::new(url, Method::Get); - request.insert_header("accept", "application/xml"); - request.insert_header("content-type", "application/xml"); - if let Some(client_request_id) = options.client_request_id { - request.insert_header("x-ms-client-request-id", client_request_id); - } - request.insert_header("x-ms-version", &self.version); - self.pipeline.send(&ctx, &mut request).await + let version = self.version.clone(); + Ok(Pager::from_callback(move |marker: Option| { + let mut url = first_url.clone(); + if let Some(marker) = marker { + if url.query_pairs().any(|(name, _)| name.eq("marker")) { + let mut new_url = url.clone(); + new_url + .query_pairs_mut() + .clear() + .extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("marker"))); + url = new_url; + } + url.query_pairs_mut().append_pair("marker", &marker); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/xml"); + request.insert_header("content-type", "application/xml"); + if let Some(client_request_id) = &options.client_request_id { + request.insert_header("x-ms-client-request-id", client_request_id); + } + request.insert_header("x-ms-version", &version); + let ctx = options.method_options.context.clone(); + let pipeline = pipeline.clone(); + async move { + let rsp: Response = + pipeline.send(&ctx, &mut request).await?; + let (status, headers, body) = rsp.deconstruct(); + let bytes = body.collect().await?; + let res: ListContainersSegmentResponse = xml::read_xml(&bytes)?; + let rsp = Response::from_bytes(status, headers, bytes); + Ok(match res.next_marker { + Some(next_marker) => PagerResult::Continue { + response: rsp, + continuation: next_marker, + }, + None => PagerResult::Complete { response: rsp }, + }) + } + })) } /// Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics and CORS (Cross-Origin @@ -324,9 +353,11 @@ impl BlobServiceClient { /// /// # Arguments /// + /// * `storage_service_properties` - The storage service properties to set. /// * `options` - Optional parameters for the request. pub async fn set_properties( &self, + storage_service_properties: RequestContent, options: Option>, ) -> Result> { let options = options.unwrap_or_default(); @@ -346,17 +377,7 @@ impl BlobServiceClient { request.insert_header("x-ms-client-request-id", client_request_id); } request.insert_header("x-ms-version", &self.version); - let body: RequestContent = SetPropertiesRequest { - logging: options.logging, - hour_metrics: options.hour_metrics, - minute_metrics: options.minute_metrics, - cors: options.cors, - default_service_version: options.default_service_version, - delete_retention_policy: options.delete_retention_policy, - static_website: options.static_website, - } - .try_into()?; - request.set_body(body); + request.set_body(storage_service_properties); self.pipeline.send(&ctx, &mut request).await } } diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs index 1099b1e3c7..939ea27285 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/block_blob_client.rs @@ -124,7 +124,7 @@ impl BlockBlobClient { let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/xml"); if let Some(if_match) = options.if_match { @@ -167,7 +167,10 @@ impl BlockBlobClient { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( @@ -299,7 +302,7 @@ impl BlockBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/octet-stream"); if let Some(if_match) = options.if_match { @@ -353,7 +356,7 @@ impl BlockBlobClient { ); } if let Some(copy_source_tags) = options.copy_source_tags { - request.insert_header("x-ms-copy-source-tags", copy_source_tags); + request.insert_header("x-ms-copy-source-tag-option", copy_source_tags); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( @@ -382,7 +385,10 @@ impl BlockBlobClient { } } if let Some(source_content_md5) = options.source_content_md5 { - request.insert_header("x-ms-source-content-md5", source_content_md5); + request.insert_header( + "x-ms-source-content-md5", + base64::encode(source_content_md5), + ); } if let Some(source_if_match) = options.source_if_match { request.insert_header("x-ms-source-if-match", source_if_match); @@ -517,14 +523,17 @@ impl BlockBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/octet-stream"); if let Some(client_request_id) = options.client_request_id { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( @@ -619,7 +628,10 @@ impl BlockBlobClient { ); } if let Some(source_content_md5) = options.source_content_md5 { - request.insert_header("x-ms-source-content-md5", source_content_md5); + request.insert_header( + "x-ms-source-content-md5", + base64::encode(source_content_md5), + ); } if let Some(source_if_match) = options.source_if_match { request.insert_header("x-ms-source-if-match", source_if_match); @@ -678,7 +690,7 @@ impl BlockBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/octet-stream"); if let Some(if_match) = options.if_match { @@ -722,7 +734,10 @@ impl BlockBlobClient { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( diff --git a/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs b/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs index 02c8bb9a83..d748bba9d0 100644 --- a/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/generated/clients/page_blob_client.rs @@ -683,7 +683,7 @@ impl PageBlobClient { request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); if let Some(transactional_content_md5) = options.transactional_content_md5 { - request.insert_header("content-md5", transactional_content_md5); + request.insert_header("content-md5", base64::encode(transactional_content_md5)); } request.insert_header("content-type", "application/octet-stream"); if let Some(if_match) = options.if_match { @@ -705,7 +705,10 @@ impl PageBlobClient { request.insert_header("x-ms-client-request-id", client_request_id); } if let Some(transactional_content_crc64) = options.transactional_content_crc64 { - request.insert_header("x-ms-content-crc64", transactional_content_crc64); + request.insert_header( + "x-ms-content-crc64", + base64::encode(transactional_content_crc64), + ); } if let Some(encryption_algorithm) = options.encryption_algorithm { request.insert_header( @@ -874,7 +877,10 @@ impl PageBlobClient { ); } if let Some(source_content_md5) = options.source_content_md5 { - request.insert_header("x-ms-source-content-md5", source_content_md5); + request.insert_header( + "x-ms-source-content-md5", + base64::encode(source_content_md5), + ); } if let Some(source_if_match) = options.source_if_match { request.insert_header("x-ms-source-if-match", source_if_match); diff --git a/sdk/storage/azure_storage_blob/src/generated/models/crate_models.rs b/sdk/storage/azure_storage_blob/src/generated/models/crate_models.rs deleted file mode 100644 index f2638eeada..0000000000 --- a/sdk/storage/azure_storage_blob/src/generated/models/crate_models.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Licensed under the MIT License. See License.txt in the project root for license information. -// Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. - -use super::{ - xml_helpers::CorsCorsRule, CorsRule, Logging, Metrics, RetentionPolicy, StaticWebsite, -}; -use azure_core::{fmt::SafeDebug, http::RequestContent, xml::to_xml, Result}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Default, Deserialize, SafeDebug, Serialize, azure_core::http::Model)] -#[typespec(format = "xml")] -pub(crate) struct GetUserDelegationKeyRequest { - /// The date-time the key expires. - #[serde(rename = "Expiry")] - pub(crate) expiry: String, - - /// The date-time the key is active. - #[serde(rename = "Start")] - pub(crate) start: String, -} - -#[derive(Clone, Default, Deserialize, SafeDebug, Serialize, azure_core::http::Model)] -#[typespec(format = "xml")] -pub(crate) struct SetPropertiesRequest { - /// The CORS properties. - #[serde( - default, - deserialize_with = "CorsCorsRule::unwrap", - rename = "Cors", - serialize_with = "CorsCorsRule::wrap", - skip_serializing_if = "Option::is_none" - )] - pub(crate) cors: Option>, - - /// The default service version. - #[serde( - rename = "DefaultServiceVersion", - skip_serializing_if = "Option::is_none" - )] - pub(crate) default_service_version: Option, - - /// The delete retention policy. - #[serde( - rename = "DeleteRetentionPolicy", - skip_serializing_if = "Option::is_none" - )] - pub(crate) delete_retention_policy: Option, - - /// The hour metrics properties. - #[serde(rename = "HourMetrics", skip_serializing_if = "Option::is_none")] - pub(crate) hour_metrics: Option, - - /// The logging properties. - #[serde(rename = "Logging", skip_serializing_if = "Option::is_none")] - pub(crate) logging: Option, - - /// The minute metrics properties. - #[serde(rename = "MinuteMetrics", skip_serializing_if = "Option::is_none")] - pub(crate) minute_metrics: Option, - - /// The static website properties. - #[serde(rename = "StaticWebsite", skip_serializing_if = "Option::is_none")] - pub(crate) static_website: Option, -} - -impl TryFrom for RequestContent { - type Error = azure_core::Error; - fn try_from(value: GetUserDelegationKeyRequest) -> Result { - RequestContent::try_from(to_xml(&value)?) - } -} - -impl TryFrom for RequestContent { - type Error = azure_core::Error; - fn try_from(value: SetPropertiesRequest) -> Result { - RequestContent::try_from(to_xml(&value)?) - } -} diff --git a/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs b/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs index ac44727c08..cb132ce3a1 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/header_traits.rs @@ -22,7 +22,7 @@ use super::{ BlockBlobClientCommitBlockListResult, BlockBlobClientPutBlobFromUrlResult, BlockBlobClientQueryResult, BlockBlobClientStageBlockFromUrlResult, BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, BlockList, CopyStatus, - FilterBlobSegment, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, + FilterBlobSegment, LeaseDuration, LeaseState, LeaseStatus, ListBlobsFlatSegmentResponse, ListBlobsHierarchySegmentResponse, PageBlobClientClearPagesResult, PageBlobClientCopyIncrementalResult, PageBlobClientCreateResult, PageBlobClientResizeResult, PageBlobClientUpdateSequenceNumberResult, PageBlobClientUploadPagesFromUrlResult, @@ -114,13 +114,13 @@ const VERSION_ID: HeaderName = HeaderName::from_static("x-ms-version-id"); /// Provides access to typed response headers for `AppendBlobClient::append_block_from_url()` pub trait AppendBlobClientAppendBlockFromUrlResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn blob_append_offset(&self) -> Result>; fn blob_committed_block_count(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -131,8 +131,8 @@ impl AppendBlobClientAppendBlockFromUrlResultHeaders { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -164,8 +164,10 @@ impl AppendBlobClientAppendBlockFromUrlResultHeaders } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -190,13 +192,13 @@ impl AppendBlobClientAppendBlockFromUrlResultHeaders /// Provides access to typed response headers for `AppendBlobClient::append_block()` pub trait AppendBlobClientAppendBlockResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn blob_append_offset(&self) -> Result>; fn blob_committed_block_count(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -206,8 +208,8 @@ pub trait AppendBlobClientAppendBlockResultHeaders: private::Sealed { impl AppendBlobClientAppendBlockResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -239,8 +241,10 @@ impl AppendBlobClientAppendBlockResultHeaders for Response Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -270,7 +274,7 @@ impl AppendBlobClientAppendBlockResultHeaders for Response Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; @@ -283,8 +287,8 @@ pub trait AppendBlobClientCreateResultHeaders: private::Sealed { impl AppendBlobClientCreateResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -472,11 +476,11 @@ impl BlobClientChangeLeaseResultHeaders for Response Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn copy_id(&self) -> Result>; fn copy_status(&self) -> Result>; fn encryption_scope(&self) -> Result>; @@ -486,8 +490,8 @@ pub trait BlobClientCopyFromUrlResultHeaders: private::Sealed { impl BlobClientCopyFromUrlResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -508,8 +512,10 @@ impl BlobClientCopyFromUrlResultHeaders for Response Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// String identifier for this copy operation. Use with Get Blob Properties to check the status of this copy operation, or @@ -606,7 +612,7 @@ pub trait BlobClientDownloadResultHeaders: private::Sealed { fn content_encoding(&self) -> Result>; fn content_language(&self) -> Result>; fn content_length(&self) -> Result>; - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn content_range(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; @@ -615,7 +621,7 @@ pub trait BlobClientDownloadResultHeaders: private::Sealed { fn is_sealed(&self) -> Result>; fn blob_sequence_number(&self) -> Result>; fn blob_type(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn copy_completion_time(&self) -> Result>; fn copy_id(&self) -> Result>; fn copy_progress(&self) -> Result>; @@ -629,7 +635,7 @@ pub trait BlobClientDownloadResultHeaders: private::Sealed { fn immutability_policy_expires_on(&self) -> Result>; fn is_current_version(&self) -> Result>; fn last_accessed(&self) -> Result>; - fn duration(&self) -> Result>; + fn duration(&self) -> Result>; fn lease_state(&self) -> Result>; fn lease_status(&self) -> Result>; fn legal_hold(&self) -> Result>; @@ -677,8 +683,8 @@ impl BlobClientDownloadResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// Indicates the range of bytes returned in the event that the client requested a subset of the blob by setting the 'Range' @@ -729,8 +735,10 @@ impl BlobClientDownloadResultHeaders for Response { } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob. This value can specify @@ -823,7 +831,7 @@ impl BlobClientDownloadResultHeaders for Response { /// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease /// can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change. - fn duration(&self) -> Result> { + fn duration(&self) -> Result> { Headers::get_optional_as(self.headers(), &LEASE_DURATION) } @@ -928,7 +936,7 @@ pub trait BlobClientGetPropertiesResultHeaders: private::Sealed { fn content_encoding(&self) -> Result>; fn content_language(&self) -> Result>; fn content_length(&self) -> Result>; - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn tier(&self) -> Result>; @@ -955,7 +963,7 @@ pub trait BlobClientGetPropertiesResultHeaders: private::Sealed { fn is_incremental_copy(&self) -> Result>; fn is_current_version(&self) -> Result>; fn last_accessed(&self) -> Result>; - fn duration(&self) -> Result>; + fn duration(&self) -> Result>; fn lease_state(&self) -> Result>; fn lease_status(&self) -> Result>; fn legal_hold(&self) -> Result>; @@ -999,8 +1007,8 @@ impl BlobClientGetPropertiesResultHeaders for Response Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// The date/time that the container was last modified. @@ -1168,7 +1176,7 @@ impl BlobClientGetPropertiesResultHeaders for Response Result> { + fn duration(&self) -> Result> { Headers::get_optional_as(self.headers(), &LEASE_DURATION) } @@ -1590,7 +1598,7 @@ pub trait BlobContainerClientGetPropertiesResultHeaders: private::Sealed { fn has_immutability_policy(&self) -> Result>; fn has_legal_hold(&self) -> Result>; fn is_immutable_storage_with_versioning_enabled(&self) -> Result>; - fn duration(&self) -> Result>; + fn duration(&self) -> Result>; fn lease_state(&self) -> Result>; fn lease_status(&self) -> Result>; fn metadata(&self) -> Result>; @@ -1644,7 +1652,7 @@ impl BlobContainerClientGetPropertiesResultHeaders /// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease /// can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change. - fn duration(&self) -> Result> { + fn duration(&self) -> Result> { Headers::get_optional_as(self.headers(), &LEASE_DURATION) } @@ -1829,10 +1837,10 @@ impl BlobTagsHeaders for Response { /// Provides access to typed response headers for `BlockBlobClient::commit_block_list()` pub trait BlockBlobClientCommitBlockListResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -1844,8 +1852,8 @@ impl BlockBlobClientCommitBlockListResultHeaders { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// The date/time that the container was last modified. @@ -1861,8 +1869,10 @@ impl BlockBlobClientCommitBlockListResultHeaders } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -1893,7 +1903,7 @@ impl BlockBlobClientCommitBlockListResultHeaders /// Provides access to typed response headers for `BlockBlobClient::put_blob_from_url()` pub trait BlockBlobClientPutBlobFromUrlResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; @@ -1906,8 +1916,8 @@ pub trait BlockBlobClientPutBlobFromUrlResultHeaders: private::Sealed { impl BlockBlobClientPutBlobFromUrlResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -1961,7 +1971,7 @@ pub trait BlockBlobClientQueryResultHeaders: private::Sealed { fn content_encoding(&self) -> Result>; fn content_language(&self) -> Result>; fn content_length(&self) -> Result>; - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn content_range(&self) -> Result>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; @@ -1970,7 +1980,7 @@ pub trait BlockBlobClientQueryResultHeaders: private::Sealed { fn blob_content_md5(&self) -> Result>>; fn blob_sequence_number(&self) -> Result>; fn blob_type(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn copy_completion_time(&self) -> Result>; fn copy_id(&self) -> Result>; fn copy_progress(&self) -> Result>; @@ -1979,7 +1989,7 @@ pub trait BlockBlobClientQueryResultHeaders: private::Sealed { fn copy_status_description(&self) -> Result>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; - fn duration(&self) -> Result>; + fn duration(&self) -> Result>; fn lease_state(&self) -> Result>; fn lease_status(&self) -> Result>; fn metadata(&self) -> Result>; @@ -2022,8 +2032,8 @@ impl BlockBlobClientQueryResultHeaders for Response /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// Indicates the range of bytes returned in the event that the client requested a subset of the blob by setting the 'Range' @@ -2074,8 +2084,10 @@ impl BlockBlobClientQueryResultHeaders for Response } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// Conclusion time of the last attempted Copy Blob operation where this blob was the destination blob. This value can specify @@ -2137,7 +2149,7 @@ impl BlockBlobClientQueryResultHeaders for Response /// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease /// can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change. - fn duration(&self) -> Result> { + fn duration(&self) -> Result> { Headers::get_optional_as(self.headers(), &LEASE_DURATION) } @@ -2172,9 +2184,9 @@ impl BlockBlobClientQueryResultHeaders for Response /// Provides access to typed response headers for `BlockBlobClient::stage_block_from_url()` pub trait BlockBlobClientStageBlockFromUrlResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -2185,8 +2197,8 @@ impl BlockBlobClientStageBlockFromUrlResultHeaders { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -2195,8 +2207,10 @@ impl BlockBlobClientStageBlockFromUrlResultHeaders } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -2221,8 +2235,8 @@ impl BlockBlobClientStageBlockFromUrlResultHeaders /// Provides access to typed response headers for `BlockBlobClient::stage_block()` pub trait BlockBlobClientStageBlockResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_md5(&self) -> Result>>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -2231,13 +2245,15 @@ pub trait BlockBlobClientStageBlockResultHeaders: private::Sealed { impl BlockBlobClientStageBlockResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -2262,7 +2278,7 @@ impl BlockBlobClientStageBlockResultHeaders for Response Result>; + fn content_md5(&self) -> Result>>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn encryption_key_sha256(&self) -> Result>; @@ -2274,8 +2290,8 @@ pub trait BlockBlobClientUploadResultHeaders: private::Sealed { impl BlockBlobClientUploadResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// The date/time that the container was last modified. @@ -2383,19 +2399,19 @@ impl ListBlobsHierarchySegmentResponseHeaders for Response Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn blob_sequence_number(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; } impl PageBlobClientClearPagesResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -2421,8 +2437,10 @@ impl PageBlobClientClearPagesResultHeaders for Response Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } } @@ -2467,7 +2485,7 @@ impl PageBlobClientCopyIncrementalResultHeaders for Response Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; @@ -2480,8 +2498,8 @@ pub trait PageBlobClientCreateResultHeaders: private::Sealed { impl PageBlobClientCreateResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -2595,12 +2613,12 @@ impl PageBlobClientUpdateSequenceNumberResultHeaders /// Provides access to typed response headers for `PageBlobClient::upload_pages_from_url()` pub trait PageBlobClientUploadPagesFromUrlResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn blob_sequence_number(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -2611,8 +2629,8 @@ impl PageBlobClientUploadPagesFromUrlResultHeaders { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -2638,8 +2656,10 @@ impl PageBlobClientUploadPagesFromUrlResultHeaders } /// This response header is returned so that the client can check for the integrity of the copied content. - fn content_crc64(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted @@ -2664,12 +2684,12 @@ impl PageBlobClientUploadPagesFromUrlResultHeaders /// Provides access to typed response headers for `PageBlobClient::upload_pages()` pub trait PageBlobClientUploadPagesResultHeaders: private::Sealed { - fn content_md5(&self) -> Result>; + fn content_md5(&self) -> Result>>; fn date(&self) -> Result>; fn last_modified(&self) -> Result>; fn etag(&self) -> Result>; fn blob_sequence_number(&self) -> Result>; - fn content_crc64(&self) -> Result>; + fn content_crc64(&self) -> Result>>; fn encryption_key_sha256(&self) -> Result>; fn encryption_scope(&self) -> Result>; fn is_server_encrypted(&self) -> Result>; @@ -2679,8 +2699,8 @@ pub trait PageBlobClientUploadPagesResultHeaders: private::Sealed { impl PageBlobClientUploadPagesResultHeaders for Response { /// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the /// client can check for message content integrity. - fn content_md5(&self) -> Result> { - Headers::get_optional_as(self.headers(), &CONTENT_MD5) + fn content_md5(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_MD5, |h| base64::decode(h.as_str())) } /// UTC date/time value generated by the service that indicates the time at which the response was initiated @@ -2706,8 +2726,10 @@ impl PageBlobClientUploadPagesResultHeaders for Response Result> { - Headers::get_optional_as(self.headers(), &CONTENT_CRC64) + fn content_crc64(&self) -> Result>> { + Headers::get_optional_with(self.headers(), &CONTENT_CRC64, |h| { + base64::decode(h.as_str()) + }) } /// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted diff --git a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs index 8ae7e61e18..2a52a8bd63 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/method_options.rs @@ -4,10 +4,9 @@ // Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. use super::{ - AccessTier, BlobDeleteType, BlobImmutabilityPolicyMode, CorsRule, DeleteSnapshotsOptionType, - EncryptionAlgorithmType, FilterBlobsIncludeItem, ListBlobsIncludeItem, - ListContainersIncludeType, Logging, Metrics, PremiumPageBlobAccessTier, PublicAccessType, - RehydratePriority, RetentionPolicy, StaticWebsite, + AccessTier, BlobDeleteType, BlobImmutabilityPolicyMode, DeleteSnapshotsOptionType, + EncryptionAlgorithmType, FilterBlobsIncludeItem, LeaseDuration, ListBlobsIncludeItem, + ListContainersIncludeType, PremiumPageBlobAccessTier, PublicAccessType, RehydratePriority, }; use azure_core::{fmt::SafeDebug, http::ClientMethodOptions}; use std::collections::HashMap; @@ -78,11 +77,11 @@ pub struct AppendBlobClientAppendBlockOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `AppendBlobClient::append_block_from_url()` @@ -146,7 +145,7 @@ pub struct AppendBlobClientAppendBlockFromUrlOptions<'a> { pub source_content_crc64: Option>, /// Specify the md5 calculated for the range of bytes that must be read from the copy source. - pub source_content_md5: Option, + pub source_content_md5: Option>, /// Specify an ETag value to operate only on blobs with a matching value. pub source_if_match: Option, @@ -168,7 +167,7 @@ pub struct AppendBlobClientAppendBlockFromUrlOptions<'a> { /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `AppendBlobClient::create()` @@ -314,7 +313,7 @@ pub struct BlobClientAcquireLeaseOptions<'a> { /// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease /// can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change. - pub duration: Option, + pub duration: Option, /// The request should only proceed if an entity matches this string. pub if_match: Option, @@ -400,9 +399,6 @@ pub struct BlobClientChangeLeaseOptions<'a> { /// Allows customization of the method call. pub method_options: ClientMethodOptions<'a>, - /// Optional. The proposed lease ID for the container. - pub proposed_lease_id: Option, - /// The timeout parameter is expressed in seconds. For more information, see [Setting Timeouts for Blob Service Operations.](https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations) pub timeout: Option, } @@ -460,7 +456,7 @@ pub struct BlobClientCopyFromUrlOptions<'a> { pub method_options: ClientMethodOptions<'a>, /// Specify the md5 calculated for the range of bytes that must be read from the copy source. - pub source_content_md5: Option, + pub source_content_md5: Option>, /// Specify an ETag value to operate only on blobs with a matching value. pub source_if_match: Option, @@ -654,6 +650,9 @@ pub struct BlobClientDownloadOptions<'a> { /// information on working with blob snapshots, see [Creating a Snapshot of a Blob.](https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob) pub snapshot: Option, + /// Required if the request body is a structured message. Specifies the message schema version and properties. + pub structured_body_type: Option, + /// The timeout parameter is expressed in seconds. For more information, see [Setting Timeouts for Blob Service Operations.](https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations) pub timeout: Option, @@ -1001,11 +1000,11 @@ pub struct BlobClientSetTagsOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, /// The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate /// on. It's for service version 2019-10-10 and newer. @@ -1135,7 +1134,7 @@ pub struct BlobContainerClientAcquireLeaseOptions<'a> { /// Specifies the duration of the lease, in seconds, or negative one (-1) for a lease that never expires. A non-infinite lease /// can be between 15 and 60 seconds. A lease duration cannot be changed using renew or change. - pub duration: Option, + pub duration: Option, /// A date-time value. A request is made under the condition that the resource has been modified since the specified date-time. pub if_modified_since: Option, @@ -1350,6 +1349,22 @@ pub struct BlobContainerClientListBlobFlatSegmentOptions<'a> { pub timeout: Option, } +impl BlobContainerClientListBlobFlatSegmentOptions<'_> { + pub fn into_owned(self) -> BlobContainerClientListBlobFlatSegmentOptions<'static> { + BlobContainerClientListBlobFlatSegmentOptions { + client_request_id: self.client_request_id, + include: self.include, + marker: self.marker, + maxresults: self.maxresults, + method_options: ClientMethodOptions { + context: self.method_options.context.into_owned(), + }, + prefix: self.prefix, + timeout: self.timeout, + } + } +} + /// Options to be passed to `BlobContainerClient::list_blob_hierarchy_segment()` #[derive(Clone, Default, SafeDebug)] pub struct BlobContainerClientListBlobHierarchySegmentOptions<'a> { @@ -1379,6 +1394,22 @@ pub struct BlobContainerClientListBlobHierarchySegmentOptions<'a> { pub timeout: Option, } +impl BlobContainerClientListBlobHierarchySegmentOptions<'_> { + pub fn into_owned(self) -> BlobContainerClientListBlobHierarchySegmentOptions<'static> { + BlobContainerClientListBlobHierarchySegmentOptions { + client_request_id: self.client_request_id, + include: self.include, + marker: self.marker, + maxresults: self.maxresults, + method_options: ClientMethodOptions { + context: self.method_options.context.into_owned(), + }, + prefix: self.prefix, + timeout: self.timeout, + } + } +} + /// Options to be passed to `BlobContainerClient::release_lease()` #[derive(Clone, Default, SafeDebug)] pub struct BlobContainerClientReleaseLeaseOptions<'a> { @@ -1609,36 +1640,31 @@ pub struct BlobServiceClientListContainersSegmentOptions<'a> { pub timeout: Option, } +impl BlobServiceClientListContainersSegmentOptions<'_> { + pub fn into_owned(self) -> BlobServiceClientListContainersSegmentOptions<'static> { + BlobServiceClientListContainersSegmentOptions { + client_request_id: self.client_request_id, + include: self.include, + marker: self.marker, + maxresults: self.maxresults, + method_options: ClientMethodOptions { + context: self.method_options.context.into_owned(), + }, + prefix: self.prefix, + timeout: self.timeout, + } + } +} + /// Options to be passed to `BlobServiceClient::set_properties()` #[derive(Clone, Default, SafeDebug)] pub struct BlobServiceClientSetPropertiesOptions<'a> { /// An opaque, globally-unique, client-generated string identifier for the request. pub client_request_id: Option, - /// The CORS properties. - pub cors: Option>, - - /// The default service version. - pub default_service_version: Option, - - /// The delete retention policy. - pub delete_retention_policy: Option, - - /// The hour metrics properties. - pub hour_metrics: Option, - - /// The logging properties. - pub logging: Option, - /// Allows customization of the method call. pub method_options: ClientMethodOptions<'a>, - /// The minute metrics properties. - pub minute_metrics: Option, - - /// The static website properties. - pub static_website: Option, - /// The timeout parameter is expressed in seconds. For more information, see [Setting Timeouts for Blob Service Operations.](https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations) pub timeout: Option, } @@ -1732,11 +1758,11 @@ pub struct BlockBlobClientCommitBlockListOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `BlockBlobClient::get_block_list()` @@ -1845,7 +1871,7 @@ pub struct BlockBlobClientPutBlobFromUrlOptions<'a> { pub method_options: ClientMethodOptions<'a>, /// Specify the md5 calculated for the range of bytes that must be read from the copy source. - pub source_content_md5: Option, + pub source_content_md5: Option>, /// Specify an ETag value to operate only on blobs with a matching value. pub source_if_match: Option, @@ -1870,7 +1896,7 @@ pub struct BlockBlobClientPutBlobFromUrlOptions<'a> { /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `BlockBlobClient::query()` @@ -1954,11 +1980,11 @@ pub struct BlockBlobClientStageBlockOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `BlockBlobClient::stage_block_from_url()` @@ -1997,7 +2023,7 @@ pub struct BlockBlobClientStageBlockFromUrlOptions<'a> { pub source_content_crc64: Option>, /// Specify the md5 calculated for the range of bytes that must be read from the copy source. - pub source_content_md5: Option, + pub source_content_md5: Option>, /// Specify an ETag value to operate only on blobs with a matching value. pub source_if_match: Option, @@ -2107,11 +2133,11 @@ pub struct BlockBlobClientUploadOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `PageBlobClient::clear_pages()` @@ -2228,8 +2254,8 @@ pub struct PageBlobClientCreateOptions<'a> { /// Optional. Sets the blob's content type. If specified, this property is stored with the blob and returned with a read request. pub blob_content_type: Option, - /// Optional. The sequence number is a user-controlled property that you can use to track requests. The value of the sequence - /// number must be between 0 and 2^63 - 1. The default value is 0. + /// Set for page blobs only. The sequence number is a user-controlled value that you can use to track requests. The value + /// of the sequence number must be between 0 and 2^63 - 1. pub blob_sequence_number: Option, /// Optional. Used to set blob tags in various blob operations. @@ -2551,11 +2577,11 @@ pub struct PageBlobClientUploadPagesOptions<'a> { pub timeout: Option, /// Specify the transactional crc64 for the body, to be validated by the service. - pub transactional_content_crc64: Option, + pub transactional_content_crc64: Option>, /// Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks /// were validated when each was uploaded. - pub transactional_content_md5: Option, + pub transactional_content_md5: Option>, } /// Options to be passed to `PageBlobClient::upload_pages_from_url()` @@ -2618,7 +2644,7 @@ pub struct PageBlobClientUploadPagesFromUrlOptions<'a> { pub source_content_crc64: Option>, /// Specify the md5 calculated for the range of bytes that must be read from the copy source. - pub source_content_md5: Option, + pub source_content_md5: Option>, /// Specify an ETag value to operate only on blobs with a matching value. pub source_if_match: Option, diff --git a/sdk/storage/azure_storage_blob/src/generated/models/mod.rs b/sdk/storage/azure_storage_blob/src/generated/models/mod.rs index 46fdc8994b..097f968604 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/mod.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/mod.rs @@ -11,6 +11,5 @@ pub use enums::*; pub use header_traits::*; pub use method_options::*; pub use pub_models::*; -pub(crate) mod crate_models; pub(crate) mod models_serde; pub(crate) mod xml_helpers; diff --git a/sdk/storage/azure_storage_blob/src/generated/models/models_serde.rs b/sdk/storage/azure_storage_blob/src/generated/models/models_serde.rs index 1a67b79a64..ceb5acde6f 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/models_serde.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/models_serde.rs @@ -3,7 +3,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. // Code generated by Microsoft (R) Rust Code Generator. DO NOT EDIT. -use super::{BlobTags, BlockLookupList, QueryRequest}; +use super::{BlobTags, BlockLookupList, KeyInfo, QueryRequest, StorageServiceProperties}; use azure_core::{http::RequestContent, xml::to_xml, Result}; impl TryFrom for RequestContent { @@ -20,6 +20,13 @@ impl TryFrom for RequestContent { } } +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: KeyInfo) -> Result { + RequestContent::try_from(to_xml(&value)?) + } +} + impl TryFrom for RequestContent { type Error = azure_core::Error; fn try_from(value: QueryRequest) -> Result { @@ -27,6 +34,13 @@ impl TryFrom for RequestContent { } } +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: StorageServiceProperties) -> Result { + RequestContent::try_from(to_xml(&value)?) + } +} + pub mod option_vec_encoded_bytes_std { #![allow(clippy::type_complexity)] use azure_core::base64; diff --git a/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs b/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs index 4a4403d42d..67199a0d6a 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/pub_models.rs @@ -222,10 +222,9 @@ pub struct BlobFlatListSegment { default, deserialize_with = "Blob_itemsBlob::unwrap", rename = "BlobItems", - serialize_with = "Blob_itemsBlob::wrap", - skip_serializing_if = "Option::is_none" + serialize_with = "Blob_itemsBlob::wrap" )] - pub blob_items: Option>, + pub blob_items: Vec, } /// Represents an array of blobs. @@ -239,10 +238,9 @@ pub struct BlobHierarchyListSegment { default, deserialize_with = "Blob_itemsBlob::unwrap", rename = "BlobItems", - serialize_with = "Blob_itemsBlob::wrap", - skip_serializing_if = "Option::is_none" + serialize_with = "Blob_itemsBlob::wrap" )] - pub blob_items: Option>, + pub blob_items: Vec, /// The blob prefixes. #[serde( @@ -971,6 +969,19 @@ pub struct JsonTextConfiguration { pub record_separator: Option, } +/// Key information +#[derive(Clone, Default, Deserialize, SafeDebug, Serialize, azure_core::http::Model)] +#[typespec(format = "xml")] +pub struct KeyInfo { + /// The date-time the key expires. + #[serde(rename = "Expiry", skip_serializing_if = "Option::is_none")] + pub expiry: Option, + + /// The date-time the key is active. + #[serde(rename = "Start", skip_serializing_if = "Option::is_none")] + pub start: Option, +} + /// An enumeration of blobs. #[derive(Clone, Default, Deserialize, SafeDebug, Serialize, azure_core::http::Model)] #[non_exhaustive] @@ -998,8 +1009,8 @@ pub struct ListBlobsFlatSegmentResponse { pub prefix: Option, /// The blob segment. - #[serde(skip_serializing_if = "Option::is_none")] - pub segment: Option, + #[serde(default)] + pub segment: BlobFlatListSegment, /// The service endpoint. #[serde(rename = "@ServiceEndpoint", skip_serializing_if = "Option::is_none")] @@ -1037,8 +1048,8 @@ pub struct ListBlobsHierarchySegmentResponse { pub prefix: Option, /// The blob segment. - #[serde(skip_serializing_if = "Option::is_none")] - pub segment: Option, + #[serde(default)] + pub segment: BlobHierarchyListSegment, /// The service endpoint. #[serde(rename = "@ServiceEndpoint", skip_serializing_if = "Option::is_none")] @@ -1056,10 +1067,9 @@ pub struct ListContainersSegmentResponse { default, deserialize_with = "Container_itemsContainer::unwrap", rename = "Containers", - serialize_with = "Container_itemsContainer::wrap", - skip_serializing_if = "Option::is_none" + serialize_with = "Container_itemsContainer::wrap" )] - pub container_items: Option>, + pub container_items: Vec, /// The marker of the containers. #[serde(rename = "Marker", skip_serializing_if = "Option::is_none")] @@ -1342,7 +1352,6 @@ pub struct StaticWebsite { /// The service properties. #[derive(Clone, Default, Deserialize, SafeDebug, Serialize, azure_core::http::Model)] -#[non_exhaustive] #[typespec(format = "xml")] pub struct StorageServiceProperties { /// The CORS properties. diff --git a/sdk/storage/azure_storage_blob/src/generated/models/xml_helpers.rs b/sdk/storage/azure_storage_blob/src/generated/models/xml_helpers.rs index af85d4a115..f20d4a15ef 100644 --- a/sdk/storage/azure_storage_blob/src/generated/models/xml_helpers.rs +++ b/sdk/storage/azure_storage_blob/src/generated/models/xml_helpers.rs @@ -16,21 +16,18 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[serde(rename = "BlobItems")] pub(crate) struct Blob_itemsBlob { #[serde(default)] - Blob: Option>, + Blob: Vec, } impl Blob_itemsBlob { - pub fn unwrap<'de, D>(deserializer: D) -> Result>, D::Error> + pub fn unwrap<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { Ok(Blob_itemsBlob::deserialize(deserializer)?.Blob) } - pub fn wrap( - to_serialize: &Option>, - serializer: S, - ) -> Result + pub fn wrap(to_serialize: &Vec, serializer: S) -> Result where S: Serializer, { @@ -178,21 +175,18 @@ impl Committed_blocksBlock { #[serde(rename = "Containers")] pub(crate) struct Container_itemsContainer { #[serde(default)] - Container: Option>, + Container: Vec, } impl Container_itemsContainer { - pub fn unwrap<'de, D>(deserializer: D) -> Result>, D::Error> + pub fn unwrap<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { Ok(Container_itemsContainer::deserialize(deserializer)?.Container) } - pub fn wrap( - to_serialize: &Option>, - serializer: S, - ) -> Result + pub fn wrap(to_serialize: &Vec, serializer: S) -> Result where S: Serializer, { diff --git a/sdk/storage/azure_storage_blob/src/lib.rs b/sdk/storage/azure_storage_blob/src/lib.rs index ec64004b2d..0e8fa822ae 100644 --- a/sdk/storage/azure_storage_blob/src/lib.rs +++ b/sdk/storage/azure_storage_blob/src/lib.rs @@ -11,28 +11,24 @@ pub mod clients; mod generated; mod pipeline; -pub use crate::clients::{BlobClient, BlobContainerClient, BlobServiceClient, BlockBlobClient}; -pub use crate::generated::clients::{ - BlobClientOptions, BlobContainerClientOptions, BlobServiceClientOptions, BlockBlobClientOptions, -}; -pub use crate::generated::models::{ - BlobClientDeleteOptions, BlobClientDownloadOptions, BlobClientGetPropertiesOptions, - BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, - BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, - BlobContainerClientGetPropertiesOptions, BlobContainerClientSetMetadataOptions, - BlobServiceClientGetPropertiesOptions, BlockBlobClientCommitBlockListOptions, - BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, - BlockBlobClientUploadOptions, -}; +pub use clients::*; pub mod models { pub use crate::generated::models::{ - AccessTier, ArchiveStatus, BlobClientDownloadResult, BlobClientDownloadResultHeaders, + AccessTier, ArchiveStatus, BlobClientDeleteOptions, BlobClientDownloadOptions, + BlobClientDownloadResult, BlobClientDownloadResultHeaders, BlobClientGetPropertiesOptions, BlobClientGetPropertiesResult, BlobClientGetPropertiesResultHeaders, - BlobContainerClientGetPropertiesResult, BlobContainerClientGetPropertiesResultHeaders, - BlobImmutabilityPolicyMode, BlobType, BlockBlobClientCommitBlockListResult, - BlockBlobClientStageBlockResult, BlockBlobClientUploadResult, BlockList, BlockListType, - BlockLookupList, CopyStatus, LeaseState, LeaseStatus, PublicAccessType, RehydratePriority, + BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlobClientSetTierOptions, + BlobContainerClientCreateOptions, BlobContainerClientDeleteOptions, + BlobContainerClientGetPropertiesOptions, BlobContainerClientGetPropertiesResult, + BlobContainerClientGetPropertiesResultHeaders, + BlobContainerClientListBlobFlatSegmentOptions, BlobContainerClientSetMetadataOptions, + BlobImmutabilityPolicyMode, BlobServiceClientGetPropertiesOptions, BlobType, + BlockBlobClientCommitBlockListOptions, BlockBlobClientCommitBlockListResult, + BlockBlobClientGetBlockListOptions, BlockBlobClientStageBlockOptions, + BlockBlobClientStageBlockResult, BlockBlobClientUploadOptions, BlockBlobClientUploadResult, + BlockList, BlockListType, BlockLookupList, CopyStatus, LeaseState, LeaseStatus, + ListBlobsFlatSegmentResponse, PublicAccessType, RehydratePriority, StorageServiceProperties, }; } diff --git a/sdk/storage/azure_storage_blob/tests/blob_client.rs b/sdk/storage/azure_storage_blob/tests/blob_client.rs index af31c4a6d0..16a9d3a2de 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_client.rs @@ -6,12 +6,10 @@ use azure_core::{ Bytes, }; use azure_core_test::{recorded, TestContext}; -use azure_storage_blob::{ - models::{ - AccessTier, BlobClientDownloadResultHeaders, BlobClientGetPropertiesResultHeaders, - LeaseState, - }, +use azure_storage_blob::models::{ + AccessTier, BlobClientDownloadResultHeaders, BlobClientGetPropertiesResultHeaders, BlobClientSetMetadataOptions, BlobClientSetPropertiesOptions, BlockBlobClientUploadOptions, + LeaseState, }; use azure_storage_blob_test::{create_test_blob, get_blob_name, get_container_client}; use std::{collections::HashMap, error::Error}; diff --git a/sdk/storage/azure_storage_blob/tests/blob_container_client.rs b/sdk/storage/azure_storage_blob/tests/blob_container_client.rs index 81c9e1ebe4..3057d1c6c7 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_container_client.rs @@ -1,13 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -use azure_core::http::StatusCode; +use azure_core::http::{Pager, PagerResult, RequestContent, StatusCode}; use azure_core_test::{recorded, TestContext}; -use azure_storage_blob::{ - models::{BlobContainerClientGetPropertiesResultHeaders, LeaseState}, - BlobContainerClientSetMetadataOptions, +use azure_storage_blob::models::{ + BlobContainerClientGetPropertiesResultHeaders, BlobContainerClientSetMetadataOptions, + LeaseState, ListBlobsFlatSegmentResponse, }; use azure_storage_blob_test::get_container_client; +use futures::TryStreamExt; use std::{collections::HashMap, error::Error}; #[recorded::test] @@ -82,3 +83,95 @@ async fn test_set_container_metadata(ctx: TestContext) -> Result<(), Box Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let container_client = get_container_client(recording, false).await?; + let blob_client_1 = container_client.blob_client("testblob1".to_string()); + let blob_client_2 = container_client.blob_client("testblob2".to_string()); + + container_client.create_container(None).await?; + let data = b"hello rusty world"; + blob_client_1 + .upload( + RequestContent::from(data.to_vec()), + false, + u64::try_from(data.len())?, + None, + ) + .await?; + blob_client_2 + .upload( + RequestContent::from(data.to_vec()), + false, + u64::try_from(data.len())?, + None, + ) + .await?; + + let mut list_blobs_response = container_client.list_blobs(None).await?; + + while let Some(page) = list_blobs_response.try_next().await? { + let list_blob_segment_response = page.into_body().await?; + let blob_list = list_blob_segment_response.segment.blob_items; + for blob in blob_list { + println!("{}", blob.name.unwrap().content.unwrap()) + } + } + + container_client.delete_container(None).await?; + Ok(()) +} + +#[recorded::test] +async fn test_list_blobs_2(ctx: TestContext) -> Result<(), Box> { + // Recording Setup + let recording = ctx.recording(); + let container_client = get_container_client(recording, false).await?; + let blob_client_1 = container_client.blob_client("testblob1".to_string()); + let blob_client_2 = container_client.blob_client("testblob2".to_string()); + + container_client.create_container(None).await?; + let data = b"hello rusty world"; + blob_client_1 + .upload( + RequestContent::from(data.to_vec()), + false, + u64::try_from(data.len())?, + None, + ) + .await?; + blob_client_2 + .upload( + RequestContent::from(data.to_vec()), + false, + u64::try_from(data.len())?, + None, + ) + .await?; + + let mut list_blobs_response = container_client.list_blobs(None).await?; + let mut count = 0; + + while let Some(page) = list_blobs_response.try_next().await? { + println!("while: {}", count); + count += 1; + let list_blob_segment_response = page.into_body().await?; + let blob_list = list_blob_segment_response.segment.blob_items; + + // for blob in blob_list { + // println!("inside of inner for-loop"); + // println!("{}", blob.name.unwrap().content.unwrap()) + // } + + let first_slice = blob_list.first(); + println!("Is this some? {}", first_slice.is_some()); + + println!("bottom of outer while-loop reached") + } + + container_client.delete_container(None).await?; + Ok(()) +} diff --git a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs index 957adfb2b4..0077ef903b 100644 --- a/sdk/storage/azure_storage_blob/tests/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/tests/blob_service_client.rs @@ -2,7 +2,7 @@ // Licensed under the MIT License. use azure_core_test::{recorded, TestContext}; -use azure_storage_blob::BlobServiceClientGetPropertiesOptions; +use azure_storage_blob::models::BlobServiceClientGetPropertiesOptions; use azure_storage_blob_test::get_blob_service_client; use std::error::Error; diff --git a/sdk/storage/azure_storage_blob/tsp-location.yaml b/sdk/storage/azure_storage_blob/tsp-location.yaml index ce396e3016..2317872844 100644 --- a/sdk/storage/azure_storage_blob/tsp-location.yaml +++ b/sdk/storage/azure_storage_blob/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/storage/Microsoft.BlobStorage -commit: a7ede2356175c7825fdb245ec17e5b6df71e1ae3 +commit: 566f9855e2272ffe7d575e560d95f4755b5b0fb5 repo: Azure/azure-rest-api-specs additionalDirectories: diff --git a/sdk/storage/azure_storage_blob_test/src/lib.rs b/sdk/storage/azure_storage_blob_test/src/lib.rs index 7338c7c57b..d8fe702769 100644 --- a/sdk/storage/azure_storage_blob_test/src/lib.rs +++ b/sdk/storage/azure_storage_blob_test/src/lib.rs @@ -27,12 +27,22 @@ fn recorded_test_setup(recording: &Recording) -> (ClientOptions, String) { (client_options, endpoint) } +/// Takes in a Recording instance and returns a randomized blob name with prefix "blob" of length 16. +/// +/// # Arguments +/// +/// * `recording` - A reference to a Recording instance. pub fn get_blob_name(recording: &Recording) -> String { recording .random_string::<12>(Some("blob")) .to_ascii_lowercase() } +/// Takes in a Recording instance and returns a randomized container name with prefix "container" of length 16. +/// +/// # Arguments +/// +/// * `recording` - A reference to a Recording instance. pub fn get_container_name(recording: &Recording) -> String { recording .random_string::<17>(Some("container"))