From bd65517b3090f198e17469db7c619e477afce853 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Tue, 29 Oct 2024 19:45:54 -0700 Subject: [PATCH 01/19] Initial wrapping work, BlobClient with working e2e download, no auth --- Cargo.toml | 1 + sdk/storage/azure_storage_blob/Cargo.toml | 12 + .../src/clients/blob_client.rs | 132 + sdk/storage/blob_storage/Cargo.toml | 20 + .../src/generated/clients/blob_append_blob.rs | 823 +++++ .../src/generated/clients/blob_blob.rs | 3264 +++++++++++++++++ .../src/generated/clients/blob_block_blob.rs | 1402 +++++++ .../src/generated/clients/blob_client.rs | 159 + .../src/generated/clients/blob_container.rs | 1737 +++++++++ .../src/generated/clients/blob_page_blob.rs | 1791 +++++++++ .../src/generated/clients/blob_service.rs | 652 ++++ .../blob_storage/src/generated/clients/mod.rs | 12 + .../blob_storage/src/generated/enums.rs | 165 + sdk/storage/blob_storage/src/generated/mod.rs | 8 + .../blob_storage/src/generated/models.rs | 1256 +++++++ sdk/storage/blob_storage/src/lib.rs | 15 + 16 files changed, 11449 insertions(+) create mode 100644 sdk/storage/blob_storage/Cargo.toml create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_blob.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_client.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_container.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/blob_service.rs create mode 100644 sdk/storage/blob_storage/src/generated/clients/mod.rs create mode 100644 sdk/storage/blob_storage/src/generated/enums.rs create mode 100644 sdk/storage/blob_storage/src/generated/mod.rs create mode 100644 sdk/storage/blob_storage/src/generated/models.rs create mode 100644 sdk/storage/blob_storage/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 694c89ae73..4ccbcdbedf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "eng/test/mock_transport", "sdk/storage", "sdk/storage/azure_storage_blob", + "sdk/storage/blob_storage", ] [workspace.package] diff --git a/sdk/storage/azure_storage_blob/Cargo.toml b/sdk/storage/azure_storage_blob/Cargo.toml index ecbcea4d73..bbef0b9057 100644 --- a/sdk/storage/azure_storage_blob/Cargo.toml +++ b/sdk/storage/azure_storage_blob/Cargo.toml @@ -11,6 +11,18 @@ rust-version.workspace = true [dependencies] azure_storage_common.workspace = true +async-std = { workspace = true } +azure_core = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +time = { workspace = true } +typespec_client_core = { workspace = true, features = ["reqwest"] } +typespec_derive = { workspace = true } +blob_storage = { path = "../blob_storage" } +uuid = { workspace = true } + +[dev-dependencies] +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } [lints] workspace = true 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 d194bed477..ba874a467f 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -1,2 +1,134 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +use azure_core::{Context, Method, Request, Response, Result, Url}; +use blob_storage::blob_blob::BlobBlobDownloadOptions; +use blob_storage::blob_client::BlobClientOptions; +use blob_storage::BlobClient as GeneratedBlobClient; +use std::sync::Arc; +use uuid::Uuid; + +// Later this will be auto-populated with current version, otherwise could take user input as well +// const CURRENT_SVC_VERSION: String = String::from("2024-08-04"); + +pub struct BlobClient { + account_name: String, + container_name: String, + blob_name: String, + client: GeneratedBlobClient, +} + +impl BlobClient { + pub fn new( + account_name: String, + container_name: String, + blob_name: String, + options: Option, + ) -> Result { + // Build Blob URL from input + let endpoint = "https://".to_owned() + &account_name + ".blob.core.windows.net/"; + let options = options.unwrap_or_default(); + let client = GeneratedBlobClient::with_no_credential(endpoint, Some(options))?; + + Ok(Self { + account_name: account_name.clone(), + container_name: container_name.clone(), + blob_name: blob_name.clone(), + client: client, + }) + } + + // fn build_url(account_name: &str) -> String { + // "https://".to_owned() + account_name + ".blob.core.windows.net/" + // } + + pub async fn download_blob( + &self, + options: Option>, // Curious if this is the right move, or if we can do a simple wrapper with an easy Into convert to the generated version + ) -> Result>> { + //TODO: Inject version through a pipeline policy + let version = Uuid::new_v4().to_string(); + self.client + .get_blob_blob_client() + .download( + self.container_name.clone(), + self.blob_name.clone(), + version, + String::from("2024-08-04"), + Some(BlobBlobDownloadOptions::default()), + ) + .await + } + + // pub async fn get_blob_properties(&self) -> Result { + // // Build the get properties request itself + // let mut request = Request::new(self.url.to_owned(), Method::Head); // This is technically cloning + // BlobClient::finalize_request(&mut request); + + // // Send the request + // let response = self.pipeline.send(&(Context::new()), &mut request).await?; + // println!("Response headers: {:?}", response); + + // // Return the entire response for now + // Ok(response) + // } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_download_blob() { + let blob_client = BlobClient::new( + String::from("vincenttranpublicac"), + String::from("public"), + String::from("hello.txt"), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = blob_client + .download_blob(Some(BlobBlobDownloadOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } +} + +// #[tokio::test] +// async fn test_get_blob_properties() { +// let credential = DefaultAzureCredentialBuilder::default() +// .build() +// .map(|cred| Arc::new(cred) as Arc) +// .expect("Failed to build credential"); + +// // Create a Blob Client +// let my_blob_client = BlobClient::new( +// String::from("vincenttranstock"), +// String::from("acontainer108f32e8"), +// String::from("hello.txt"), +// credential, +// None, +// ); + +// // Get response +// let ret = my_blob_client +// .get_blob_properties() +// .await +// .expect("Request failed!"); +// let (status_code, headers, _response_body) = ret.deconstruct(); + +// // Assert equality +// assert_eq!(status_code, azure_core::StatusCode::Ok); +// assert_eq!( +// headers +// .get_str(&HeaderName::from_static("content-length")) +// .expect("Failed getting content-length header"), +// "10" +// ) +// } +// } diff --git a/sdk/storage/blob_storage/Cargo.toml b/sdk/storage/blob_storage/Cargo.toml new file mode 100644 index 0000000000..0bfe0b7f94 --- /dev/null +++ b/sdk/storage/blob_storage/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "blob_storage" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true + +[dependencies] +async-std = { workspace = true } +azure_core = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +time = { workspace = true } +typespec_client_core = { workspace = true, features = ["reqwest"] } +typespec_derive = { workspace = true } + +[dev-dependencies] +tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs b/sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs new file mode 100644 index 0000000000..c9e5b372d7 --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs @@ -0,0 +1,823 @@ +// 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 crate::models::BlobImmutabilityPolicyMode; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; +use time::OffsetDateTime; + +pub struct BlobAppendBlob { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobAppendBlob { + /// The Append Block operation commits a new block of data to the end of an append blob. + pub async fn append_block( + &self, + body: RequestContent>, + container_name: impl Into, + blob: impl Into, + content_length: i64, + max_size: i64, + append_position: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from( + "/{containerName}/{blob}?AppendBlob/{containerName}/{blob}?comp=appendblock", + ); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + 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-type", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("x-ms-blob-condition-appendpos", append_position.to_string()); + request.insert_header("x-ms-blob-condition-maxsize", max_size.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Append Block From URL operation creates a new block to be committed as part of an append blob where the contents are + /// read from a URL. + pub async fn append_block_from_url( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + source_url: impl Into, + source_range: impl Into, + max_size: i64, + append_position: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from( + "/{containerName}/{blob}?AppendBlob/{containerName}/{blob}?comp=appendblock&fromUrl", + ); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("x-ms-blob-condition-appendpos", append_position.to_string()); + request.insert_header("x-ms-blob-condition-maxsize", max_size.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(copy_source_authorization) = options.copy_source_authorization { + request.insert_header("x-ms-copy-source-authorization", copy_source_authorization); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(source_content_crc64) = options.source_content_crc64 { + request.insert_header("x-ms-source-content-crc64", source_content_crc64); + } + 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-range", source_range.into()); + request.insert_header("x-ms-source-url", source_url.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Create operation creates a new append blob. + pub async fn create( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?AppendBlob"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Seal operation seals the Append Blob to make it read-only. Seal is supported only on version 2019-12-12 version or + /// later. + pub async fn seal( + &self, + container_name: impl Into, + blob: impl Into, + append_position: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = + String::from("/{containerName}/{blob}?AppendBlob/{containerName}/{blob}?comp=seal"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("x-ms-blob-condition-appendpos", append_position.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobAppendBlobAppendBlockOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobAppendBlobAppendBlockOptions<'a> { + pub fn builder() -> builders::BlobAppendBlobAppendBlockOptionsBuilder<'a> { + builders::BlobAppendBlobAppendBlockOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobAppendBlobAppendBlockFromUrlOptions<'a> { + copy_source_authorization: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_content_crc64: Option, + source_content_md5: Option, + timeout: Option, +} + +impl<'a> BlobAppendBlobAppendBlockFromUrlOptions<'a> { + pub fn builder() -> builders::BlobAppendBlobAppendBlockFromUrlOptionsBuilder<'a> { + builders::BlobAppendBlobAppendBlockFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobAppendBlobCreateOptions<'a> { + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + blob_tags_string: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + lease_id: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobAppendBlobCreateOptions<'a> { + pub fn builder() -> builders::BlobAppendBlobCreateOptionsBuilder<'a> { + builders::BlobAppendBlobCreateOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobAppendBlobSealOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobAppendBlobSealOptions<'a> { + pub fn builder() -> builders::BlobAppendBlobSealOptionsBuilder<'a> { + builders::BlobAppendBlobSealOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobAppendBlobAppendBlockOptionsBuilder<'a> { + options: BlobAppendBlobAppendBlockOptions<'a>, + } + + impl BlobAppendBlobAppendBlockOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobAppendBlobAppendBlockOptions::default(), + } + } + + pub fn build(&self) -> BlobAppendBlobAppendBlockOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobAppendBlobAppendBlockOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobAppendBlobAppendBlockFromUrlOptionsBuilder<'a> { + options: BlobAppendBlobAppendBlockFromUrlOptions<'a>, + } + + impl BlobAppendBlobAppendBlockFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobAppendBlobAppendBlockFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobAppendBlobAppendBlockFromUrlOptions { + self.options.clone() + } + + pub fn with_copy_source_authorization(mut self, copy_source_authorization: String) -> Self { + self.options.copy_source_authorization = Some(copy_source_authorization); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_content_crc64(mut self, source_content_crc64: String) -> Self { + self.options.source_content_crc64 = Some(source_content_crc64); + self + } + + pub fn with_source_content_md5(mut self, source_content_md5: String) -> Self { + self.options.source_content_md5 = Some(source_content_md5); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobAppendBlobAppendBlockFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobAppendBlobCreateOptionsBuilder<'a> { + options: BlobAppendBlobCreateOptions<'a>, + } + + impl BlobAppendBlobCreateOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobAppendBlobCreateOptions::default(), + } + } + + pub fn build(&self) -> BlobAppendBlobCreateOptions { + self.options.clone() + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobAppendBlobCreateOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobAppendBlobSealOptionsBuilder<'a> { + options: BlobAppendBlobSealOptions<'a>, + } + + impl BlobAppendBlobSealOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobAppendBlobSealOptions::default(), + } + } + + pub fn build(&self) -> BlobAppendBlobSealOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobAppendBlobSealOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_blob.rs b/sdk/storage/blob_storage/src/generated/clients/blob_blob.rs new file mode 100644 index 0000000000..cfa5b45fad --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_blob.rs @@ -0,0 +1,3264 @@ +// 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 crate::models::{ + AccessTier, BlobExpiryOptions, BlobImmutabilityPolicyMode, BlobTags, DeleteSnapshotsOptionType, + QueryRequest, RehydratePriority, +}; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; +use time::OffsetDateTime; + +pub struct BlobBlob { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobBlob { + /// The Abort Copy From URL operation aborts a pending Copy From URL operation, and leaves a destination blob with zero length + /// and full metadata. + pub async fn abort_copy_from_url( + &self, + container_name: impl Into, + blob: impl Into, + copy_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=copy©id"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-copy-id", copy_id.into()); + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations. + pub async fn acquire_lease( + &self, + container_name: impl Into, + blob: impl Into, + duration: i32, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=lease&acquire"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + request.insert_header("x-ms-lease-duration", duration.to_string()); + 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-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations. + pub async fn break_lease( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=lease&break"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(break_period) = options.break_period { + request.insert_header("x-ms-lease-break-period", break_period.to_string()); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations. + pub async fn change_lease( + &self, + container_name: impl Into, + blob: impl Into, + lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=lease&change"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + 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-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Copy From URL operation copies a blob or an internet resource to a new blob. It will not return a response until the + /// copy is complete. + pub async fn copy_from_url( + &self, + container_name: impl Into, + blob: impl Into, + copy_source: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=copy&sync"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(tier) = options.tier { + request.insert_header("x-ms-access-tier", tier.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-copy-source", copy_source.into()); + if let Some(copy_source_authorization) = options.copy_source_authorization { + 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); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(source_content_md5) = options.source_content_md5 { + request.insert_header("x-ms-source-content-md5", source_content_md5); + } + if let Some(source_if_match) = options.source_if_match { + request.insert_header("x-ms-source-if-match", source_if_match); + } + if let Some(source_if_modified_since) = options.source_if_modified_since { + request.insert_header( + "x-ms-source-if-modified-since", + source_if_modified_since.to_string(), + ); + } + if let Some(source_if_none_match) = options.source_if_none_match { + request.insert_header("x-ms-source-if-none-match", source_if_none_match); + } + if let Some(source_if_unmodified_since) = options.source_if_unmodified_since { + request.insert_header( + "x-ms-source-if-unmodified-since", + source_if_unmodified_since.to_string(), + ); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Create Snapshot operation creates a read-only snapshot of a blob + pub async fn create_snapshot( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=snapshot"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed from + /// the storage account. If the storage account's soft delete feature is enabled, then, when a blob is deleted, it is marked + /// for deletion and becomes inaccessible immediately. However, the blob service retains the blob or snapshot for the number + /// of days specified by the DeleteRetentionPolicy section of [Storage service properties] (Set-Blob-Service-Properties.md). + /// After the specified number of days has passed, the blob's data is permanently removed from the storage account. Note that + /// you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use the List Blobs API + /// and specify the \"include=deleted\" query parameter to discover which blobs and snapshots have been soft deleted. You + /// can then use the Undelete Blob API to restore a soft-deleted blob. All other operations on a soft-deleted blob or snapshot + /// causes the service to return an HTTP status code of 404 (ResourceNotFound). + pub async fn delete( + &self, + container_name: impl Into, + blob: impl Into, + version_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(blob_delete_type) = options.blob_delete_type { + url.query_pairs_mut() + .append_pair("deletetype", &blob_delete_type.to_string()); + } + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Delete); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("versionid", version_id.into()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(delete_snapshots) = options.delete_snapshots { + request.insert_header("x-ms-delete-snapshots", delete_snapshots.to_string()); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Delete Immutability Policy operation deletes the immutability policy on the blob. + pub async fn delete_immutability_policy( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=immutabilityPolicies"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Delete); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Download operation reads or downloads a blob from the system, including its metadata and properties. You can also + /// call Download to read a snapshot. + pub async fn download( + &self, + container_name: impl Into, + blob: impl Into, + version_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result>> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("versionid", version_id.into()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(range) = options.range { + request.insert_header("x-ms-range", range); + } + if let Some(range_content_crc64) = options.range_content_crc64 { + request.insert_header( + "x-ms-range-get-content-crc64", + range_content_crc64.to_string(), + ); + } + if let Some(range_content_md5) = options.range_content_md5 { + request.insert_header("x-ms-range-get-content-md5", range_content_md5.to_string()); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Returns the sku name and account kind + pub async fn get_account_info( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?restype=account&comp=properties"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get Properties operation returns all user-defined metadata, standard HTTP properties, and system properties for the + /// blob. It does not return the content of the blob. + pub async fn get_properties( + &self, + container_name: impl Into, + blob: impl Into, + version_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + let mut request = Request::new(url, Method::Head); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("versionid", version_id.into()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get Blob Tags operation enables users to get tags on a blob. + pub async fn get_tags( + &self, + container_name: impl Into, + blob: impl Into, + version_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/{containerName}/{blob}?comp=tags"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + request.insert_header("versionid", version_id.into()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Query operation enables users to select/project on blob data by providing simple query expressions. + pub async fn query( + &self, + query_request: RequestContent, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result>> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/{containerName}/{blob}?comp=query"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(query_request); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations. + pub async fn release_lease( + &self, + container_name: impl Into, + blob: impl Into, + lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=lease&release"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations. + pub async fn renew_lease( + &self, + container_name: impl Into, + blob: impl Into, + lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=lease&renew"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// "Set the expiration time of a blob" + pub async fn set_expiry( + &self, + container_name: impl Into, + blob: impl Into, + expiry_options: BlobExpiryOptions, + expires_on: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=expiry"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-expiry-option", expiry_options.to_string()); + request.insert_header("x-ms-expiry-time", expires_on.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Set HTTP Headers operation sets system properties on the blob. + pub async fn set_http_headers( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=properties&SetHTTPHeaders"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// "Set the immutability policy of a blob" + pub async fn set_immutability_policy( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=immutabilityPolicies"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Set Legal Hold operation sets a legal hold on the blob. + pub async fn set_legal_hold( + &self, + container_name: impl Into, + blob: impl Into, + legal_hold: bool, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=legalhold"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Set Metadata operation sets user-defined metadata for the specified blob as one or more name-value pairs. + pub async fn set_metadata( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=metadata"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Set Tags operation enables users to set tags on a blob. + pub async fn set_tags( + &self, + container_name: impl Into, + blob: impl Into, + version_id: impl Into, + tags: RequestContent, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/{containerName}/{blob}?comp=tags"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + 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-type", "application/json"); + request.insert_header("versionid", version_id.into()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(tags); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Set Tier operation sets the tier on a block blob. The operation is allowed on a page blob or block blob, but not on + /// an append blob. A block blob's tier determines Hot/Cool/Archive storage type. This operation does not update the blob's + /// ETag. + pub async fn set_tier( + &self, + container_name: impl Into, + blob: impl Into, + access_tier: AccessTier, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=tier"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("x-ms-access-tier", access_tier.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(rehydrate_priority) = options.rehydrate_priority { + request.insert_header("x-ms-rehydrate-priority", rehydrate_priority.to_string()); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Start Copy From URL operation copies a blob or an internet resource to a new blob. + pub async fn start_copy_from_url( + &self, + container_name: impl Into, + blob: impl Into, + copy_source: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=copy"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(tier) = options.tier { + request.insert_header("x-ms-access-tier", tier.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-copy-source", copy_source.into()); + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(rehydrate_priority) = options.rehydrate_priority { + request.insert_header("x-ms-rehydrate-priority", rehydrate_priority.to_string()); + } + if let Some(seal_blob) = options.seal_blob { + request.insert_header("x-ms-seal-blob", seal_blob.to_string()); + } + if let Some(source_if_match) = options.source_if_match { + request.insert_header("x-ms-source-if-match", source_if_match); + } + if let Some(source_if_modified_since) = options.source_if_modified_since { + request.insert_header( + "x-ms-source-if-modified-since", + source_if_modified_since.to_string(), + ); + } + if let Some(source_if_none_match) = options.source_if_none_match { + request.insert_header("x-ms-source-if-none-match", source_if_none_match); + } + if let Some(source_if_tags) = options.source_if_tags { + request.insert_header("x-ms-source-if-tags", source_if_tags); + } + if let Some(source_if_unmodified_since) = options.source_if_unmodified_since { + request.insert_header( + "x-ms-source-if-unmodified-since", + source_if_unmodified_since.to_string(), + ); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// "Undelete a blob that was previously soft deleted" + pub async fn undelete( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}/?comp=undelete"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobAbortCopyFromUrlOptions<'a> { + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobAbortCopyFromUrlOptions<'a> { + pub fn builder() -> builders::BlobBlobAbortCopyFromUrlOptionsBuilder<'a> { + builders::BlobBlobAbortCopyFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobAcquireLeaseOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + proposed_lease_id: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobAcquireLeaseOptions<'a> { + pub fn builder() -> builders::BlobBlobAcquireLeaseOptionsBuilder<'a> { + builders::BlobBlobAcquireLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobBreakLeaseOptions<'a> { + break_period: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobBreakLeaseOptions<'a> { + pub fn builder() -> builders::BlobBlobBreakLeaseOptionsBuilder<'a> { + builders::BlobBlobBreakLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobChangeLeaseOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + proposed_lease_id: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobChangeLeaseOptions<'a> { + pub fn builder() -> builders::BlobBlobChangeLeaseOptionsBuilder<'a> { + builders::BlobBlobChangeLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobCopyFromUrlOptions<'a> { + blob_tags_string: Option, + copy_source_authorization: Option, + copy_source_tags: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + lease_id: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_content_md5: Option, + source_if_match: Option, + source_if_modified_since: Option, + source_if_none_match: Option, + source_if_unmodified_since: Option, + tier: Option, + timeout: Option, +} + +impl<'a> BlobBlobCopyFromUrlOptions<'a> { + pub fn builder() -> builders::BlobBlobCopyFromUrlOptionsBuilder<'a> { + builders::BlobBlobCopyFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobCreateSnapshotOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobCreateSnapshotOptions<'a> { + pub fn builder() -> builders::BlobBlobCreateSnapshotOptionsBuilder<'a> { + builders::BlobBlobCreateSnapshotOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobDeleteOptions<'a> { + blob_delete_type: Option, + delete_snapshots: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + snapshot: Option, + timeout: Option, +} + +impl<'a> BlobBlobDeleteOptions<'a> { + pub fn builder() -> builders::BlobBlobDeleteOptionsBuilder<'a> { + builders::BlobBlobDeleteOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobDeleteImmutabilityPolicyOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobDeleteImmutabilityPolicyOptions<'a> { + pub fn builder() -> builders::BlobBlobDeleteImmutabilityPolicyOptionsBuilder<'a> { + builders::BlobBlobDeleteImmutabilityPolicyOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobDownloadOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + range: Option, + range_content_crc64: Option, + range_content_md5: Option, + request_id: Option, + snapshot: Option, + timeout: Option, +} + +impl<'a> BlobBlobDownloadOptions<'a> { + pub fn builder() -> builders::BlobBlobDownloadOptionsBuilder<'a> { + builders::BlobBlobDownloadOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobGetAccountInfoOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, +} + +impl<'a> BlobBlobGetAccountInfoOptions<'a> { + pub fn builder() -> builders::BlobBlobGetAccountInfoOptionsBuilder<'a> { + builders::BlobBlobGetAccountInfoOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobGetPropertiesOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + snapshot: Option, +} + +impl<'a> BlobBlobGetPropertiesOptions<'a> { + pub fn builder() -> builders::BlobBlobGetPropertiesOptionsBuilder<'a> { + builders::BlobBlobGetPropertiesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobGetTagsOptions<'a> { + if_tags: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + snapshot: Option, + timeout: Option, +} + +impl<'a> BlobBlobGetTagsOptions<'a> { + pub fn builder() -> builders::BlobBlobGetTagsOptionsBuilder<'a> { + builders::BlobBlobGetTagsOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobQueryOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + snapshot: Option, + timeout: Option, +} + +impl<'a> BlobBlobQueryOptions<'a> { + pub fn builder() -> builders::BlobBlobQueryOptionsBuilder<'a> { + builders::BlobBlobQueryOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobReleaseLeaseOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobReleaseLeaseOptions<'a> { + pub fn builder() -> builders::BlobBlobReleaseLeaseOptionsBuilder<'a> { + builders::BlobBlobReleaseLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobRenewLeaseOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobRenewLeaseOptions<'a> { + pub fn builder() -> builders::BlobBlobRenewLeaseOptionsBuilder<'a> { + builders::BlobBlobRenewLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetExpiryOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, +} + +impl<'a> BlobBlobSetExpiryOptions<'a> { + pub fn builder() -> builders::BlobBlobSetExpiryOptionsBuilder<'a> { + builders::BlobBlobSetExpiryOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetHttpHeadersOptions<'a> { + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobSetHttpHeadersOptions<'a> { + pub fn builder() -> builders::BlobBlobSetHttpHeadersOptionsBuilder<'a> { + builders::BlobBlobSetHttpHeadersOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetImmutabilityPolicyOptions<'a> { + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobSetImmutabilityPolicyOptions<'a> { + pub fn builder() -> builders::BlobBlobSetImmutabilityPolicyOptionsBuilder<'a> { + builders::BlobBlobSetImmutabilityPolicyOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetLegalHoldOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobSetLegalHoldOptions<'a> { + pub fn builder() -> builders::BlobBlobSetLegalHoldOptionsBuilder<'a> { + builders::BlobBlobSetLegalHoldOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetMetadataOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobSetMetadataOptions<'a> { + pub fn builder() -> builders::BlobBlobSetMetadataOptionsBuilder<'a> { + builders::BlobBlobSetMetadataOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetTagsOptions<'a> { + if_tags: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobBlobSetTagsOptions<'a> { + pub fn builder() -> builders::BlobBlobSetTagsOptionsBuilder<'a> { + builders::BlobBlobSetTagsOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobSetTierOptions<'a> { + if_tags: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + rehydrate_priority: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobBlobSetTierOptions<'a> { + pub fn builder() -> builders::BlobBlobSetTierOptionsBuilder<'a> { + builders::BlobBlobSetTierOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobStartCopyFromUrlOptions<'a> { + blob_tags_string: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + lease_id: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + rehydrate_priority: Option, + request_id: Option, + seal_blob: Option, + source_if_match: Option, + source_if_modified_since: Option, + source_if_none_match: Option, + source_if_tags: Option, + source_if_unmodified_since: Option, + tier: Option, + timeout: Option, +} + +impl<'a> BlobBlobStartCopyFromUrlOptions<'a> { + pub fn builder() -> builders::BlobBlobStartCopyFromUrlOptionsBuilder<'a> { + builders::BlobBlobStartCopyFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlobUndeleteOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, +} + +impl<'a> BlobBlobUndeleteOptions<'a> { + pub fn builder() -> builders::BlobBlobUndeleteOptionsBuilder<'a> { + builders::BlobBlobUndeleteOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobBlobAbortCopyFromUrlOptionsBuilder<'a> { + options: BlobBlobAbortCopyFromUrlOptions<'a>, + } + + impl BlobBlobAbortCopyFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobAbortCopyFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobAbortCopyFromUrlOptions { + self.options.clone() + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobAbortCopyFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobAcquireLeaseOptionsBuilder<'a> { + options: BlobBlobAcquireLeaseOptions<'a>, + } + + impl BlobBlobAcquireLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobAcquireLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobAcquireLeaseOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_proposed_lease_id(mut self, proposed_lease_id: String) -> Self { + self.options.proposed_lease_id = Some(proposed_lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobAcquireLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobBreakLeaseOptionsBuilder<'a> { + options: BlobBlobBreakLeaseOptions<'a>, + } + + impl BlobBlobBreakLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobBreakLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobBreakLeaseOptions { + self.options.clone() + } + + pub fn with_break_period(mut self, break_period: i32) -> Self { + self.options.break_period = Some(break_period); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobBreakLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobChangeLeaseOptionsBuilder<'a> { + options: BlobBlobChangeLeaseOptions<'a>, + } + + impl BlobBlobChangeLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobChangeLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobChangeLeaseOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_proposed_lease_id(mut self, proposed_lease_id: String) -> Self { + self.options.proposed_lease_id = Some(proposed_lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobChangeLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobCopyFromUrlOptionsBuilder<'a> { + options: BlobBlobCopyFromUrlOptions<'a>, + } + + impl BlobBlobCopyFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobCopyFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobCopyFromUrlOptions { + self.options.clone() + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_copy_source_authorization(mut self, copy_source_authorization: String) -> Self { + self.options.copy_source_authorization = Some(copy_source_authorization); + self + } + + pub fn with_copy_source_tags(mut self, copy_source_tags: String) -> Self { + self.options.copy_source_tags = Some(copy_source_tags); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_content_md5(mut self, source_content_md5: String) -> Self { + self.options.source_content_md5 = Some(source_content_md5); + self + } + + pub fn with_source_if_match(mut self, source_if_match: String) -> Self { + self.options.source_if_match = Some(source_if_match); + self + } + + pub fn with_source_if_modified_since( + mut self, + source_if_modified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_modified_since = Some(source_if_modified_since); + self + } + + pub fn with_source_if_none_match(mut self, source_if_none_match: String) -> Self { + self.options.source_if_none_match = Some(source_if_none_match); + self + } + + pub fn with_source_if_unmodified_since( + mut self, + source_if_unmodified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_unmodified_since = Some(source_if_unmodified_since); + self + } + + pub fn with_tier(mut self, tier: AccessTier) -> Self { + self.options.tier = Some(tier); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobCopyFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobCreateSnapshotOptionsBuilder<'a> { + options: BlobBlobCreateSnapshotOptions<'a>, + } + + impl BlobBlobCreateSnapshotOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobCreateSnapshotOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobCreateSnapshotOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobCreateSnapshotOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobDeleteOptionsBuilder<'a> { + options: BlobBlobDeleteOptions<'a>, + } + + impl BlobBlobDeleteOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobDeleteOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobDeleteOptions { + self.options.clone() + } + + pub fn with_blob_delete_type( + mut self, + blob_delete_type: DeleteSnapshotsOptionType, + ) -> Self { + self.options.blob_delete_type = Some(blob_delete_type); + self + } + + pub fn with_delete_snapshots( + mut self, + delete_snapshots: DeleteSnapshotsOptionType, + ) -> Self { + self.options.delete_snapshots = Some(delete_snapshots); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobDeleteOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobDeleteImmutabilityPolicyOptionsBuilder<'a> { + options: BlobBlobDeleteImmutabilityPolicyOptions<'a>, + } + + impl BlobBlobDeleteImmutabilityPolicyOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobDeleteImmutabilityPolicyOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobDeleteImmutabilityPolicyOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobDeleteImmutabilityPolicyOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobDownloadOptionsBuilder<'a> { + options: BlobBlobDownloadOptions<'a>, + } + + impl BlobBlobDownloadOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobDownloadOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobDownloadOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_range(mut self, range: String) -> Self { + self.options.range = Some(range); + self + } + + pub fn with_range_content_crc64(mut self, range_content_crc64: bool) -> Self { + self.options.range_content_crc64 = Some(range_content_crc64); + self + } + + pub fn with_range_content_md5(mut self, range_content_md5: bool) -> Self { + self.options.range_content_md5 = Some(range_content_md5); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobDownloadOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobGetAccountInfoOptionsBuilder<'a> { + options: BlobBlobGetAccountInfoOptions<'a>, + } + + impl BlobBlobGetAccountInfoOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobGetAccountInfoOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobGetAccountInfoOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobGetAccountInfoOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobGetPropertiesOptionsBuilder<'a> { + options: BlobBlobGetPropertiesOptions<'a>, + } + + impl BlobBlobGetPropertiesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobGetPropertiesOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobGetPropertiesOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobGetPropertiesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobGetTagsOptionsBuilder<'a> { + options: BlobBlobGetTagsOptions<'a>, + } + + impl BlobBlobGetTagsOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobGetTagsOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobGetTagsOptions { + self.options.clone() + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobGetTagsOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobQueryOptionsBuilder<'a> { + options: BlobBlobQueryOptions<'a>, + } + + impl BlobBlobQueryOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobQueryOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobQueryOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobQueryOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobReleaseLeaseOptionsBuilder<'a> { + options: BlobBlobReleaseLeaseOptions<'a>, + } + + impl BlobBlobReleaseLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobReleaseLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobReleaseLeaseOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobReleaseLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobRenewLeaseOptionsBuilder<'a> { + options: BlobBlobRenewLeaseOptions<'a>, + } + + impl BlobBlobRenewLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobRenewLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobRenewLeaseOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobRenewLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetExpiryOptionsBuilder<'a> { + options: BlobBlobSetExpiryOptions<'a>, + } + + impl BlobBlobSetExpiryOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetExpiryOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetExpiryOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetExpiryOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetHttpHeadersOptionsBuilder<'a> { + options: BlobBlobSetHttpHeadersOptions<'a>, + } + + impl BlobBlobSetHttpHeadersOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetHttpHeadersOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetHttpHeadersOptions { + self.options.clone() + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetHttpHeadersOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetImmutabilityPolicyOptionsBuilder<'a> { + options: BlobBlobSetImmutabilityPolicyOptions<'a>, + } + + impl BlobBlobSetImmutabilityPolicyOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetImmutabilityPolicyOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetImmutabilityPolicyOptions { + self.options.clone() + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetImmutabilityPolicyOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetLegalHoldOptionsBuilder<'a> { + options: BlobBlobSetLegalHoldOptions<'a>, + } + + impl BlobBlobSetLegalHoldOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetLegalHoldOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetLegalHoldOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetLegalHoldOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetMetadataOptionsBuilder<'a> { + options: BlobBlobSetMetadataOptions<'a>, + } + + impl BlobBlobSetMetadataOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetMetadataOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetMetadataOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetMetadataOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetTagsOptionsBuilder<'a> { + options: BlobBlobSetTagsOptions<'a>, + } + + impl BlobBlobSetTagsOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetTagsOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetTagsOptions { + self.options.clone() + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetTagsOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobSetTierOptionsBuilder<'a> { + options: BlobBlobSetTierOptions<'a>, + } + + impl BlobBlobSetTierOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobSetTierOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobSetTierOptions { + self.options.clone() + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_rehydrate_priority(mut self, rehydrate_priority: RehydratePriority) -> Self { + self.options.rehydrate_priority = Some(rehydrate_priority); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobSetTierOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobStartCopyFromUrlOptionsBuilder<'a> { + options: BlobBlobStartCopyFromUrlOptions<'a>, + } + + impl BlobBlobStartCopyFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobStartCopyFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobStartCopyFromUrlOptions { + self.options.clone() + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_rehydrate_priority(mut self, rehydrate_priority: RehydratePriority) -> Self { + self.options.rehydrate_priority = Some(rehydrate_priority); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_seal_blob(mut self, seal_blob: bool) -> Self { + self.options.seal_blob = Some(seal_blob); + self + } + + pub fn with_source_if_match(mut self, source_if_match: String) -> Self { + self.options.source_if_match = Some(source_if_match); + self + } + + pub fn with_source_if_modified_since( + mut self, + source_if_modified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_modified_since = Some(source_if_modified_since); + self + } + + pub fn with_source_if_none_match(mut self, source_if_none_match: String) -> Self { + self.options.source_if_none_match = Some(source_if_none_match); + self + } + + pub fn with_source_if_tags(mut self, source_if_tags: String) -> Self { + self.options.source_if_tags = Some(source_if_tags); + self + } + + pub fn with_source_if_unmodified_since( + mut self, + source_if_unmodified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_unmodified_since = Some(source_if_unmodified_since); + self + } + + pub fn with_tier(mut self, tier: AccessTier) -> Self { + self.options.tier = Some(tier); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobStartCopyFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlobUndeleteOptionsBuilder<'a> { + options: BlobBlobUndeleteOptions<'a>, + } + + impl BlobBlobUndeleteOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlobUndeleteOptions::default(), + } + } + + pub fn build(&self) -> BlobBlobUndeleteOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlobUndeleteOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs new file mode 100644 index 0000000000..ae3210e657 --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs @@ -0,0 +1,1402 @@ +// 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 crate::models::{AccessTier, BlobImmutabilityPolicyMode, BlockListType, BlockLookupList}; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; +use time::OffsetDateTime; + +pub struct BlobBlockBlob { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobBlockBlob { + /// The Commit Block List operation writes a blob by specifying the list of block IDs that make up the blob. In order to be + /// written as part of a blob, a block must have been successfully written to the server in a prior Put Block operation. You + /// can call Put Block List to update a blob by uploading only those blocks that have changed, then committing the new and + /// existing blocks together. You can do this by specifying whether to commit a block from the committed block list or from + /// the uncommitted block list, or to commit the most recently uploaded version of the block, whichever list it may belong + /// to. + pub async fn commit_block_list( + &self, + blocks: RequestContent, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/?comp=blocklist/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + 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-type", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(tier) = options.tier { + request.insert_header("x-ms-access-tier", tier.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(blocks); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get Block List operation retrieves the list of blocks that have been uploaded as part of a block blob. + pub async fn get_block_list( + &self, + container_name: impl Into, + blob: impl Into, + list_type: BlockListType, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/?comp=blocklist/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + url.query_pairs_mut() + .append_pair("blocklisttype", &list_type.to_string()); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Put Blob from URL operation creates a new Block Blob where the contents of the blob are read from a given URL. This + /// API is supported beginning with the 2020-04-08 version. Partial updates are not supported with Put Blob from URL; the + /// content of an existing blob is overwritten with the content of the new blob. To perform partial updates to a block blob’s + /// contents using a source URL, use the Put Block from URL API in conjunction with Put Block List. + pub async fn put_blob_from_url( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + copy_source: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?BlockBlob&fromUrl"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + 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); + } + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(tier) = options.tier { + request.insert_header("x-ms-access-tier", tier.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-copy-source", copy_source.into()); + if let Some(copy_source_authorization) = options.copy_source_authorization { + request.insert_header("x-ms-copy-source-authorization", copy_source_authorization); + } + if let Some(copy_source_blob_properties) = options.copy_source_blob_properties { + request.insert_header( + "x-ms-copy-source-blob-properties", + copy_source_blob_properties.to_string(), + ); + } + if let Some(copy_source_tags) = options.copy_source_tags { + request.insert_header("x-ms-copy-source-tags", copy_source_tags); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(source_content_md5) = options.source_content_md5 { + request.insert_header("x-ms-source-content-md5", source_content_md5); + } + if let Some(source_if_match) = options.source_if_match { + request.insert_header("x-ms-source-if-match", source_if_match); + } + if let Some(source_if_modified_since) = options.source_if_modified_since { + request.insert_header( + "x-ms-source-if-modified-since", + source_if_modified_since.to_string(), + ); + } + if let Some(source_if_none_match) = options.source_if_none_match { + request.insert_header("x-ms-source-if-none-match", source_if_none_match); + } + if let Some(source_if_tags) = options.source_if_tags { + request.insert_header("x-ms-source-if-tags", source_if_tags); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Stage Block operation creates a new block to be committed as part of a blob + pub async fn stage_block( + &self, + body: RequestContent>, + container_name: impl Into, + blob: impl Into, + block_id: impl Into, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=block"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + url.query_pairs_mut() + .append_pair("blockid", &block_id.into()); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + 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-type", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Stage Block From URL operation creates a new block to be committed as part of a blob where the contents are read from + /// a URL. + pub async fn stage_block_from_url( + &self, + container_name: impl Into, + blob: impl Into, + block_id: impl Into, + content_length: i64, + source_url: impl Into, + source_range: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/?comp=block&fromURL/{containerName}/{blob}"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + url.query_pairs_mut() + .append_pair("blockid", &block_id.into()); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(copy_source_authorization) = options.copy_source_authorization { + request.insert_header("x-ms-copy-source-authorization", copy_source_authorization); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(source_content_crc64) = options.source_content_crc64 { + request.insert_header("x-ms-source-content-crc64", source_content_crc64); + } + if let Some(source_content_md5) = options.source_content_md5 { + request.insert_header("x-ms-source-content-md5", source_content_md5); + } + if let Some(source_if_match) = options.source_if_match { + request.insert_header("x-ms-source-if-match", source_if_match); + } + if let Some(source_if_modified_since) = options.source_if_modified_since { + request.insert_header( + "x-ms-source-if-modified-since", + source_if_modified_since.to_string(), + ); + } + if let Some(source_if_none_match) = options.source_if_none_match { + request.insert_header("x-ms-source-if-none-match", source_if_none_match); + } + if let Some(source_if_unmodified_since) = options.source_if_unmodified_since { + request.insert_header( + "x-ms-source-if-unmodified-since", + source_if_unmodified_since.to_string(), + ); + } + request.insert_header("x-ms-source-range", source_range.into()); + request.insert_header("x-ms-source-url", source_url.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Upload Block Blob operation updates the content of an existing block blob. Updating an existing block blob overwrites + /// any existing metadata on the blob. Partial updates are not supported with Put Blob; the content of the existing blob is + /// overwritten with the content of the new blob. To perform a partial update of the content of a block blob, use the Put + /// Block List operation. + pub async fn upload( + &self, + container_name: impl Into, + blob: impl Into, + body: RequestContent>, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?BlockBlob"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + 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-type", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(tier) = options.tier { + request.insert_header("x-ms-access-tier", tier.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_mode) = options.immutability_policy_mode { + request.insert_header( + "x-ms-immutability-policy-mode", + immutability_policy_mode.to_string(), + ); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobCommitBlockListOptions<'a> { + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + blob_tags_string: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + tier: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobBlockBlobCommitBlockListOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobCommitBlockListOptionsBuilder<'a> { + builders::BlobBlockBlobCommitBlockListOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobGetBlockListOptions<'a> { + if_tags: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + snapshot: Option, +} + +impl<'a> BlobBlockBlobGetBlockListOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobGetBlockListOptionsBuilder<'a> { + builders::BlobBlockBlobGetBlockListOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobPutBlobFromUrlOptions<'a> { + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + blob_tags_string: Option, + copy_source_authorization: Option, + copy_source_blob_properties: Option, + copy_source_tags: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_content_md5: Option, + source_if_match: Option, + source_if_modified_since: Option, + source_if_none_match: Option, + source_if_tags: Option, + tier: Option, + timeout: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobBlockBlobPutBlobFromUrlOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobPutBlobFromUrlOptionsBuilder<'a> { + builders::BlobBlockBlobPutBlobFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobStageBlockOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobBlockBlobStageBlockOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobStageBlockOptionsBuilder<'a> { + builders::BlobBlockBlobStageBlockOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobStageBlockFromUrlOptions<'a> { + copy_source_authorization: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_content_crc64: Option, + source_content_md5: Option, + source_if_match: Option, + source_if_modified_since: Option, + source_if_none_match: Option, + source_if_unmodified_since: Option, + timeout: Option, +} + +impl<'a> BlobBlockBlobStageBlockFromUrlOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobStageBlockFromUrlOptionsBuilder<'a> { + builders::BlobBlockBlobStageBlockFromUrlOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobBlockBlobUploadOptions<'a> { + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + blob_tags_string: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + immutability_policy_mode: Option, + lease_id: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + tier: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobBlockBlobUploadOptions<'a> { + pub fn builder() -> builders::BlobBlockBlobUploadOptionsBuilder<'a> { + builders::BlobBlockBlobUploadOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobBlockBlobCommitBlockListOptionsBuilder<'a> { + options: BlobBlockBlobCommitBlockListOptions<'a>, + } + + impl BlobBlockBlobCommitBlockListOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobCommitBlockListOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobCommitBlockListOptions { + self.options.clone() + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_tier(mut self, tier: AccessTier) -> Self { + self.options.tier = Some(tier); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobCommitBlockListOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlockBlobGetBlockListOptionsBuilder<'a> { + options: BlobBlockBlobGetBlockListOptions<'a>, + } + + impl BlobBlockBlobGetBlockListOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobGetBlockListOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobGetBlockListOptions { + self.options.clone() + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobGetBlockListOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlockBlobPutBlobFromUrlOptionsBuilder<'a> { + options: BlobBlockBlobPutBlobFromUrlOptions<'a>, + } + + impl BlobBlockBlobPutBlobFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobPutBlobFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobPutBlobFromUrlOptions { + self.options.clone() + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_copy_source_authorization(mut self, copy_source_authorization: String) -> Self { + self.options.copy_source_authorization = Some(copy_source_authorization); + self + } + + pub fn with_copy_source_blob_properties( + mut self, + copy_source_blob_properties: bool, + ) -> Self { + self.options.copy_source_blob_properties = Some(copy_source_blob_properties); + self + } + + pub fn with_copy_source_tags(mut self, copy_source_tags: String) -> Self { + self.options.copy_source_tags = Some(copy_source_tags); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_content_md5(mut self, source_content_md5: String) -> Self { + self.options.source_content_md5 = Some(source_content_md5); + self + } + + pub fn with_source_if_match(mut self, source_if_match: String) -> Self { + self.options.source_if_match = Some(source_if_match); + self + } + + pub fn with_source_if_modified_since( + mut self, + source_if_modified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_modified_since = Some(source_if_modified_since); + self + } + + pub fn with_source_if_none_match(mut self, source_if_none_match: String) -> Self { + self.options.source_if_none_match = Some(source_if_none_match); + self + } + + pub fn with_source_if_tags(mut self, source_if_tags: String) -> Self { + self.options.source_if_tags = Some(source_if_tags); + self + } + + pub fn with_tier(mut self, tier: AccessTier) -> Self { + self.options.tier = Some(tier); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobPutBlobFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlockBlobStageBlockOptionsBuilder<'a> { + options: BlobBlockBlobStageBlockOptions<'a>, + } + + impl BlobBlockBlobStageBlockOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobStageBlockOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobStageBlockOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobStageBlockOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlockBlobStageBlockFromUrlOptionsBuilder<'a> { + options: BlobBlockBlobStageBlockFromUrlOptions<'a>, + } + + impl BlobBlockBlobStageBlockFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobStageBlockFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobStageBlockFromUrlOptions { + self.options.clone() + } + + pub fn with_copy_source_authorization(mut self, copy_source_authorization: String) -> Self { + self.options.copy_source_authorization = Some(copy_source_authorization); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_content_crc64(mut self, source_content_crc64: String) -> Self { + self.options.source_content_crc64 = Some(source_content_crc64); + self + } + + pub fn with_source_content_md5(mut self, source_content_md5: String) -> Self { + self.options.source_content_md5 = Some(source_content_md5); + self + } + + pub fn with_source_if_match(mut self, source_if_match: String) -> Self { + self.options.source_if_match = Some(source_if_match); + self + } + + pub fn with_source_if_modified_since( + mut self, + source_if_modified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_modified_since = Some(source_if_modified_since); + self + } + + pub fn with_source_if_none_match(mut self, source_if_none_match: String) -> Self { + self.options.source_if_none_match = Some(source_if_none_match); + self + } + + pub fn with_source_if_unmodified_since( + mut self, + source_if_unmodified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_unmodified_since = Some(source_if_unmodified_since); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobStageBlockFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobBlockBlobUploadOptionsBuilder<'a> { + options: BlobBlockBlobUploadOptions<'a>, + } + + impl BlobBlockBlobUploadOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobBlockBlobUploadOptions::default(), + } + } + + pub fn build(&self) -> BlobBlockBlobUploadOptions { + self.options.clone() + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_immutability_policy_mode( + mut self, + immutability_policy_mode: BlobImmutabilityPolicyMode, + ) -> Self { + self.options.immutability_policy_mode = Some(immutability_policy_mode); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_tier(mut self, tier: AccessTier) -> Self { + self.options.tier = Some(tier); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobBlockBlobUploadOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/blob_storage/src/generated/clients/blob_client.rs new file mode 100644 index 0000000000..a8cd2d0db9 --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_client.rs @@ -0,0 +1,159 @@ +// 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 crate::blob_append_blob::BlobAppendBlob; +use crate::blob_blob::BlobBlob; +use crate::blob_block_blob::BlobBlockBlob; +use crate::blob_container::BlobContainer; +use crate::blob_page_blob::BlobPageBlob; +use crate::blob_service::BlobService; +use azure_core::builders::ClientOptionsBuilder; +use azure_core::{ClientOptions, Pipeline, Policy, Result, RetryOptions, TransportOptions, Url}; +use std::sync::Arc; + +pub struct BlobClient { + endpoint: Url, + pipeline: Pipeline, +} + +#[derive(Clone, Debug)] +pub struct BlobClientOptions { + client_options: ClientOptions, +} + +impl BlobClient { + pub fn with_no_credential( + endpoint: impl AsRef, + options: Option, + ) -> Result { + let mut endpoint = Url::parse(endpoint.as_ref())?; + endpoint.query_pairs_mut().clear(); + let options = options.unwrap_or_default(); + Ok(Self { + endpoint, + pipeline: Pipeline::new( + option_env!("CARGO_PKG_NAME"), + option_env!("CARGO_PKG_VERSION"), + options.client_options, + Vec::default(), + Vec::default(), + ), + }) + } + + pub fn get_blob_append_blob_client(&self) -> BlobAppendBlob { + BlobAppendBlob { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + pub fn get_blob_blob_client(&self) -> BlobBlob { + BlobBlob { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + pub fn get_blob_block_blob_client(&self) -> BlobBlockBlob { + BlobBlockBlob { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + pub fn get_blob_container_client(&self) -> BlobContainer { + BlobContainer { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + pub fn get_blob_page_blob_client(&self) -> BlobPageBlob { + BlobPageBlob { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } + + pub fn get_blob_service_client(&self) -> BlobService { + BlobService { + endpoint: self.endpoint.clone(), + pipeline: self.pipeline.clone(), + } + } +} + +impl BlobClientOptions { + pub fn builder() -> builders::BlobClientOptionsBuilder { + builders::BlobClientOptionsBuilder::new() + } +} + +impl Default for BlobClientOptions { + fn default() -> Self { + Self { + client_options: ClientOptions::default(), + } + } +} + +impl ClientOptionsBuilder for BlobClientOptions { + fn with_per_call_policies

(mut self, per_call_policies: P) -> Self + where + P: Into>>, + Self: Sized, + { + self.client_options.set_per_call_policies(per_call_policies); + self + } + + fn with_per_try_policies

(mut self, per_try_policies: P) -> Self + where + P: Into>>, + Self: Sized, + { + self.client_options.set_per_try_policies(per_try_policies); + self + } + + fn with_retry

(mut self, retry: P) -> Self + where + P: Into, + Self: Sized, + { + self.client_options.set_retry(retry); + self + } + + fn with_transport

(mut self, transport: P) -> Self + where + P: Into, + Self: Sized, + { + self.client_options.set_transport(transport); + self + } +} + +pub mod builders { + use super::*; + + pub struct BlobClientOptionsBuilder { + options: BlobClientOptions, + } + + impl BlobClientOptionsBuilder { + pub(super) fn new() -> Self { + Self { + options: BlobClientOptions::default(), + } + } + + pub fn build(&self) -> BlobClientOptions { + self.options.clone() + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/blob_storage/src/generated/clients/blob_container.rs new file mode 100644 index 0000000000..72e8b9609d --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_container.rs @@ -0,0 +1,1737 @@ +// 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 crate::models::{ + FilterBlobSegment, FilterBlobsIncludes, ListBlobsFlatSegmentResponse, + ListBlobsHierarchySegmentResponse, ListBlobsIncludes, PublicAccessType, SignedIdentifier, +}; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; +use time::OffsetDateTime; + +pub struct BlobContainer { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobContainer { + /// [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, + /// or can be infinite + pub async fn acquire_lease( + &self, + container_name: impl Into, + duration: i32, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?comp=lease&restype=container&acquire"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-lease-duration", duration.to_string()); + 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-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, + /// or can be infinite + pub async fn break_lease( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?comp=lease&restype=container&break"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(break_period) = options.break_period { + request.insert_header("x-ms-lease-break-period", break_period.to_string()); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, + /// or can be infinite + pub async fn change_lease( + &self, + container_name: impl Into, + lease_id: impl Into, + proposed_lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?comp=lease&restype=container&change"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + request.insert_header("x-ms-proposed-lease-id", proposed_lease_id.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Creates a new container under the specified account. If the container with the same name already exists, the operation + /// fails. + pub async fn create( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(access) = options.access { + request.insert_header("x-ms-blob-public-access", access.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(default_encryption_scope) = options.default_encryption_scope { + request.insert_header("x-ms-default-encryption-scope", default_encryption_scope); + } + if let Some(deny_encryption_scope_override) = options.deny_encryption_scope_override { + request.insert_header( + "x-ms-deny-encryption-scope-override", + deny_encryption_scope_override.to_string(), + ); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// operation marks the specified container for deletion. The container and any blobs contained within it are later deleted + /// during garbage collection + pub async fn delete( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Delete); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Filter Blobs operation enables callers to list blobs in a container whose tags match a given search expression. Filter + /// blobs searches within the given container. + pub async fn filter_blobs( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=blobs"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(include) = options.include { + url.query_pairs_mut().append_pair( + "include", + &include + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(","), + ); + } + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + if let Some(where_param) = options.where_param { + url.query_pairs_mut().append_pair("where", &where_param); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// gets the permissions for the specified container. The permissions indicate whether container data may be accessed publicly. + pub async fn get_access_policy( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result>> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=acl"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Returns the sku name and account kind + pub async fn get_account_info( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=account&comp=properties"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// returns all user-defined metadata and system properties for the specified container. The data returned does not include + /// the container's list of blobs + pub async fn get_properties( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The List Blobs operation returns a list of the blobs under the specified container + pub async fn list_blob_flat_segment( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=list&flat"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(include) = options.include { + url.query_pairs_mut().append_pair( + "include", + &include + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(","), + ); + } + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(prefix) = options.prefix { + url.query_pairs_mut().append_pair("prefix", &prefix); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] The List Blobs operation returns a list of the blobs under the specified container + pub async fn list_blob_hierarchy_segment( + &self, + container_name: impl Into, + delimiter: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=list&hierarchy"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + url.query_pairs_mut() + .append_pair("delimiter", &delimiter.into()); + if let Some(include) = options.include { + url.query_pairs_mut().append_pair( + "include", + &include + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(","), + ); + } + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(prefix) = options.prefix { + url.query_pairs_mut().append_pair("prefix", &prefix); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, + /// or can be infinite + pub async fn release_lease( + &self, + container_name: impl Into, + lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?comp=lease&restype=container&release"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Renames an existing container. + pub async fn rename( + &self, + container_name: impl Into, + source_container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=rename"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-source-container-name", source_container_name.into()); + if let Some(source_lease_id) = options.source_lease_id { + request.insert_header("x-ms-source-lease-id", source_lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 to 60 seconds, + /// or can be infinite + pub async fn renew_lease( + &self, + container_name: impl Into, + lease_id: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?comp=lease&restype=container&renew"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-lease-id", lease_id.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// sets the permissions for the specified container. The permissions indicate whether blobs in a container may be accessed + /// publicly. + pub async fn set_access_policy( + &self, + container_name: impl Into, + acl: RequestContent>, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=acl"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(acl); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// operation sets one or more user-defined name-value pairs for the specified container. + pub async fn set_metadata( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=metadata"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Batch operation allows multiple API calls to be embedded into a single HTTP request. + pub async fn submit_batch( + &self, + body: RequestContent>, + container_name: impl Into, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result>> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=batch"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + request.insert_header("content-type", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Restores a previously-deleted container. + pub async fn undelete( + &self, + container_name: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}?restype=container&comp=undelete"); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(deleted_container_name) = options.deleted_container_name { + request.insert_header("x-ms-deleted-container-name", deleted_container_name); + } + if let Some(deleted_container_version) = options.deleted_container_version { + request.insert_header("x-ms-deleted-container-version", deleted_container_version); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerAcquireLeaseOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + proposed_lease_id: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerAcquireLeaseOptions<'a> { + pub fn builder() -> builders::BlobContainerAcquireLeaseOptionsBuilder<'a> { + builders::BlobContainerAcquireLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerBreakLeaseOptions<'a> { + break_period: Option, + if_modified_since: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerBreakLeaseOptions<'a> { + pub fn builder() -> builders::BlobContainerBreakLeaseOptionsBuilder<'a> { + builders::BlobContainerBreakLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerChangeLeaseOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerChangeLeaseOptions<'a> { + pub fn builder() -> builders::BlobContainerChangeLeaseOptionsBuilder<'a> { + builders::BlobContainerChangeLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerCreateOptions<'a> { + access: Option, + default_encryption_scope: Option, + deny_encryption_scope_override: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerCreateOptions<'a> { + pub fn builder() -> builders::BlobContainerCreateOptionsBuilder<'a> { + builders::BlobContainerCreateOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerDeleteOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerDeleteOptions<'a> { + pub fn builder() -> builders::BlobContainerDeleteOptionsBuilder<'a> { + builders::BlobContainerDeleteOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerFilterBlobsOptions<'a> { + include: Option>, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, + where_param: Option, +} + +impl<'a> BlobContainerFilterBlobsOptions<'a> { + pub fn builder() -> builders::BlobContainerFilterBlobsOptionsBuilder<'a> { + builders::BlobContainerFilterBlobsOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerGetAccessPolicyOptions<'a> { + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerGetAccessPolicyOptions<'a> { + pub fn builder() -> builders::BlobContainerGetAccessPolicyOptionsBuilder<'a> { + builders::BlobContainerGetAccessPolicyOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerGetAccountInfoOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, +} + +impl<'a> BlobContainerGetAccountInfoOptions<'a> { + pub fn builder() -> builders::BlobContainerGetAccountInfoOptionsBuilder<'a> { + builders::BlobContainerGetAccountInfoOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerGetPropertiesOptions<'a> { + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerGetPropertiesOptions<'a> { + pub fn builder() -> builders::BlobContainerGetPropertiesOptionsBuilder<'a> { + builders::BlobContainerGetPropertiesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerListBlobFlatSegmentOptions<'a> { + include: Option>, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + prefix: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerListBlobFlatSegmentOptions<'a> { + pub fn builder() -> builders::BlobContainerListBlobFlatSegmentOptionsBuilder<'a> { + builders::BlobContainerListBlobFlatSegmentOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerListBlobHierarchySegmentOptions<'a> { + include: Option>, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + prefix: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerListBlobHierarchySegmentOptions<'a> { + pub fn builder() -> builders::BlobContainerListBlobHierarchySegmentOptionsBuilder<'a> { + builders::BlobContainerListBlobHierarchySegmentOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerReleaseLeaseOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerReleaseLeaseOptions<'a> { + pub fn builder() -> builders::BlobContainerReleaseLeaseOptionsBuilder<'a> { + builders::BlobContainerReleaseLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerRenameOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_lease_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerRenameOptions<'a> { + pub fn builder() -> builders::BlobContainerRenameOptionsBuilder<'a> { + builders::BlobContainerRenameOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerRenewLeaseOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerRenewLeaseOptions<'a> { + pub fn builder() -> builders::BlobContainerRenewLeaseOptionsBuilder<'a> { + builders::BlobContainerRenewLeaseOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerSetAccessPolicyOptions<'a> { + if_modified_since: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerSetAccessPolicyOptions<'a> { + pub fn builder() -> builders::BlobContainerSetAccessPolicyOptionsBuilder<'a> { + builders::BlobContainerSetAccessPolicyOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerSetMetadataOptions<'a> { + if_modified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerSetMetadataOptions<'a> { + pub fn builder() -> builders::BlobContainerSetMetadataOptionsBuilder<'a> { + builders::BlobContainerSetMetadataOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerSubmitBatchOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerSubmitBatchOptions<'a> { + pub fn builder() -> builders::BlobContainerSubmitBatchOptionsBuilder<'a> { + builders::BlobContainerSubmitBatchOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobContainerUndeleteOptions<'a> { + deleted_container_name: Option, + deleted_container_version: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobContainerUndeleteOptions<'a> { + pub fn builder() -> builders::BlobContainerUndeleteOptionsBuilder<'a> { + builders::BlobContainerUndeleteOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobContainerAcquireLeaseOptionsBuilder<'a> { + options: BlobContainerAcquireLeaseOptions<'a>, + } + + impl BlobContainerAcquireLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerAcquireLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerAcquireLeaseOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_proposed_lease_id(mut self, proposed_lease_id: String) -> Self { + self.options.proposed_lease_id = Some(proposed_lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerAcquireLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerBreakLeaseOptionsBuilder<'a> { + options: BlobContainerBreakLeaseOptions<'a>, + } + + impl BlobContainerBreakLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerBreakLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerBreakLeaseOptions { + self.options.clone() + } + + pub fn with_break_period(mut self, break_period: i32) -> Self { + self.options.break_period = Some(break_period); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerBreakLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerChangeLeaseOptionsBuilder<'a> { + options: BlobContainerChangeLeaseOptions<'a>, + } + + impl BlobContainerChangeLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerChangeLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerChangeLeaseOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerChangeLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerCreateOptionsBuilder<'a> { + options: BlobContainerCreateOptions<'a>, + } + + impl BlobContainerCreateOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerCreateOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerCreateOptions { + self.options.clone() + } + + pub fn with_access(mut self, access: PublicAccessType) -> Self { + self.options.access = Some(access); + self + } + + pub fn with_default_encryption_scope(mut self, default_encryption_scope: String) -> Self { + self.options.default_encryption_scope = Some(default_encryption_scope); + self + } + + pub fn with_deny_encryption_scope_override( + mut self, + deny_encryption_scope_override: bool, + ) -> Self { + self.options.deny_encryption_scope_override = Some(deny_encryption_scope_override); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerCreateOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerDeleteOptionsBuilder<'a> { + options: BlobContainerDeleteOptions<'a>, + } + + impl BlobContainerDeleteOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerDeleteOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerDeleteOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerDeleteOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerFilterBlobsOptionsBuilder<'a> { + options: BlobContainerFilterBlobsOptions<'a>, + } + + impl BlobContainerFilterBlobsOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerFilterBlobsOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerFilterBlobsOptions { + self.options.clone() + } + + pub fn with_include(mut self, include: Vec) -> Self { + self.options.include = Some(include); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_where_param(mut self, where_param: String) -> Self { + self.options.where_param = Some(where_param); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerFilterBlobsOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerGetAccessPolicyOptionsBuilder<'a> { + options: BlobContainerGetAccessPolicyOptions<'a>, + } + + impl BlobContainerGetAccessPolicyOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerGetAccessPolicyOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerGetAccessPolicyOptions { + self.options.clone() + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerGetAccessPolicyOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerGetAccountInfoOptionsBuilder<'a> { + options: BlobContainerGetAccountInfoOptions<'a>, + } + + impl BlobContainerGetAccountInfoOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerGetAccountInfoOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerGetAccountInfoOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerGetAccountInfoOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerGetPropertiesOptionsBuilder<'a> { + options: BlobContainerGetPropertiesOptions<'a>, + } + + impl BlobContainerGetPropertiesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerGetPropertiesOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerGetPropertiesOptions { + self.options.clone() + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerGetPropertiesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerListBlobFlatSegmentOptionsBuilder<'a> { + options: BlobContainerListBlobFlatSegmentOptions<'a>, + } + + impl BlobContainerListBlobFlatSegmentOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerListBlobFlatSegmentOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerListBlobFlatSegmentOptions { + self.options.clone() + } + + pub fn with_include(mut self, include: Vec) -> Self { + self.options.include = Some(include); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_prefix(mut self, prefix: String) -> Self { + self.options.prefix = Some(prefix); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerListBlobFlatSegmentOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerListBlobHierarchySegmentOptionsBuilder<'a> { + options: BlobContainerListBlobHierarchySegmentOptions<'a>, + } + + impl BlobContainerListBlobHierarchySegmentOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerListBlobHierarchySegmentOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerListBlobHierarchySegmentOptions { + self.options.clone() + } + + pub fn with_include(mut self, include: Vec) -> Self { + self.options.include = Some(include); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_prefix(mut self, prefix: String) -> Self { + self.options.prefix = Some(prefix); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> + for BlobContainerListBlobHierarchySegmentOptionsBuilder<'a> + { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerReleaseLeaseOptionsBuilder<'a> { + options: BlobContainerReleaseLeaseOptions<'a>, + } + + impl BlobContainerReleaseLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerReleaseLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerReleaseLeaseOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerReleaseLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerRenameOptionsBuilder<'a> { + options: BlobContainerRenameOptions<'a>, + } + + impl BlobContainerRenameOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerRenameOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerRenameOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_lease_id(mut self, source_lease_id: String) -> Self { + self.options.source_lease_id = Some(source_lease_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerRenameOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerRenewLeaseOptionsBuilder<'a> { + options: BlobContainerRenewLeaseOptions<'a>, + } + + impl BlobContainerRenewLeaseOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerRenewLeaseOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerRenewLeaseOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerRenewLeaseOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerSetAccessPolicyOptionsBuilder<'a> { + options: BlobContainerSetAccessPolicyOptions<'a>, + } + + impl BlobContainerSetAccessPolicyOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerSetAccessPolicyOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerSetAccessPolicyOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerSetAccessPolicyOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerSetMetadataOptionsBuilder<'a> { + options: BlobContainerSetMetadataOptions<'a>, + } + + impl BlobContainerSetMetadataOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerSetMetadataOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerSetMetadataOptions { + self.options.clone() + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerSetMetadataOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerSubmitBatchOptionsBuilder<'a> { + options: BlobContainerSubmitBatchOptions<'a>, + } + + impl BlobContainerSubmitBatchOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerSubmitBatchOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerSubmitBatchOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerSubmitBatchOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobContainerUndeleteOptionsBuilder<'a> { + options: BlobContainerUndeleteOptions<'a>, + } + + impl BlobContainerUndeleteOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobContainerUndeleteOptions::default(), + } + } + + pub fn build(&self) -> BlobContainerUndeleteOptions { + self.options.clone() + } + + pub fn with_deleted_container_name(mut self, deleted_container_name: String) -> Self { + self.options.deleted_container_name = Some(deleted_container_name); + self + } + + pub fn with_deleted_container_version(mut self, deleted_container_version: String) -> Self { + self.options.deleted_container_version = Some(deleted_container_version); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobContainerUndeleteOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs b/sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs new file mode 100644 index 0000000000..dbf8f24d3c --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs @@ -0,0 +1,1791 @@ +// 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 crate::models::{PageList, PremiumPageBlobAccessTier, SequenceNumberActionType}; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; +use time::OffsetDateTime; + +pub struct BlobPageBlob { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobPageBlob { + /// The Clear Pages operation clears a range of pages from a page blob + pub async fn clear_pages( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=page&clear"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_sequence_number_equal_to) = options.if_sequence_number_equal_to { + request.insert_header( + "x-ms-if-sequence-number-eq", + if_sequence_number_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than_or_equal_to) = + options.if_sequence_number_less_than_or_equal_to + { + request.insert_header( + "x-ms-if-sequence-number-le", + if_sequence_number_less_than_or_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than) = options.if_sequence_number_less_than { + request.insert_header( + "x-ms-if-sequence-number-lt", + if_sequence_number_less_than.to_string(), + ); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(range) = options.range { + request.insert_header("x-ms-range", range); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Copy Incremental operation copies a snapshot of the source page blob to a destination page blob. The snapshot is copied + /// such that only the differential changes between the previously copied snapshot are transferred to the destination. The + /// copied snapshots are complete copies of the original snapshot and can be read or copied from as usual. This API is supported + /// since REST version 2016-05-31. + pub async fn copy_incremental( + &self, + container_name: impl Into, + blob: impl Into, + copy_source: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=incrementalcopy"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-copy-source", copy_source.into()); + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Create operation creates a new page blob. + pub async fn create( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + blob_content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?PageBlob"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(access_tier) = options.access_tier { + request.insert_header("x-ms-access-tier", access_tier.to_string()); + } + if let Some(blob_cache_control) = options.blob_cache_control { + request.insert_header("x-ms-blob-cache-control", blob_cache_control); + } + if let Some(blob_content_disposition) = options.blob_content_disposition { + request.insert_header("x-ms-blob-content-disposition", blob_content_disposition); + } + if let Some(blob_content_encoding) = options.blob_content_encoding { + request.insert_header("x-ms-blob-content-encoding", blob_content_encoding); + } + if let Some(blob_content_language) = options.blob_content_language { + request.insert_header("x-ms-blob-content-language", blob_content_language); + } + request.insert_header("x-ms-blob-content-length", blob_content_length.to_string()); + if let Some(blob_content_md5) = options.blob_content_md5 { + request.insert_header("x-ms-blob-content-md5", blob_content_md5); + } + if let Some(blob_content_type) = options.blob_content_type { + request.insert_header("x-ms-blob-content-type", blob_content_type); + } + if let Some(blob_sequence_number) = options.blob_sequence_number { + request.insert_header( + "x-ms-blob-sequence-number", + blob_sequence_number.to_string(), + ); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(immutability_policy_expiry) = options.immutability_policy_expiry { + request.insert_header( + "x-ms-immutability-policy-until-date", + immutability_policy_expiry, + ); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(legal_hold) = options.legal_hold { + request.insert_header("x-ms-legal-hold", legal_hold.to_string()); + } + if let Some(blob_tags_string) = options.blob_tags_string { + request.insert_header("x-ms-tags", blob_tags_string); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get Page Ranges operation returns the list of valid page ranges for a page blob or snapshot of a page blob. + pub async fn get_page_ranges( + &self, + container_name: impl Into, + blob: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=pagelist"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(range) = options.range { + request.insert_header("x-ms-range", range); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get Page Ranges Diff operation returns the list of valid page ranges for a page blob or snapshot of a page blob. + pub async fn get_page_ranges_diff( + &self, + container_name: impl Into, + blob: impl Into, + prevsnapshot: impl Into, + prev_snapshot_url: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=pagelist&diff"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + url.query_pairs_mut() + .append_pair("prevsnapshot", &prevsnapshot.into()); + if let Some(snapshot) = options.snapshot { + url.query_pairs_mut().append_pair("snapshot", &snapshot); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-previous-snapshot-url", prev_snapshot_url.into()); + if let Some(range) = options.range { + request.insert_header("x-ms-range", range); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Resize operation increases the size of the page blob to the specified size. + pub async fn resize( + &self, + container_name: impl Into, + blob: impl Into, + blob_content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=properties&Resize"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header("x-ms-blob-content-length", blob_content_length.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Update Sequence Number operation sets the blob's sequence number. The operation will fail if the specified sequence + /// number is less than the current sequence number of the blob. + pub async fn update_sequence_number( + &self, + container_name: impl Into, + blob: impl Into, + sequence_number_action: SequenceNumberActionType, + blob_sequence_number: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=properties&UpdateSequenceNumber"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + request.insert_header( + "x-ms-blob-sequence-number", + blob_sequence_number.to_string(), + ); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header( + "x-ms-sequence-number-action", + sequence_number_action.to_string(), + ); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Upload Pages operation writes a range of pages to a page blob + pub async fn upload_pages( + &self, + body: RequestContent>, + container_name: impl Into, + blob: impl Into, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=page&update"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + 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-type", "application/json"); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(transactional_content_crc64) = options.transactional_content_crc64 { + request.insert_header("x-ms-content-crc64", transactional_content_crc64); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_sequence_number_equal_to) = options.if_sequence_number_equal_to { + request.insert_header( + "x-ms-if-sequence-number-eq", + if_sequence_number_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than_or_equal_to) = + options.if_sequence_number_less_than_or_equal_to + { + request.insert_header( + "x-ms-if-sequence-number-le", + if_sequence_number_less_than_or_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than) = options.if_sequence_number_less_than { + request.insert_header( + "x-ms-if-sequence-number-lt", + if_sequence_number_less_than.to_string(), + ); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + if let Some(range) = options.range { + request.insert_header("x-ms-range", range); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Upload Pages operation writes a range of pages to a page blob where the contents are read from a URL. + pub async fn upload_pages_from_url( + &self, + container_name: impl Into, + blob: impl Into, + content_length: i64, + source_url: impl Into, + source_range: impl Into, + range: impl Into, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + let mut path = String::from("/{containerName}/{blob}?comp=page&update&fromUrl"); + path = path.replace("{blob}", &blob.into()); + path = path.replace("{containerName}", &container_name.into()); + url.set_path(&path); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(if_match) = options.if_match { + request.insert_header("if-match", if_match); + } + if let Some(if_modified_since) = options.if_modified_since { + request.insert_header("if-modified-since", if_modified_since.to_string()); + } + if let Some(if_none_match) = options.if_none_match { + request.insert_header("if-none-match", if_none_match); + } + if let Some(if_unmodified_since) = options.if_unmodified_since { + request.insert_header("if-unmodified-since", if_unmodified_since.to_string()); + } + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + if let Some(copy_source_authorization) = options.copy_source_authorization { + request.insert_header("x-ms-copy-source-authorization", copy_source_authorization); + } + if let Some(encryption_algorithm) = options.encryption_algorithm { + request.insert_header("x-ms-encryption-algorithm", encryption_algorithm); + } + if let Some(encryption_key) = options.encryption_key { + request.insert_header("x-ms-encryption-key", encryption_key); + } + if let Some(encryption_key_sha256) = options.encryption_key_sha256 { + request.insert_header("x-ms-encryption-key-sha256", encryption_key_sha256); + } + if let Some(encryption_scope) = options.encryption_scope { + request.insert_header("x-ms-encryption-scope", encryption_scope); + } + if let Some(if_sequence_number_equal_to) = options.if_sequence_number_equal_to { + request.insert_header( + "x-ms-if-sequence-number-eq", + if_sequence_number_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than_or_equal_to) = + options.if_sequence_number_less_than_or_equal_to + { + request.insert_header( + "x-ms-if-sequence-number-le", + if_sequence_number_less_than_or_equal_to.to_string(), + ); + } + if let Some(if_sequence_number_less_than) = options.if_sequence_number_less_than { + request.insert_header( + "x-ms-if-sequence-number-lt", + if_sequence_number_less_than.to_string(), + ); + } + if let Some(if_tags) = options.if_tags { + request.insert_header("x-ms-if-tags", if_tags); + } + if let Some(lease_id) = options.lease_id { + request.insert_header("x-ms-lease-id", lease_id); + } + request.insert_header("x-ms-range", range.into()); + if let Some(source_content_crc64) = options.source_content_crc64 { + request.insert_header("x-ms-source-content-crc64", source_content_crc64); + } + if let Some(source_content_md5) = options.source_content_md5 { + request.insert_header("x-ms-source-content-md5", source_content_md5); + } + if let Some(source_if_match) = options.source_if_match { + request.insert_header("x-ms-source-if-match", source_if_match); + } + if let Some(source_if_modified_since) = options.source_if_modified_since { + request.insert_header( + "x-ms-source-if-modified-since", + source_if_modified_since.to_string(), + ); + } + if let Some(source_if_none_match) = options.source_if_none_match { + request.insert_header("x-ms-source-if-none-match", source_if_none_match); + } + if let Some(source_if_unmodified_since) = options.source_if_unmodified_since { + request.insert_header( + "x-ms-source-if-unmodified-since", + source_if_unmodified_since.to_string(), + ); + } + request.insert_header("x-ms-source-range", source_range.into()); + request.insert_header("x-ms-source-url", source_url.into()); + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobClearPagesOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_sequence_number_equal_to: Option, + if_sequence_number_less_than: Option, + if_sequence_number_less_than_or_equal_to: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + range: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobClearPagesOptions<'a> { + pub fn builder() -> builders::BlobPageBlobClearPagesOptionsBuilder<'a> { + builders::BlobPageBlobClearPagesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobCopyIncrementalOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobCopyIncrementalOptions<'a> { + pub fn builder() -> builders::BlobPageBlobCopyIncrementalOptionsBuilder<'a> { + builders::BlobPageBlobCopyIncrementalOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobCreateOptions<'a> { + access_tier: Option, + blob_cache_control: Option, + blob_content_disposition: Option, + blob_content_encoding: Option, + blob_content_language: Option, + blob_content_md5: Option, + blob_content_type: Option, + blob_sequence_number: Option, + blob_tags_string: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + immutability_policy_expiry: Option, + lease_id: Option, + legal_hold: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobCreateOptions<'a> { + pub fn builder() -> builders::BlobPageBlobCreateOptionsBuilder<'a> { + builders::BlobPageBlobCreateOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobGetPageRangesOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + range: Option, + request_id: Option, + snapshot: Option, +} + +impl<'a> BlobPageBlobGetPageRangesOptions<'a> { + pub fn builder() -> builders::BlobPageBlobGetPageRangesOptionsBuilder<'a> { + builders::BlobPageBlobGetPageRangesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobGetPageRangesDiffOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + range: Option, + request_id: Option, + snapshot: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobGetPageRangesDiffOptions<'a> { + pub fn builder() -> builders::BlobPageBlobGetPageRangesDiffOptionsBuilder<'a> { + builders::BlobPageBlobGetPageRangesDiffOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobResizeOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobResizeOptions<'a> { + pub fn builder() -> builders::BlobPageBlobResizeOptionsBuilder<'a> { + builders::BlobPageBlobResizeOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobUpdateSequenceNumberOptions<'a> { + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobUpdateSequenceNumberOptions<'a> { + pub fn builder() -> builders::BlobPageBlobUpdateSequenceNumberOptionsBuilder<'a> { + builders::BlobPageBlobUpdateSequenceNumberOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobUploadPagesOptions<'a> { + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_sequence_number_equal_to: Option, + if_sequence_number_less_than: Option, + if_sequence_number_less_than_or_equal_to: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + range: Option, + request_id: Option, + timeout: Option, + transactional_content_crc64: Option, + transactional_content_md5: Option, +} + +impl<'a> BlobPageBlobUploadPagesOptions<'a> { + pub fn builder() -> builders::BlobPageBlobUploadPagesOptionsBuilder<'a> { + builders::BlobPageBlobUploadPagesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobPageBlobUploadPagesFromUrlOptions<'a> { + copy_source_authorization: Option, + encryption_algorithm: Option, + encryption_key: Option, + encryption_key_sha256: Option, + encryption_scope: Option, + if_match: Option, + if_modified_since: Option, + if_none_match: Option, + if_sequence_number_equal_to: Option, + if_sequence_number_less_than: Option, + if_sequence_number_less_than_or_equal_to: Option, + if_tags: Option, + if_unmodified_since: Option, + lease_id: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + source_content_crc64: Option, + source_content_md5: Option, + source_if_match: Option, + source_if_modified_since: Option, + source_if_none_match: Option, + source_if_unmodified_since: Option, + timeout: Option, +} + +impl<'a> BlobPageBlobUploadPagesFromUrlOptions<'a> { + pub fn builder() -> builders::BlobPageBlobUploadPagesFromUrlOptionsBuilder<'a> { + builders::BlobPageBlobUploadPagesFromUrlOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobPageBlobClearPagesOptionsBuilder<'a> { + options: BlobPageBlobClearPagesOptions<'a>, + } + + impl BlobPageBlobClearPagesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobClearPagesOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobClearPagesOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_sequence_number_equal_to( + mut self, + if_sequence_number_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_equal_to = Some(if_sequence_number_equal_to); + self + } + + pub fn with_if_sequence_number_less_than( + mut self, + if_sequence_number_less_than: i64, + ) -> Self { + self.options.if_sequence_number_less_than = Some(if_sequence_number_less_than); + self + } + + pub fn with_if_sequence_number_less_than_or_equal_to( + mut self, + if_sequence_number_less_than_or_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_less_than_or_equal_to = + Some(if_sequence_number_less_than_or_equal_to); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_range(mut self, range: String) -> Self { + self.options.range = Some(range); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobClearPagesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobCopyIncrementalOptionsBuilder<'a> { + options: BlobPageBlobCopyIncrementalOptions<'a>, + } + + impl BlobPageBlobCopyIncrementalOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobCopyIncrementalOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobCopyIncrementalOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobCopyIncrementalOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobCreateOptionsBuilder<'a> { + options: BlobPageBlobCreateOptions<'a>, + } + + impl BlobPageBlobCreateOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobCreateOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobCreateOptions { + self.options.clone() + } + + pub fn with_access_tier(mut self, access_tier: PremiumPageBlobAccessTier) -> Self { + self.options.access_tier = Some(access_tier); + self + } + + pub fn with_blob_cache_control(mut self, blob_cache_control: String) -> Self { + self.options.blob_cache_control = Some(blob_cache_control); + self + } + + pub fn with_blob_content_disposition(mut self, blob_content_disposition: String) -> Self { + self.options.blob_content_disposition = Some(blob_content_disposition); + self + } + + pub fn with_blob_content_encoding(mut self, blob_content_encoding: String) -> Self { + self.options.blob_content_encoding = Some(blob_content_encoding); + self + } + + pub fn with_blob_content_language(mut self, blob_content_language: String) -> Self { + self.options.blob_content_language = Some(blob_content_language); + self + } + + pub fn with_blob_content_md5(mut self, blob_content_md5: String) -> Self { + self.options.blob_content_md5 = Some(blob_content_md5); + self + } + + pub fn with_blob_content_type(mut self, blob_content_type: String) -> Self { + self.options.blob_content_type = Some(blob_content_type); + self + } + + pub fn with_blob_sequence_number(mut self, blob_sequence_number: i64) -> Self { + self.options.blob_sequence_number = Some(blob_sequence_number); + self + } + + pub fn with_blob_tags_string(mut self, blob_tags_string: String) -> Self { + self.options.blob_tags_string = Some(blob_tags_string); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_immutability_policy_expiry( + mut self, + immutability_policy_expiry: String, + ) -> Self { + self.options.immutability_policy_expiry = Some(immutability_policy_expiry); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_legal_hold(mut self, legal_hold: bool) -> Self { + self.options.legal_hold = Some(legal_hold); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobCreateOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobGetPageRangesOptionsBuilder<'a> { + options: BlobPageBlobGetPageRangesOptions<'a>, + } + + impl BlobPageBlobGetPageRangesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobGetPageRangesOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobGetPageRangesOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_range(mut self, range: String) -> Self { + self.options.range = Some(range); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobGetPageRangesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobGetPageRangesDiffOptionsBuilder<'a> { + options: BlobPageBlobGetPageRangesDiffOptions<'a>, + } + + impl BlobPageBlobGetPageRangesDiffOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobGetPageRangesDiffOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobGetPageRangesDiffOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_range(mut self, range: String) -> Self { + self.options.range = Some(range); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_snapshot(mut self, snapshot: String) -> Self { + self.options.snapshot = Some(snapshot); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobGetPageRangesDiffOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobResizeOptionsBuilder<'a> { + options: BlobPageBlobResizeOptions<'a>, + } + + impl BlobPageBlobResizeOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobResizeOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobResizeOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobResizeOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobUpdateSequenceNumberOptionsBuilder<'a> { + options: BlobPageBlobUpdateSequenceNumberOptions<'a>, + } + + impl BlobPageBlobUpdateSequenceNumberOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobUpdateSequenceNumberOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobUpdateSequenceNumberOptions { + self.options.clone() + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobUpdateSequenceNumberOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobUploadPagesOptionsBuilder<'a> { + options: BlobPageBlobUploadPagesOptions<'a>, + } + + impl BlobPageBlobUploadPagesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobUploadPagesOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobUploadPagesOptions { + self.options.clone() + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_sequence_number_equal_to( + mut self, + if_sequence_number_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_equal_to = Some(if_sequence_number_equal_to); + self + } + + pub fn with_if_sequence_number_less_than( + mut self, + if_sequence_number_less_than: i64, + ) -> Self { + self.options.if_sequence_number_less_than = Some(if_sequence_number_less_than); + self + } + + pub fn with_if_sequence_number_less_than_or_equal_to( + mut self, + if_sequence_number_less_than_or_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_less_than_or_equal_to = + Some(if_sequence_number_less_than_or_equal_to); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_range(mut self, range: String) -> Self { + self.options.range = Some(range); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_transactional_content_crc64( + mut self, + transactional_content_crc64: String, + ) -> Self { + self.options.transactional_content_crc64 = Some(transactional_content_crc64); + self + } + + pub fn with_transactional_content_md5(mut self, transactional_content_md5: String) -> Self { + self.options.transactional_content_md5 = Some(transactional_content_md5); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobUploadPagesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobPageBlobUploadPagesFromUrlOptionsBuilder<'a> { + options: BlobPageBlobUploadPagesFromUrlOptions<'a>, + } + + impl BlobPageBlobUploadPagesFromUrlOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobPageBlobUploadPagesFromUrlOptions::default(), + } + } + + pub fn build(&self) -> BlobPageBlobUploadPagesFromUrlOptions { + self.options.clone() + } + + pub fn with_copy_source_authorization(mut self, copy_source_authorization: String) -> Self { + self.options.copy_source_authorization = Some(copy_source_authorization); + self + } + + pub fn with_encryption_algorithm(mut self, encryption_algorithm: String) -> Self { + self.options.encryption_algorithm = Some(encryption_algorithm); + self + } + + pub fn with_encryption_key(mut self, encryption_key: String) -> Self { + self.options.encryption_key = Some(encryption_key); + self + } + + pub fn with_encryption_key_sha256(mut self, encryption_key_sha256: String) -> Self { + self.options.encryption_key_sha256 = Some(encryption_key_sha256); + self + } + + pub fn with_encryption_scope(mut self, encryption_scope: String) -> Self { + self.options.encryption_scope = Some(encryption_scope); + self + } + + pub fn with_if_match(mut self, if_match: String) -> Self { + self.options.if_match = Some(if_match); + self + } + + pub fn with_if_modified_since(mut self, if_modified_since: OffsetDateTime) -> Self { + self.options.if_modified_since = Some(if_modified_since); + self + } + + pub fn with_if_none_match(mut self, if_none_match: String) -> Self { + self.options.if_none_match = Some(if_none_match); + self + } + + pub fn with_if_sequence_number_equal_to( + mut self, + if_sequence_number_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_equal_to = Some(if_sequence_number_equal_to); + self + } + + pub fn with_if_sequence_number_less_than( + mut self, + if_sequence_number_less_than: i64, + ) -> Self { + self.options.if_sequence_number_less_than = Some(if_sequence_number_less_than); + self + } + + pub fn with_if_sequence_number_less_than_or_equal_to( + mut self, + if_sequence_number_less_than_or_equal_to: i64, + ) -> Self { + self.options.if_sequence_number_less_than_or_equal_to = + Some(if_sequence_number_less_than_or_equal_to); + self + } + + pub fn with_if_tags(mut self, if_tags: String) -> Self { + self.options.if_tags = Some(if_tags); + self + } + + pub fn with_if_unmodified_since(mut self, if_unmodified_since: OffsetDateTime) -> Self { + self.options.if_unmodified_since = Some(if_unmodified_since); + self + } + + pub fn with_lease_id(mut self, lease_id: String) -> Self { + self.options.lease_id = Some(lease_id); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_source_content_crc64(mut self, source_content_crc64: String) -> Self { + self.options.source_content_crc64 = Some(source_content_crc64); + self + } + + pub fn with_source_content_md5(mut self, source_content_md5: String) -> Self { + self.options.source_content_md5 = Some(source_content_md5); + self + } + + pub fn with_source_if_match(mut self, source_if_match: String) -> Self { + self.options.source_if_match = Some(source_if_match); + self + } + + pub fn with_source_if_modified_since( + mut self, + source_if_modified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_modified_since = Some(source_if_modified_since); + self + } + + pub fn with_source_if_none_match(mut self, source_if_none_match: String) -> Self { + self.options.source_if_none_match = Some(source_if_none_match); + self + } + + pub fn with_source_if_unmodified_since( + mut self, + source_if_unmodified_since: OffsetDateTime, + ) -> Self { + self.options.source_if_unmodified_since = Some(source_if_unmodified_since); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobPageBlobUploadPagesFromUrlOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_service.rs b/sdk/storage/blob_storage/src/generated/clients/blob_service.rs new file mode 100644 index 0000000000..35314284db --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/blob_service.rs @@ -0,0 +1,652 @@ +// 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 crate::models::{ + FilterBlobSegment, FilterBlobsIncludes, KeyInfo, ListContainersSegmentResponse, + StorageServiceProperties, StorageServiceStats, UserDelegationKey, +}; +use azure_core::builders::ClientMethodOptionsBuilder; +use azure_core::{ + AsClientMethodOptions, ClientMethodOptions, Context, Method, Pipeline, Request, RequestContent, + Response, Result, Url, +}; + +pub struct BlobService { + pub(in crate::generated::clients) endpoint: Url, + pub(in crate::generated::clients) pipeline: Pipeline, +} + +impl BlobService { + /// The Filter Blobs operation enables callers to list blobs across all containers whose tags match a given search expression. + pub async fn filter_blobs( + &self, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?comp=blobs"); + if let Some(include) = options.include { + url.query_pairs_mut().append_pair( + "include", + &include + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(","), + ); + } + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + if let Some(where_param) = options.where_param { + url.query_pairs_mut().append_pair("where", &where_param); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Returns the sku name and account kind. + pub async fn get_account_info( + &self, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?restype=account&comp=properties"); + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Retrieves properties of a storage account's Blob service, including properties for Storage Analytics and CORS (Cross-Origin + /// Resource Sharing) rules. + pub async fn get_properties( + &self, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?restype=service&comp=properties"); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Retrieves statistics related to replication for the Blob service. It is only available on the secondary location endpoint + /// when read-access geo-redundant replication is enabled for the storage account. + pub async fn get_statistics( + &self, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?restype=service&comp=stats"); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Get User Delegation Key operation gets the user delegation key for the Blob service. This is only a valid operation + /// when using User Delegation SAS. For more information, see Create + /// a user delegation SAS. + pub async fn get_user_delegation_key( + &self, + body: RequestContent, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?restype=service&comp=userdelegationkey"); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The List Containers Segment operation returns a list of the containers under the specified account + pub async fn list_containers_segment( + &self, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?comp=list"); + if let Some(marker) = options.marker { + url.query_pairs_mut().append_pair("marker", &marker); + } + if let Some(maxresults) = options.maxresults { + url.query_pairs_mut() + .append_pair("maxresults", &maxresults.to_string()); + } + if let Some(prefix) = options.prefix { + url.query_pairs_mut().append_pair("prefix", &prefix); + } + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Get); + request.insert_header("accept", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// Get the properties of a storage account's Blob service, including properties for Storage Analytics and CORS (Cross-Origin + /// Resource Sharing) rules. + pub async fn set_properties( + &self, + body: RequestContent, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?restype=service&comp=properties"); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Put); + request.insert_header("accept", "application/json"); + request.insert_header("content-type", "application/json"); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + request.set_body(body); + self.pipeline.send(&mut ctx, &mut request).await + } + + /// The Batch operation allows multiple API calls to be embedded into a single HTTP request. + pub async fn submit_batch( + &self, + content_length: i64, + version: impl Into, + options: Option>, + ) -> Result> { + let options = options.unwrap_or_default(); + let mut ctx = options.method_options.context(); + let mut url = self.endpoint.clone(); + url.set_path("/?comp=batch"); + if let Some(timeout) = options.timeout { + url.query_pairs_mut() + .append_pair("timeout", &timeout.to_string()); + } + let mut request = Request::new(url, Method::Post); + request.insert_header("accept", "application/json"); + request.insert_header("content-length", content_length.to_string()); + if let Some(request_id) = options.request_id { + request.insert_header("x-ms-client-request-id", request_id); + } + request.insert_header("x-ms-version", version.into()); + self.pipeline.send(&mut ctx, &mut request).await + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceFilterBlobsOptions<'a> { + include: Option>, + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, + where_param: Option, +} + +impl<'a> BlobServiceFilterBlobsOptions<'a> { + pub fn builder() -> builders::BlobServiceFilterBlobsOptionsBuilder<'a> { + builders::BlobServiceFilterBlobsOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceGetAccountInfoOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, +} + +impl<'a> BlobServiceGetAccountInfoOptions<'a> { + pub fn builder() -> builders::BlobServiceGetAccountInfoOptionsBuilder<'a> { + builders::BlobServiceGetAccountInfoOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceGetPropertiesOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceGetPropertiesOptions<'a> { + pub fn builder() -> builders::BlobServiceGetPropertiesOptionsBuilder<'a> { + builders::BlobServiceGetPropertiesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceGetStatisticsOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceGetStatisticsOptions<'a> { + pub fn builder() -> builders::BlobServiceGetStatisticsOptionsBuilder<'a> { + builders::BlobServiceGetStatisticsOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceGetUserDelegationKeyOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceGetUserDelegationKeyOptions<'a> { + pub fn builder() -> builders::BlobServiceGetUserDelegationKeyOptionsBuilder<'a> { + builders::BlobServiceGetUserDelegationKeyOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceListContainersSegmentOptions<'a> { + marker: Option, + maxresults: Option, + method_options: ClientMethodOptions<'a>, + prefix: Option, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceListContainersSegmentOptions<'a> { + pub fn builder() -> builders::BlobServiceListContainersSegmentOptionsBuilder<'a> { + builders::BlobServiceListContainersSegmentOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceSetPropertiesOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceSetPropertiesOptions<'a> { + pub fn builder() -> builders::BlobServiceSetPropertiesOptionsBuilder<'a> { + builders::BlobServiceSetPropertiesOptionsBuilder::new() + } +} + +#[derive(Clone, Debug, Default)] +pub struct BlobServiceSubmitBatchOptions<'a> { + method_options: ClientMethodOptions<'a>, + request_id: Option, + timeout: Option, +} + +impl<'a> BlobServiceSubmitBatchOptions<'a> { + pub fn builder() -> builders::BlobServiceSubmitBatchOptionsBuilder<'a> { + builders::BlobServiceSubmitBatchOptionsBuilder::new() + } +} + +pub mod builders { + use super::*; + + pub struct BlobServiceFilterBlobsOptionsBuilder<'a> { + options: BlobServiceFilterBlobsOptions<'a>, + } + + impl BlobServiceFilterBlobsOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceFilterBlobsOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceFilterBlobsOptions { + self.options.clone() + } + + pub fn with_include(mut self, include: Vec) -> Self { + self.options.include = Some(include); + self + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + + pub fn with_where_param(mut self, where_param: String) -> Self { + self.options.where_param = Some(where_param); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceFilterBlobsOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceGetAccountInfoOptionsBuilder<'a> { + options: BlobServiceGetAccountInfoOptions<'a>, + } + + impl BlobServiceGetAccountInfoOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceGetAccountInfoOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceGetAccountInfoOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceGetAccountInfoOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceGetPropertiesOptionsBuilder<'a> { + options: BlobServiceGetPropertiesOptions<'a>, + } + + impl BlobServiceGetPropertiesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceGetPropertiesOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceGetPropertiesOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceGetPropertiesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceGetStatisticsOptionsBuilder<'a> { + options: BlobServiceGetStatisticsOptions<'a>, + } + + impl BlobServiceGetStatisticsOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceGetStatisticsOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceGetStatisticsOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceGetStatisticsOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceGetUserDelegationKeyOptionsBuilder<'a> { + options: BlobServiceGetUserDelegationKeyOptions<'a>, + } + + impl BlobServiceGetUserDelegationKeyOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceGetUserDelegationKeyOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceGetUserDelegationKeyOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceGetUserDelegationKeyOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceListContainersSegmentOptionsBuilder<'a> { + options: BlobServiceListContainersSegmentOptions<'a>, + } + + impl BlobServiceListContainersSegmentOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceListContainersSegmentOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceListContainersSegmentOptions { + self.options.clone() + } + + pub fn with_marker(mut self, marker: String) -> Self { + self.options.marker = Some(marker); + self + } + + pub fn with_maxresults(mut self, maxresults: i32) -> Self { + self.options.maxresults = Some(maxresults); + self + } + + pub fn with_prefix(mut self, prefix: String) -> Self { + self.options.prefix = Some(prefix); + self + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceListContainersSegmentOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceSetPropertiesOptionsBuilder<'a> { + options: BlobServiceSetPropertiesOptions<'a>, + } + + impl BlobServiceSetPropertiesOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceSetPropertiesOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceSetPropertiesOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceSetPropertiesOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } + + pub struct BlobServiceSubmitBatchOptionsBuilder<'a> { + options: BlobServiceSubmitBatchOptions<'a>, + } + + impl BlobServiceSubmitBatchOptionsBuilder<'_> { + pub(super) fn new() -> Self { + Self { + options: BlobServiceSubmitBatchOptions::default(), + } + } + + pub fn build(&self) -> BlobServiceSubmitBatchOptions { + self.options.clone() + } + + pub fn with_request_id(mut self, request_id: String) -> Self { + self.options.request_id = Some(request_id); + self + } + + pub fn with_timeout(mut self, timeout: i32) -> Self { + self.options.timeout = Some(timeout); + self + } + } + + impl<'a> ClientMethodOptionsBuilder<'a> for BlobServiceSubmitBatchOptionsBuilder<'a> { + fn with_context(mut self, context: &'a Context) -> Self { + self.options.method_options.set_context(context); + self + } + } +} diff --git a/sdk/storage/blob_storage/src/generated/clients/mod.rs b/sdk/storage/blob_storage/src/generated/clients/mod.rs new file mode 100644 index 0000000000..5ff361bffb --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/clients/mod.rs @@ -0,0 +1,12 @@ +// 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. + +pub mod blob_append_blob; +pub mod blob_blob; +pub mod blob_block_blob; +pub mod blob_client; +pub mod blob_container; +pub mod blob_page_blob; +pub mod blob_service; diff --git a/sdk/storage/blob_storage/src/generated/enums.rs b/sdk/storage/blob_storage/src/generated/enums.rs new file mode 100644 index 0000000000..009902874d --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/enums.rs @@ -0,0 +1,165 @@ +// 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 typespec_client_core::{create_enum, create_extensible_enum}; + +create_extensible_enum!( + AccessTier, + (Archive, "Archive"), + (Cool, "Cool"), + (Hot, "Hot"), + (P10, "P10"), + (P15, "P15"), + (P20, "P20"), + (P30, "P30"), + (P4, "P4"), + (P40, "P40"), + (P50, "P50"), + (P6, "P6"), + (P60, "P60"), + (P70, "P70"), + (P80, "P80") +); + +create_extensible_enum!( + AccountKind, + (BlobStorage, "BlobStorage"), + (BlockBlobStorage, "BlockBlobStorage"), + (FileStorage, "FileStorage"), + (Storage, "Storage"), + (StorageV2, "StorageV2") +); + +create_extensible_enum!( + ArchiveStatus, + (RehydratePendingToArchive, "rehydrate-pending-to-archive"), + (RehydratePendingToCool, "rehydrate-pending-to-cool"), + (RehydratePendingToExpired, "rehydrate-pending-to-expired"), + (RehydratePendingToHot, "rehydrate-pending-to-hot") +); + +create_extensible_enum!( + BlobExpiryOptions, + (Absolute, "Absolute"), + (NeverExpire, "NeverExpire"), + (RelativeToCreation, "RelativeToCreation"), + (RelativeToNow, "RelativeToNow") +); + +create_extensible_enum!( + BlobImmutabilityPolicyMode, + (Locked, "Locked"), + (Mutable, "Mutable"), + (Unlocked, "Unlocked") +); + +create_extensible_enum!( + BlobType, + (AppendBlob, "AppendBlob"), + (BlockBlob, "BlockBlob"), + (PageBlob, "PageBlob") +); + +create_extensible_enum!( + BlockListType, + (All, "all"), + (Committed, "committed"), + (Uncomitted, "uncommitted") +); + +create_extensible_enum!( + CopyStatus, + (Aborted, "aborted"), + (Failed, "failed"), + (Pending, "pending"), + (Success, "success") +); + +create_extensible_enum!( + DeleteSnapshotsOptionType, + (Include, "include"), + (Nonne, "none") +); + +create_extensible_enum!(FilterBlobsIncludes, (None, "none"), (Versions, "versions")); + +create_extensible_enum!( + GeoReplicationStatus, + (Bootstrap, "bootstrap"), + (Live, "live"), + (Unavailable, "unavailable") +); + +create_extensible_enum!(LeaseDuration, (Fixed, "fixed"), (Infinite, "infinite")); + +create_extensible_enum!( + LeaseState, + (Available, "available"), + (Breaking, "breaking"), + (Broken, "broken"), + (Expired, "expired"), + (Leased, "leased") +); + +create_extensible_enum!(LeaseStatus, (Locked, "locked"), (Unlocked, "unlocked")); + +create_extensible_enum!( + ListBlobsIncludes, + (Copies, "copies"), + (Deleted, "deleted"), + (DeletedWithVersions, "deletedwithversions"), + (ImmutabilityPolicy, "immutabilitypolicy"), + (LegalHold, "legalhold"), + (Metadata, "metadata"), + (Snapshots, "snapshots"), + (Tags, "tags"), + (UncommittedBlobs, "uncommittedblobs"), + (Versions, "versions") +); + +create_extensible_enum!( + PremiumPageBlobAccessTier, + (P10, "P10"), + (P15, "P15"), + (P20, "P20"), + (P30, "P30"), + (P4, "P4"), + (P40, "P40"), + (P50, "P50"), + (P6, "P6"), + (P60, "P60"), + (P70, "P70"), + (P80, "P80") +); + +create_extensible_enum!(PublicAccessType, (Blob, "blob"), (Container, "container")); + +create_extensible_enum!(QueryRequestTypeSqlOnly, (SQL, "SQL")); + +create_extensible_enum!( + QueryType, + (Arrow, "arrow"), + (Delimited, "delimited"), + (JSON, "json"), + (Parquet, "parquet") +); + +create_extensible_enum!(RehydratePriority, (High, "High"), (Standard, "Standard")); + +create_extensible_enum!( + SequenceNumberActionType, + (Increment, "increment"), + (Max, "max"), + (Update, "update") +); + +create_extensible_enum!( + SkuName, + (PremiumLRS, "Premium_LRS"), + (StandardGRS, "tandard_GRS"), + (StandardLRS, "Standard_LRS"), + (StandardRAGRS, "Standard_RAGRS"), + (StandardZRS, "Standard_ZRS") +); diff --git a/sdk/storage/blob_storage/src/generated/mod.rs b/sdk/storage/blob_storage/src/generated/mod.rs new file mode 100644 index 0000000000..f839ba0be0 --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/mod.rs @@ -0,0 +1,8 @@ +// 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. + +pub mod clients; +pub mod enums; +pub mod models; diff --git a/sdk/storage/blob_storage/src/generated/models.rs b/sdk/storage/blob_storage/src/generated/models.rs new file mode 100644 index 0000000000..4f7dee537a --- /dev/null +++ b/sdk/storage/blob_storage/src/generated/models.rs @@ -0,0 +1,1256 @@ +// 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 crate::models::{ + AccessTier, ArchiveStatus, BlobImmutabilityPolicyMode, BlobType, CopyStatus, + GeoReplicationStatus, LeaseDuration, LeaseState, LeaseStatus, PublicAccessType, + QueryRequestTypeSqlOnly, QueryType, RehydratePriority, +}; +use async_std::task::block_on; +use azure_core::{RequestContent, Response}; +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; +use typespec_derive::Model; + +/// Represents an access policy. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct AccessPolicy { + /// The date-time the policy expires. + #[serde(skip_serializing_if = "Option::is_none")] + pub expiry: Option, + + /// The permissions for acl the policy. + #[serde(skip_serializing_if = "Option::is_none")] + pub permission: Option, + + /// The date-time the policy is active. + #[serde(skip_serializing_if = "Option::is_none")] + pub start: Option, +} + +/// Represents the Apache Arrow configuration. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ArrowConfiguration { + /// The Apache Arrow schema + #[serde(skip_serializing_if = "Option::is_none")] + pub schema: Option>, +} + +/// Represents an Apache Arrow field. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ArrowField { + /// The arrow field name. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + + /// The arrow field precision. + #[serde(skip_serializing_if = "Option::is_none")] + pub precision: Option, + + /// The arrow field scale. + #[serde(skip_serializing_if = "Option::is_none")] + pub scale: Option, + + /// The arrow field type. + #[serde(rename = "type")] + #[serde(skip_serializing_if = "Option::is_none")] + pub type_prop: Option, +} + +/// The blob flat list segment. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobFlatListSegment { + /// The blob items. + #[serde(rename = "blobItems")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_items: Option>, +} + +/// Represents an array of blobs. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobHierarchyListSegment { + /// The blob items + #[serde(rename = "blobItems")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_items: Option>, + + /// The blob prefixes. + #[serde(rename = "blobPrefixes")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_prefixes: Option>, +} + +/// An Azure Storage Blob +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobItemInternal { + /// The tags of the blob. + #[serde(rename = "blobTags")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_tags: Option>, + + /// Whether the blob is deleted. + #[serde(skip_serializing_if = "Option::is_none")] + pub deleted: Option, + + /// Whether the blog has versions only. + #[serde(rename = "hasVersionsOnly")] + #[serde(skip_serializing_if = "Option::is_none")] + pub has_versions_only: Option, + + /// Whether the blob is the current version. + #[serde(rename = "isCurrentVersion")] + #[serde(skip_serializing_if = "Option::is_none")] + pub is_current_version: Option, + + /// The metadata of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata: Option, + + /// The name of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + + /// The object replication metadata of the blob. + #[serde(rename = "objectReplicationMetadata")] + #[serde(skip_serializing_if = "Option::is_none")] + pub object_replication_metadata: Option, + + /// The properties of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub properties: Option, + + /// The snapshot of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub snapshot: Option, + + /// The version id of the blob. + #[serde(rename = "versionId")] + #[serde(skip_serializing_if = "Option::is_none")] + pub version_id: Option, +} + +/// The blob metadata. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobMetadata { + /// Whether the blob metadata is encrypted. + #[serde(skip_serializing_if = "Option::is_none")] + pub encrypted: Option, +} + +/// Represents a blob name. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobName { + /// The blob name. + #[serde(skip_serializing_if = "Option::is_none")] + pub content: Option, + + /// Whether the blob name is encoded. + #[serde(skip_serializing_if = "Option::is_none")] + pub encoded: Option, +} + +/// Represents a blob prefix. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobPrefix { + /// The blob name. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, +} + +/// The properties of a blob. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobPropertiesInternal { + /// The access tier of the blob. + #[serde(rename = "accessTier")] + #[serde(skip_serializing_if = "Option::is_none")] + pub access_tier: Option, + + /// The access tier change time of the blob. + #[serde(rename = "accessTierChangeTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub access_tier_change_time: Option, + + /// Whether the access tier is inferred. + #[serde(rename = "accessTierInferred")] + #[serde(skip_serializing_if = "Option::is_none")] + pub access_tier_inferred: Option, + + /// The archive status of the blob. + #[serde(rename = "archiveStatus")] + #[serde(skip_serializing_if = "Option::is_none")] + pub archive_status: Option, + + /// The sequence number of the blob. + #[serde(rename = "blobSequenceNumber")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_sequence_number: Option, + + /// The blob type. + #[serde(rename = "blobType")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_type: Option, + + /// The cache control of the blob. + #[serde(rename = "cacheControl")] + #[serde(skip_serializing_if = "Option::is_none")] + pub cache_control: Option, + + /// The content disposition of the blob. + #[serde(rename = "contentDisposition")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_disposition: Option, + + /// The content encoding of the blob. + #[serde(rename = "contentEncoding")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_encoding: Option, + + /// The content language of the blob. + #[serde(rename = "contentLanguage")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_language: Option, + + /// The content length of the blob. + #[serde(rename = "contentLength")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_length: Option, + + /// The content MD5 of the blob. + #[serde(rename = "contentMd5")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_md5: Option, + + /// The content type of the blob. + #[serde(rename = "contentType")] + #[serde(skip_serializing_if = "Option::is_none")] + pub content_type: Option, + + /// The copy completion time of the blob. + #[serde(rename = "copyCompletionTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_completion_time: Option, + + /// The copy ID of the blob. + #[serde(rename = "copyId")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_id: Option, + + /// The copy progress of the blob. + #[serde(rename = "copyProgress")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_progress: Option, + + /// The copy source of the blob. + #[serde(rename = "copySource")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_source: Option, + + /// The copy status of the blob. + #[serde(rename = "copyStatus")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_status: Option, + + /// The copy status description of the blob. + #[serde(rename = "copyStatusDescription")] + #[serde(skip_serializing_if = "Option::is_none")] + pub copy_status_description: Option, + + /// The date-time the blob was created in RFC1123 format. + #[serde(rename = "creationTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub creation_time: Option, + + /// The time the blob was deleted. + #[serde(rename = "deletedTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub deleted_time: Option, + + /// The name of the desination snapshot. + #[serde(rename = "destinationSnapshot")] + #[serde(skip_serializing_if = "Option::is_none")] + pub destination_snapshot: Option, + + /// The blog ETag. + #[serde(rename = "eTag")] + #[serde(skip_serializing_if = "Option::is_none")] + pub e_tag: Option, + + /// The encryption scope of the blob. + #[serde(rename = "encryptionScope")] + #[serde(skip_serializing_if = "Option::is_none")] + pub encryption_scope: Option, + + /// The expire time of the blob. + #[serde(rename = "expiryTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub expiry_time: Option, + + /// The immutability policy mode of the blob. + #[serde(rename = "immutabilityPolicyMode")] + #[serde(skip_serializing_if = "Option::is_none")] + pub immutability_policy_mode: Option, + + /// The immutability policy until time of the blob. + #[serde(rename = "immutabilityPolicyUntilDate")] + #[serde(skip_serializing_if = "Option::is_none")] + pub immutability_policy_until_date: Option, + + /// Whether the blog is incremental copy. + #[serde(rename = "incrementalCopy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub incremental_copy: Option, + + /// The last access time of the blob. + #[serde(rename = "lastAccessTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub last_access_time: Option, + + /// The date-time the blob was last modified in RFC1123 format. + #[serde(rename = "lastModified")] + #[serde(skip_serializing_if = "Option::is_none")] + pub last_modified: Option, + + /// The lease duration of the blob. + #[serde(rename = "leaseDuration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_duration: Option, + + /// The lease state of the blob. + #[serde(rename = "leaseState")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_state: Option, + + /// The lease status of the blob. + #[serde(rename = "leaseStatus")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_status: Option, + + /// Whether the blob is under legal hold. + #[serde(rename = "legalHold")] + #[serde(skip_serializing_if = "Option::is_none")] + pub legal_hold: Option, + + /// The rehydrate priority of the blob. + #[serde(rename = "rehydratePriority")] + #[serde(skip_serializing_if = "Option::is_none")] + pub rehydrate_priority: Option, + + /// The remaining retention days of the blob. + #[serde(rename = "remainingRetentionDays")] + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining_retention_days: Option, + + /// Whether the blob is sealed. + #[serde(skip_serializing_if = "Option::is_none")] + pub sealed: Option, + + /// Whether the blog is encrypted on the server. + #[serde(rename = "serverEncrypted")] + #[serde(skip_serializing_if = "Option::is_none")] + pub server_encrypted: Option, + + /// The number of tags for the blob. + #[serde(rename = "tagCount")] + #[serde(skip_serializing_if = "Option::is_none")] + pub tag_count: Option, +} + +/// The blob tags. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobTag { + /// The key of the tag. + #[serde(skip_serializing_if = "Option::is_none")] + pub key: Option, + + /// The value of the tag. + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, +} + +/// Represents blob tags. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlobTags { + /// Represents the blob tags. + #[serde(rename = "blobTagSet")] + #[serde(skip_serializing_if = "Option::is_none")] + pub blob_tag_set: Option>, +} + +/// The Block lookup list. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct BlockLookupList { + /// The committed blocks + #[serde(skip_serializing_if = "Option::is_none")] + pub committed: Option>, + + /// The latest blocks + #[serde(skip_serializing_if = "Option::is_none")] + pub latest: Option>, + + /// The uncommitted blocks + #[serde(skip_serializing_if = "Option::is_none")] + pub uncommitted: Option>, +} + +/// The clear range. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ClearRange { + /// The end of the byte range. + #[serde(skip_serializing_if = "Option::is_none")] + pub end: Option, + + /// The start of the byte range. + #[serde(skip_serializing_if = "Option::is_none")] + pub start: Option, +} + +/// An Azure Storage container. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ContainerItem { + /// Whether the container is deleted. + #[serde(skip_serializing_if = "Option::is_none")] + pub delete: Option, + + /// The metadata of the container. + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata: Option, + + /// The name of the container. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + + /// The properties of the container. + #[serde(skip_serializing_if = "Option::is_none")] + pub properties: Option, + + /// The version of the container. + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} + +/// The metadata of a container. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ContainerMetadata { + /// Whether the metadata is encrypted. + #[serde(skip_serializing_if = "Option::is_none")] + pub encrypted: Option, +} + +/// The properties of a container. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ContainerProperties { + /// The date-time the container was created in RFC1123 format. + #[serde(rename = "creationTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub creation_time: Option, + + /// The default encryption scope of the container. + #[serde(rename = "defaultEncryptionScope")] + #[serde(skip_serializing_if = "Option::is_none")] + pub default_encryption_scope: Option, + + /// The deleted time of the container. + #[serde(rename = "deletedTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub deleted_time: Option, + + /// Whether to prevent encryption scope override. + #[serde(rename = "denyEncryptionScopeOverride")] + #[serde(skip_serializing_if = "Option::is_none")] + pub deny_encryption_scope_override: Option, + + /// The ETag of the container. + #[serde(rename = "eTag")] + #[serde(skip_serializing_if = "Option::is_none")] + pub e_tag: Option, + + /// Whether it has an immutability policy. + #[serde(rename = "hasImmutabilityPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub has_immutability_policy: Option, + + /// The has legal hold status of the container. + #[serde(rename = "hasLegalHold")] + #[serde(skip_serializing_if = "Option::is_none")] + pub has_legal_hold: Option, + + /// Whether immutable storage with versioning is enabled. + #[serde(rename = "immutableStorageWithVersioningEnabled")] + #[serde(skip_serializing_if = "Option::is_none")] + pub immutable_storage_with_versioning_enabled: Option, + + /// The date-time the container was last modified in RFC1123 format. + #[serde(rename = "lastModified")] + #[serde(skip_serializing_if = "Option::is_none")] + pub last_modified: Option, + + /// The lease duration of the container. + #[serde(rename = "leaseDuration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_duration: Option, + + /// The lease state of the container. + #[serde(rename = "leaseState")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_state: Option, + + /// The lease status of the container. + #[serde(rename = "leaseStatus")] + #[serde(skip_serializing_if = "Option::is_none")] + pub lease_status: Option, + + /// The public access type of the container. + #[serde(rename = "publicAccess")] + #[serde(skip_serializing_if = "Option::is_none")] + pub public_access: Option, + + /// The remaining retention days of the container. + #[serde(rename = "remainingRetentionDays")] + #[serde(skip_serializing_if = "Option::is_none")] + pub remaining_retention_days: Option, +} + +/// The CORS rule. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct CorsRule { + /// The allowed headers. + #[serde(rename = "allowedHeaders")] + #[serde(skip_serializing_if = "Option::is_none")] + pub allowed_headers: Option, + + /// The allowed methods. + #[serde(rename = "allowedMethods")] + #[serde(skip_serializing_if = "Option::is_none")] + pub allowed_methods: Option, + + /// The allowed origins. + #[serde(rename = "allowedOrigins")] + #[serde(skip_serializing_if = "Option::is_none")] + pub allowed_origins: Option, + + /// The exposed headers. + #[serde(rename = "exposedHeaders")] + #[serde(skip_serializing_if = "Option::is_none")] + pub exposed_headers: Option, + + /// The maximum age in seconds. + #[serde(rename = "maxAgeInSeconds")] + #[serde(skip_serializing_if = "Option::is_none")] + pub max_age_in_seconds: Option, +} + +/// Represents the delimited text configuration. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct DelimitedTextConfiguration { + /// The string used to separate columns. + #[serde(rename = "columnSeparator")] + #[serde(skip_serializing_if = "Option::is_none")] + pub column_separator: Option, + + /// The string used to escape a quote character in a field. + #[serde(rename = "escapeChar")] + #[serde(skip_serializing_if = "Option::is_none")] + pub escape_char: Option, + + /// The string used to quote a specific field. + #[serde(rename = "fieldQuote")] + #[serde(skip_serializing_if = "Option::is_none")] + pub field_quote: Option, + + /// Represents whether the data has headers. + #[serde(rename = "headersPresent")] + #[serde(skip_serializing_if = "Option::is_none")] + pub headers_present: Option, + + /// The string used to separate records. + #[serde(rename = "recordSeparator")] + #[serde(skip_serializing_if = "Option::is_none")] + pub record_separator: Option, +} + +/// The filter blob item. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct FilterBlobItem { + /// The properties of the blob. + #[serde(rename = "containerName")] + #[serde(skip_serializing_if = "Option::is_none")] + pub container_name: Option, + + /// Whether it is the current version of the blob + #[serde(rename = "isCurrentVersion")] + #[serde(skip_serializing_if = "Option::is_none")] + pub is_current_version: Option, + + /// The name of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + + /// The metadata of the blob. + #[serde(skip_serializing_if = "Option::is_none")] + pub tags: Option, + + /// The version ID of the blob. + #[serde(rename = "versionId")] + #[serde(skip_serializing_if = "Option::is_none")] + pub version_id: Option, +} + +/// The result of a Filter Blobs API call +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct FilterBlobSegment { + /// The blob segment. + #[serde(skip_serializing_if = "Option::is_none")] + pub blobs: Option>, + + /// The next marker of the blobs. + #[serde(rename = "nextMarker")] + #[serde(skip_serializing_if = "Option::is_none")] + pub next_marker: Option, + + /// The service endpoint. + #[serde(rename = "serviceEndpoint")] + #[serde(skip_serializing_if = "Option::is_none")] + pub service_endpoint: Option, + + /// The filter for the blobs. + #[serde(rename = "where")] + #[serde(skip_serializing_if = "Option::is_none")] + pub where_prop: Option, +} + +/// The geo replication status. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct GeoReplication { + /// The last sync time. + #[serde(rename = "lastSyncTime")] + #[serde(skip_serializing_if = "Option::is_none")] + pub last_sync_time: Option, + + /// The georeplication status. + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, +} + +/// Represents the JSON text configuration. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct JsonTextConfiguration { + /// The string used to separate records. + #[serde(rename = "recordSeparator")] + #[serde(skip_serializing_if = "Option::is_none")] + pub record_separator: Option, +} + +/// Key information +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct KeyInfo { + /// The date-time the key expires. + #[serde(skip_serializing_if = "Option::is_none")] + pub expiry: Option, + + /// The date-time the key is active. + #[serde(skip_serializing_if = "Option::is_none")] + pub start: Option, +} + +/// An enumeration of blobs. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ListBlobsFlatSegmentResponse { + /// The container name. + #[serde(rename = "containerName")] + #[serde(skip_serializing_if = "Option::is_none")] + pub container_name: Option, + + /// The marker of the blobs. + #[serde(skip_serializing_if = "Option::is_none")] + pub marker: Option, + + /// The max results of the blobs. + #[serde(rename = "maxResults")] + #[serde(skip_serializing_if = "Option::is_none")] + pub max_results: Option, + + /// The next marker of the blobs. + #[serde(rename = "nextMarker")] + #[serde(skip_serializing_if = "Option::is_none")] + pub next_marker: Option, + + /// The prefix of the blobs. + #[serde(skip_serializing_if = "Option::is_none")] + pub rrefix: Option, + + /// The blob segment. + #[serde(skip_serializing_if = "Option::is_none")] + pub segment: Option, + + /// The service endpoint. + #[serde(rename = "serviceEndpoint")] + #[serde(skip_serializing_if = "Option::is_none")] + pub service_endpoint: Option, +} + +/// An enumeration of blobs +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ListBlobsHierarchySegmentResponse { + /// The container name. + #[serde(rename = "containerName")] + #[serde(skip_serializing_if = "Option::is_none")] + pub container_name: Option, + + /// The delimiter of the blobs. + #[serde(skip_serializing_if = "Option::is_none")] + pub delimiter: Option, + + /// The marker of the blobs. + #[serde(skip_serializing_if = "Option::is_none")] + pub marker: Option, + + /// The max results of the blobs. + #[serde(rename = "maxResults")] + #[serde(skip_serializing_if = "Option::is_none")] + pub max_results: Option, + + /// The next marker of the blobs. + #[serde(rename = "nextMarker")] + #[serde(skip_serializing_if = "Option::is_none")] + pub next_marker: Option, + + /// The prefix of the blobs. + #[serde(skip_serializing_if = "Option::is_none")] + pub prefix: Option, + + /// The blob segment. + #[serde(skip_serializing_if = "Option::is_none")] + pub segment: Option, + + /// The service endpoint. + #[serde(rename = "serviceEndpoint")] + #[serde(skip_serializing_if = "Option::is_none")] + pub service_endpoint: Option, +} + +/// The list container segement response +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ListContainersSegmentResponse { + /// The container segment. + #[serde(rename = "containerItems")] + #[serde(skip_serializing_if = "Option::is_none")] + pub container_items: Option>, + + /// The marker of the containers. + #[serde(skip_serializing_if = "Option::is_none")] + pub marker: Option, + + /// The max results of the containers. + #[serde(rename = "maxxResults")] + #[serde(skip_serializing_if = "Option::is_none")] + pub maxx_results: Option, + + /// The next marker of the containers. + #[serde(rename = "nextMarker")] + #[serde(skip_serializing_if = "Option::is_none")] + pub next_marker: Option, + + /// The prefix of the containers. + #[serde(skip_serializing_if = "Option::is_none")] + pub prefix: Option, + + /// The service endpoint. + #[serde(rename = "serviceEndpoint")] + #[serde(skip_serializing_if = "Option::is_none")] + pub service_endpoint: Option, +} + +/// The logging properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct Logging { + /// Whether delete operation is logged. + #[serde(skip_serializing_if = "Option::is_none")] + pub delete: Option, + + /// Whether read operation is logged. + #[serde(skip_serializing_if = "Option::is_none")] + pub read: Option, + + /// The retention policy of the logs. + #[serde(rename = "retentionPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub retention_policy: Option, + + /// The version of the logging properties. + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, + + /// Whether write operation is logged. + #[serde(skip_serializing_if = "Option::is_none")] + pub write: Option, +} + +/// The metrics properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct Metrics { + /// Whether it is enabled. + #[serde(skip_serializing_if = "Option::is_none")] + pub enabled: Option, + + /// Whether to include API in the metrics. + #[serde(rename = "includeApis")] + #[serde(skip_serializing_if = "Option::is_none")] + pub include_apis: Option, + + /// The retention policy of the metrics. + #[serde(rename = "retentionPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub retention_policy: Option, + + /// The service properties of the metrics. + #[serde(rename = "serviceProperties")] + #[serde(skip_serializing_if = "Option::is_none")] + pub service_properties: Option, + + /// The version of the metrics properties. + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} + +/// The metrics properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct MetricsProperties { + /// Whether to include API in the metrics. + #[serde(skip_serializing_if = "Option::is_none")] + pub enabled: Option, + + /// The retention policy of the metrics. + #[serde(rename = "retentionPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub retention_policy: Option, + + /// The version of the metrics properties. + #[serde(skip_serializing_if = "Option::is_none")] + pub version: Option, +} + +/// The metrics service properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct MetricsServiceProperties { + /// The hour metrics properties. + #[serde(rename = "hourMetrics")] + #[serde(skip_serializing_if = "Option::is_none")] + pub hour_metrics: Option, + + /// The minute metrics properties. + #[serde(rename = "minuteMetrics")] + #[serde(skip_serializing_if = "Option::is_none")] + pub minute_metrics: Option, +} + +/// The object replication metadata. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ObjectReplicationMetadata {} + +/// Represents a page list. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct PageList { + /// The clear ranges. + #[serde(rename = "clearRange")] + #[serde(skip_serializing_if = "Option::is_none")] + pub clear_range: Option>, + + /// The next marker. + #[serde(rename = "nextMarker")] + #[serde(skip_serializing_if = "Option::is_none")] + pub next_marker: Option, + + /// The page ranges. + #[serde(rename = "pageRange")] + #[serde(skip_serializing_if = "Option::is_none")] + pub page_range: Option>, +} + +/// The page range. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct PageRange { + /// The end of the byte range. + #[serde(skip_serializing_if = "Option::is_none")] + pub end: Option, + + /// The start of the byte range. + #[serde(skip_serializing_if = "Option::is_none")] + pub start: Option, +} + +/// Represents the Parquet configuration. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct ParquetConfiguration {} + +/// The query format settings. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct QueryFormat { + /// The Apache Arrow configuration. + #[serde(rename = "arrowConfiguration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub arrow_configuration: Option, + + /// The delimited text configuration. + #[serde(rename = "delimitedTextConfiguration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub delimited_text_configuration: Option, + + /// The JSON text configuration. + #[serde(rename = "jsonTextConfiguration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub json_text_configuration: Option, + + /// The Parquet configuration. + #[serde(rename = "parquetConfiguration")] + #[serde(skip_serializing_if = "Option::is_none")] + pub parquet_configuration: Option, + + /// The query type. + #[serde(rename = "type")] + #[serde(skip_serializing_if = "Option::is_none")] + pub type_prop: Option, +} + +/// Groups the set of query request settings. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct QueryRequest { + /// The query expression in SQL. The maximum size of the query expression is 256KiB. + #[serde(skip_serializing_if = "Option::is_none")] + pub expression: Option, + + /// The input serialization settings. + #[serde(rename = "inputSerialization")] + #[serde(skip_serializing_if = "Option::is_none")] + pub input_serialization: Option, + + /// The output serialization settings. + #[serde(rename = "outputSerialization")] + #[serde(skip_serializing_if = "Option::is_none")] + pub output_serialization: Option, + + /// Required. The type of the provided query expression. + #[serde(rename = "queryType")] + #[serde(skip_serializing_if = "Option::is_none")] + pub query_type: Option, +} + +/// The query serialization settings. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct QuerySerialization { + /// The query format. + #[serde(skip_serializing_if = "Option::is_none")] + pub format: Option, +} + +/// The retention policy. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct RetentionPolicy { + /// Whether to allow permanent delete. + #[serde(rename = "allowPermanentDelete")] + #[serde(skip_serializing_if = "Option::is_none")] + pub allow_permanent_delete: Option, + + /// The number of days to retain the logs. + #[serde(skip_serializing_if = "Option::is_none")] + pub days: Option, + + /// Whether to enable the retention policy. + #[serde(skip_serializing_if = "Option::is_none")] + pub enabled: Option, +} + +/// The signed identifier. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct SignedIdentifier { + /// The access policy for the signed identifier. + #[serde(rename = "accessPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub access_policy: Option, + + /// The unique ID for the signed identifier. + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, +} + +/// The static website properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct StaticWebsite { + /// The error document. + #[serde(rename = "errorDocument")] + #[serde(skip_serializing_if = "Option::is_none")] + pub error_document: Option, + + /// The index document. + #[serde(rename = "indexDocument")] + #[serde(skip_serializing_if = "Option::is_none")] + pub index_document: Option, +} + +/// The error response. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct StorageError { + /// The error message. + #[serde(rename = "Message")] + #[serde(skip_serializing_if = "Option::is_none")] + pub message: Option, +} + +/// The service properties. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct StorageServiceProperties { + /// The CORS properties. + #[serde(skip_serializing_if = "Option::is_none")] + pub cors: Option>, + + /// The default service version. + #[serde(rename = "defaultServiceVersion")] + #[serde(skip_serializing_if = "Option::is_none")] + pub default_service_version: Option, + + /// The delete retention policy. + #[serde(rename = "deleteRetentionPolicy")] + #[serde(skip_serializing_if = "Option::is_none")] + pub delete_retention_policy: Option, + + /// The hour metrics properties. + #[serde(rename = "hourMetrics")] + #[serde(skip_serializing_if = "Option::is_none")] + pub hour_metrics: Option, + + /// The logging properties. + #[serde(skip_serializing_if = "Option::is_none")] + pub logging: Option, + + /// The minute metrics properties. + #[serde(rename = "minuteMetrics")] + #[serde(skip_serializing_if = "Option::is_none")] + pub minute_metrics: Option, + + /// The static website properties. + #[serde(rename = "staticWebsite")] + #[serde(skip_serializing_if = "Option::is_none")] + pub static_website: Option, +} + +/// Stats for the storage service. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct StorageServiceStats { + /// The geo replication stats. + #[serde(rename = "geoReplication")] + #[serde(skip_serializing_if = "Option::is_none")] + pub geo_replication: Option, +} + +/// A user delegation key. +#[derive(Clone, Debug, Default, Deserialize, Model, Serialize)] +#[non_exhaustive] +pub struct UserDelegationKey { + /// The date-time the key expires. + #[serde(rename = "signedExpiry")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_expiry: Option, + + /// The Azure Active Directory object ID in GUID format. + #[serde(rename = "signedOid")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_oid: Option, + + /// Abbreviation of the Azure Storage service that accepts the key. + #[serde(rename = "signedService")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_service: Option, + + /// The date-time the key is active. + #[serde(rename = "signedStart")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_start: Option, + + /// The Azure Active Directory tenant ID in GUID format. + #[serde(rename = "signedTid")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_tid: Option, + + /// The service version that created the key. + #[serde(rename = "signedVersion")] + #[serde(skip_serializing_if = "Option::is_none")] + pub signed_version: Option, + + /// The key as a base64 string. + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: BlobTags) -> Result { + Ok(RequestContent::from(serde_json::to_vec(&value)?)) + } +} + +impl TryFrom> for BlobTags { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: BlockLookupList) -> Result { + Ok(RequestContent::from(serde_json::to_vec(&value)?)) + } +} + +impl TryFrom> for BlockLookupList { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for FilterBlobSegment { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: KeyInfo) -> Result { + Ok(RequestContent::from(serde_json::to_vec(&value)?)) + } +} + +impl TryFrom> for ListBlobsFlatSegmentResponse { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for ListBlobsHierarchySegmentResponse { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || { + value + .into_body() + .json::() + }; + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for ListContainersSegmentResponse { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for PageList { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: QueryRequest) -> Result { + Ok(RequestContent::from(serde_json::to_vec(&value)?)) + } +} + +impl TryFrom for RequestContent { + type Error = azure_core::Error; + fn try_from(value: StorageServiceProperties) -> Result { + Ok(RequestContent::from(serde_json::to_vec(&value)?)) + } +} + +impl TryFrom> for StorageServiceProperties { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for StorageServiceStats { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} + +impl TryFrom> for UserDelegationKey { + type Error = azure_core::Error; + fn try_from(value: Response) -> Result { + let f = || value.into_body().json::(); + let r = block_on(f())?; + Ok(r) + } +} diff --git a/sdk/storage/blob_storage/src/lib.rs b/sdk/storage/blob_storage/src/lib.rs new file mode 100644 index 0000000000..ec2d89e66b --- /dev/null +++ b/sdk/storage/blob_storage/src/lib.rs @@ -0,0 +1,15 @@ +// 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. + +mod generated; + +pub use crate::generated::clients::*; + +pub mod models { + pub use crate::generated::enums::*; + pub use crate::generated::models::*; +} + +pub use blob_client::BlobClient; From bc607390208576618917657eaaef1ee036cd84dd Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Wed, 30 Oct 2024 18:19:42 -0700 Subject: [PATCH 02/19] Moved gen code into our dir, rough draft StorageHeadersPolicy, having issues with setting per-call via options bag --- Cargo.toml | 1 - sdk/storage/azure_storage_blob/Cargo.toml | 3 +- .../blob_storage/Cargo.toml | 0 .../src/generated/clients/blob_append_blob.rs | 0 .../src/generated/clients/blob_blob.rs | 0 .../src/generated/clients/blob_block_blob.rs | 0 .../src/generated/clients/blob_client.rs | 3 +- .../src/generated/clients/blob_container.rs | 0 .../src/generated/clients/blob_page_blob.rs | 0 .../src/generated/clients/blob_service.rs | 0 .../blob_storage/src/generated/clients/mod.rs | 0 .../blob_storage/src/generated/enums.rs | 0 .../blob_storage/src/generated/mod.rs | 0 .../blob_storage/src/generated/models.rs | 0 .../blob_storage/src/lib.rs | 0 .../src/clients/blob_client.rs | 45 +++++++++++-------- sdk/storage/azure_storage_blob/src/lib.rs | 1 + .../azure_storage_blob/src/policies/mod.rs | 4 ++ .../src/policies/storage_headers_policy.rs | 32 +++++++++++++ 19 files changed, 67 insertions(+), 22 deletions(-) rename sdk/storage/{ => azure_storage_blob}/blob_storage/Cargo.toml (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_append_blob.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_blob.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_block_blob.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_client.rs (97%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_container.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_page_blob.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/blob_service.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/clients/mod.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/enums.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/mod.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/generated/models.rs (100%) rename sdk/storage/{ => azure_storage_blob}/blob_storage/src/lib.rs (100%) create mode 100644 sdk/storage/azure_storage_blob/src/policies/mod.rs create mode 100644 sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs diff --git a/Cargo.toml b/Cargo.toml index 4ccbcdbedf..694c89ae73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ members = [ "eng/test/mock_transport", "sdk/storage", "sdk/storage/azure_storage_blob", - "sdk/storage/blob_storage", ] [workspace.package] diff --git a/sdk/storage/azure_storage_blob/Cargo.toml b/sdk/storage/azure_storage_blob/Cargo.toml index bbef0b9057..1acadcfc25 100644 --- a/sdk/storage/azure_storage_blob/Cargo.toml +++ b/sdk/storage/azure_storage_blob/Cargo.toml @@ -11,6 +11,7 @@ rust-version.workspace = true [dependencies] azure_storage_common.workspace = true +async-trait.workspace = true async-std = { workspace = true } azure_core = { workspace = true } serde = { workspace = true } @@ -18,7 +19,7 @@ serde_json = { workspace = true } time = { workspace = true } typespec_client_core = { workspace = true, features = ["reqwest"] } typespec_derive = { workspace = true } -blob_storage = { path = "../blob_storage" } +blob_storage = { path = "blob_storage" } uuid = { workspace = true } [dev-dependencies] diff --git a/sdk/storage/blob_storage/Cargo.toml b/sdk/storage/azure_storage_blob/blob_storage/Cargo.toml similarity index 100% rename from sdk/storage/blob_storage/Cargo.toml rename to sdk/storage/azure_storage_blob/blob_storage/Cargo.toml diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_append_blob.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_append_blob.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_append_blob.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_blob.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_block_blob.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs similarity index 97% rename from sdk/storage/blob_storage/src/generated/clients/blob_client.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs index a8cd2d0db9..ce7ec830dc 100644 --- a/sdk/storage/blob_storage/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs @@ -20,7 +20,8 @@ pub struct BlobClient { #[derive(Clone, Debug)] pub struct BlobClientOptions { - client_options: ClientOptions, + // NYI GENERATED CODE SUPPORT: client_options pub(crate) + pub client_options: ClientOptions, } impl BlobClient { diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_container.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_page_blob.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_page_blob.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_page_blob.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/blob_service.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/blob_service.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs diff --git a/sdk/storage/blob_storage/src/generated/clients/mod.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/mod.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/clients/mod.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/mod.rs diff --git a/sdk/storage/blob_storage/src/generated/enums.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/enums.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/enums.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/enums.rs diff --git a/sdk/storage/blob_storage/src/generated/mod.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/mod.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/mod.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/mod.rs diff --git a/sdk/storage/blob_storage/src/generated/models.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/models.rs similarity index 100% rename from sdk/storage/blob_storage/src/generated/models.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/generated/models.rs diff --git a/sdk/storage/blob_storage/src/lib.rs b/sdk/storage/azure_storage_blob/blob_storage/src/lib.rs similarity index 100% rename from sdk/storage/blob_storage/src/lib.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/lib.rs 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 ba874a467f..61d5b35cd0 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -1,60 +1,67 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -use azure_core::{Context, Method, Request, Response, Result, Url}; +use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use azure_core::{ + AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Request, Response, Result, Url, +}; use blob_storage::blob_blob::BlobBlobDownloadOptions; use blob_storage::blob_client::BlobClientOptions; use blob_storage::BlobClient as GeneratedBlobClient; use std::sync::Arc; use uuid::Uuid; -// Later this will be auto-populated with current version, otherwise could take user input as well -// const CURRENT_SVC_VERSION: String = String::from("2024-08-04"); - pub struct BlobClient { - account_name: String, + endpoint: String, container_name: String, blob_name: String, client: GeneratedBlobClient, } impl BlobClient { + const VERSION_ID: &'static str = ("2024-08-04"); + pub fn new( - account_name: String, + endpoint: String, container_name: String, blob_name: String, options: Option, ) -> Result { - // Build Blob URL from input - let endpoint = "https://".to_owned() + &account_name + ".blob.core.windows.net/"; let options = options.unwrap_or_default(); - let client = GeneratedBlobClient::with_no_credential(endpoint, Some(options))?; + + // Modify the policies in BlobClientOptions to have our new StorageHeadersPolicy + // let mut client_options = options.client_options; + // let per_call_policies = client_options.per_call_policies(); + // client_options.set_per_call_policies(per_call_policies); + + // let options = BlobClientOptions::default(); + // let mut client_options = options.client_options; + // client_options.set_per_call_policies(client_options.per_call_policies()); + + let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options))?; Ok(Self { - account_name: account_name.clone(), + endpoint: endpoint.clone(), container_name: container_name.clone(), blob_name: blob_name.clone(), client: client, }) } - // fn build_url(account_name: &str) -> String { - // "https://".to_owned() + account_name + ".blob.core.windows.net/" - // } - pub async fn download_blob( &self, - options: Option>, // Curious if this is the right move, or if we can do a simple wrapper with an easy Into convert to the generated version + options: Option>, ) -> Result>> { - //TODO: Inject version through a pipeline policy - let version = Uuid::new_v4().to_string(); + // Let's hardcode this for now, and we will set a different value in the pipeline policy. + // Pipeline policy value should show up since it runs last + let version = String::from("80bc3c5e-3bb7-95f6-6c57-8ceb2c9155"); self.client .get_blob_blob_client() .download( self.container_name.clone(), self.blob_name.clone(), version, - String::from("2024-08-04"), + String::from(Self::VERSION_ID), Some(BlobBlobDownloadOptions::default()), ) .await @@ -81,7 +88,7 @@ mod tests { #[tokio::test] async fn test_download_blob() { let blob_client = BlobClient::new( - String::from("vincenttranpublicac"), + String::from("https://vincenttranpublicac.blob.core.windows.net/"), String::from("public"), String::from("hello.txt"), Some(BlobClientOptions::default()), diff --git a/sdk/storage/azure_storage_blob/src/lib.rs b/sdk/storage/azure_storage_blob/src/lib.rs index 3ae259b188..97129b7561 100644 --- a/sdk/storage/azure_storage_blob/src/lib.rs +++ b/sdk/storage/azure_storage_blob/src/lib.rs @@ -2,3 +2,4 @@ // Licensed under the MIT License. mod clients; +mod policies; diff --git a/sdk/storage/azure_storage_blob/src/policies/mod.rs b/sdk/storage/azure_storage_blob/src/policies/mod.rs new file mode 100644 index 0000000000..ad1d1d9586 --- /dev/null +++ b/sdk/storage/azure_storage_blob/src/policies/mod.rs @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +pub(crate) mod storage_headers_policy; diff --git a/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs b/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs new file mode 100644 index 0000000000..927c83916f --- /dev/null +++ b/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +use async_trait::async_trait; +use azure_core::{Context, Policy, PolicyResult, Request}; +use std::sync::Arc; +use uuid::Uuid; + +#[derive(Debug, Clone)] +pub struct StorageHeadersPolicy {} + +impl StorageHeadersPolicy { + pub(crate) fn new() -> Self { + Self {} + } +} + +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +impl Policy for StorageHeadersPolicy { + async fn send( + &self, + ctx: &Context, + request: &mut Request, + next: &[Arc], + ) -> PolicyResult { + let request_id = Uuid::new_v4().to_string(); + request.insert_header("x-ms-client-request-id", request_id); + + next[0].send(ctx, request, &next[1..]).await + } +} From da34a57c8913813873af79f7899b711a08e0b647 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Thu, 31 Oct 2024 11:36:24 -0700 Subject: [PATCH 03/19] Modifiable options POC, next step is bringing in auth and verifying StorageHeadersPolicy --- .../azure_storage_blob/src/clients/blob_client.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 61d5b35cd0..743bb699a6 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -32,13 +32,15 @@ impl BlobClient { // Modify the policies in BlobClientOptions to have our new StorageHeadersPolicy // let mut client_options = options.client_options; // let per_call_policies = client_options.per_call_policies(); - // client_options.set_per_call_policies(per_call_policies); + // client_options.set_per_call_policies(*per_call_policies); - // let options = BlobClientOptions::default(); - // let mut client_options = options.client_options; - // client_options.set_per_call_policies(client_options.per_call_policies()); + let options = BlobClientOptions::default(); + let mut client_options = options.client_options.clone(); + let per_call_policies = client_options.per_call_policies().clone(); + client_options.set_per_call_policies(per_call_policies); - let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options))?; + let client = + GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; Ok(Self { endpoint: endpoint.clone(), From 3d8fad6f4954a852c5a6fa37f1213698ba9df5be Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Fri, 1 Nov 2024 14:33:56 -0700 Subject: [PATCH 04/19] Added StorageHeadersPolicy to per_call_policies, but weird side effect on response --- .../src/generated/clients/blob_client.rs | 2 +- .../azure_storage_blob/src/clients/blob_client.rs | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs index ce7ec830dc..022f96bd7a 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs @@ -20,7 +20,7 @@ pub struct BlobClient { #[derive(Clone, Debug)] pub struct BlobClientOptions { - // NYI GENERATED CODE SUPPORT: client_options pub(crate) + // NYI GENERATED CODE SUPPORT: client_options being pub pub client_options: ClientOptions, } 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 743bb699a6..6b42176c37 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -2,6 +2,7 @@ // Licensed under the MIT License. use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use azure_core::headers::HeaderName; use azure_core::{ AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Request, Response, Result, Url, }; @@ -27,17 +28,15 @@ impl BlobClient { blob_name: String, options: Option, ) -> Result { - let options = options.unwrap_or_default(); + let mut options = BlobClientOptions::default(); // Modify the policies in BlobClientOptions to have our new StorageHeadersPolicy - // let mut client_options = options.client_options; - // let per_call_policies = client_options.per_call_policies(); - // client_options.set_per_call_policies(*per_call_policies); - - let options = BlobClientOptions::default(); let mut client_options = options.client_options.clone(); - let per_call_policies = client_options.per_call_policies().clone(); + let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); + let mut per_call_policies = client_options.per_call_policies().clone(); + per_call_policies.push(storage_headers_policy); client_options.set_per_call_policies(per_call_policies); + options.client_options = client_options; let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; From 11afbc68aeb9a73a4b01403c4a1870200e278eba Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Fri, 1 Nov 2024 17:04:41 -0700 Subject: [PATCH 05/19] Working authenticated download --- sdk/storage/azure_storage_blob/Cargo.toml | 1 + .../src/clients/blob_client.rs | 58 ++++++++++++++++--- .../src/policies/storage_headers_policy.rs | 1 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/sdk/storage/azure_storage_blob/Cargo.toml b/sdk/storage/azure_storage_blob/Cargo.toml index 1acadcfc25..83e952baee 100644 --- a/sdk/storage/azure_storage_blob/Cargo.toml +++ b/sdk/storage/azure_storage_blob/Cargo.toml @@ -14,6 +14,7 @@ azure_storage_common.workspace = true async-trait.workspace = true async-std = { workspace = true } azure_core = { workspace = true } +azure_identity = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } time = { workspace = true } 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 6b42176c37..742489a63a 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -2,10 +2,13 @@ // Licensed under the MIT License. use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ - AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Request, Response, Result, Url, + AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, Response, + Result, Url, }; +use azure_identity::DefaultAzureCredentialBuilder; use blob_storage::blob_blob::BlobBlobDownloadOptions; use blob_storage::blob_client::BlobClientOptions; use blob_storage::BlobClient as GeneratedBlobClient; @@ -16,6 +19,7 @@ pub struct BlobClient { endpoint: String, container_name: String, blob_name: String, + credential: Option>, client: GeneratedBlobClient, } @@ -26,17 +30,31 @@ impl BlobClient { endpoint: String, container_name: String, blob_name: String, + credential: Option>, options: Option, ) -> Result { let mut options = BlobClientOptions::default(); - // Modify the policies in BlobClientOptions to have our new StorageHeadersPolicy + // Fold in StorageHeadersPolicy policy via ClientOptions let mut client_options = options.client_options.clone(); - let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); let mut per_call_policies = client_options.per_call_policies().clone(); + let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); per_call_policies.push(storage_headers_policy); client_options.set_per_call_policies(per_call_policies); - options.client_options = client_options; + + // Conditionally add authentication if provided + if credential.is_some() { + let oauth_token_policy = BearerTokenCredentialPolicy::new( + credential.clone().unwrap(), + ["https://storage.azure.com/.default"], + ); + let mut per_try_policies = client_options.per_call_policies().clone(); + per_try_policies.push(Arc::new(oauth_token_policy) as Arc); + client_options.set_per_try_policies(per_try_policies); + } + + // Set it after modifying everything + options.client_options = client_options.clone(); let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; @@ -45,6 +63,7 @@ impl BlobClient { endpoint: endpoint.clone(), container_name: container_name.clone(), blob_name: blob_name.clone(), + credential, client: client, }) } @@ -53,16 +72,15 @@ impl BlobClient { &self, options: Option>, ) -> Result>> { - // Let's hardcode this for now, and we will set a different value in the pipeline policy. - // Pipeline policy value should show up since it runs last + // This hard-coded value still works, even though this is technically a bug for version_id let version = String::from("80bc3c5e-3bb7-95f6-6c57-8ceb2c9155"); self.client .get_blob_blob_client() .download( self.container_name.clone(), self.blob_name.clone(), - version, - String::from(Self::VERSION_ID), + version, //blob version + String::from(Self::VERSION_ID), //svc version Some(BlobBlobDownloadOptions::default()), ) .await @@ -92,6 +110,30 @@ mod tests { String::from("https://vincenttranpublicac.blob.core.windows.net/"), String::from("public"), String::from("hello.txt"), + None, + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = blob_client + .download_blob(Some(BlobBlobDownloadOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Don't forget to az-login + async fn test_download_blob_authenticated() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + String::from("hello.txt"), + Some(credential), Some(BlobClientOptions::default()), ) .unwrap(); diff --git a/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs b/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs index 927c83916f..19e6f863e8 100644 --- a/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs +++ b/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs @@ -24,6 +24,7 @@ impl Policy for StorageHeadersPolicy { request: &mut Request, next: &[Arc], ) -> PolicyResult { + // TODO: Check if the header is already set (that means cx set), so don't set if so let request_id = Uuid::new_v4().to_string(); request.insert_header("x-ms-client-request-id", request_id); From c04ebff2b404fb94806dbd288f7207a188bdf733 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Mon, 4 Nov 2024 16:17:20 -0800 Subject: [PATCH 06/19] Fleshed out more of ContainerClient, BlobServiceClient, added get_blob_client to service, but some APIs are not functioning properly --- .../src/clients/blob_client.rs | 43 ++++- .../src/clients/blob_container_client.rs | 181 ++++++++++++++++++ .../src/clients/blob_service_client.rs | 153 +++++++++++++++ 3 files changed, 376 insertions(+), 1 deletion(-) 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 742489a63a..075ecd4001 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -9,7 +9,7 @@ use azure_core::{ Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; -use blob_storage::blob_blob::BlobBlobDownloadOptions; +use blob_storage::blob_blob::{BlobBlobDownloadOptions, BlobBlobGetPropertiesOptions}; use blob_storage::blob_client::BlobClientOptions; use blob_storage::BlobClient as GeneratedBlobClient; use std::sync::Arc; @@ -86,6 +86,26 @@ impl BlobClient { .await } + pub async fn get_blob_properties( + &self, + options: Option>, + ) -> Result> { + // This hard-coded value still works, even though this is technically a bug for version_id + let version = String::from("80bc3c5e-3bb7-95f6-6c57-8ceb2c9155"); + self.client + .get_blob_blob_client() + .get_properties( + self.container_name.clone(), + self.blob_name.clone(), + version, //blob version + String::from(Self::VERSION_ID), //svc version + Some(BlobBlobGetPropertiesOptions::default()), + ) + .await + } + + // pub fn get_container_client(&self) -> + // pub async fn get_blob_properties(&self) -> Result { // // Build the get properties request itself // let mut request = Request::new(self.url.to_owned(), Method::Head); // This is technically cloning @@ -125,6 +145,27 @@ mod tests { ); } + #[tokio::test] + async fn test_get_blob_properties() { + let blob_client = BlobClient::new( + String::from("https://vincenttranpublicac.blob.core.windows.net/"), + String::from("public"), + String::from("hello.txt"), + None, + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = blob_client + .get_blob_properties(Some(BlobBlobGetPropertiesOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + #[tokio::test] // Don't forget to az-login async fn test_download_blob_authenticated() { 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 d194bed477..fcb3fe929e 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 @@ -1,2 +1,183 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use azure_core::credentials::TokenCredential; +use azure_core::headers::HeaderName; +use azure_core::{ + AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, Response, + Result, Url, +}; +use azure_identity::DefaultAzureCredentialBuilder; +use blob_storage::blob_client::BlobClientOptions; +use blob_storage::blob_container::{ + BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, + BlobContainerGetPropertiesOptions, +}; +use blob_storage::BlobClient as GeneratedBlobClient; +use std::sync::Arc; +use uuid::Uuid; +pub struct ContainerClient { + endpoint: String, + container_name: String, + credential: Option>, + client: GeneratedBlobClient, +} + +impl ContainerClient { + const VERSION_ID: &'static str = ("2024-08-04"); + + pub fn new( + endpoint: String, + container_name: String, + credential: Option>, + options: Option, + ) -> Result { + let mut options = BlobClientOptions::default(); + + // Fold in StorageHeadersPolicy policy via ClientOptions + let mut client_options = options.client_options.clone(); + let mut per_call_policies = client_options.per_call_policies().clone(); + let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); + per_call_policies.push(storage_headers_policy); + client_options.set_per_call_policies(per_call_policies); + + // Conditionally add authentication if provided + if credential.is_some() { + let oauth_token_policy = BearerTokenCredentialPolicy::new( + credential.clone().unwrap(), + ["https://storage.azure.com/.default"], + ); + let mut per_try_policies = client_options.per_call_policies().clone(); + per_try_policies.push(Arc::new(oauth_token_policy) as Arc); + client_options.set_per_try_policies(per_try_policies); + } + + // Set it after modifying everything + options.client_options = client_options.clone(); + + let client = + GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; + + Ok(Self { + endpoint: endpoint.clone(), + container_name: container_name.clone(), + credential, + client: client, + }) + } + + pub async fn create_container( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_container_client() + .create( + self.container_name.clone(), + String::from(Self::VERSION_ID), //svc version + Some(BlobContainerCreateOptions::default()), + ) + .await + } + + pub async fn get_container_properties( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_container_client() + .get_properties( + self.container_name.clone(), + String::from(Self::VERSION_ID), //svc version + Some(BlobContainerGetPropertiesOptions::default()), + ) + .await + } + + pub async fn get_account_info( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_container_client() + .get_account_info( + self.container_name.clone(), + String::from(Self::VERSION_ID), //svc version + Some(BlobContainerGetAccountInfoOptions::default()), + ) + .await + } +} +#[cfg(test)] +mod tests { + use super::*; + #[tokio::test] + // Don't forget to az-login + // This fails for ContainerNotFound + async fn test_get_container_properties_auth() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let container_client = ContainerClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = container_client + .get_container_properties(Some(BlobContainerGetPropertiesOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Don't forget to az-login + // This fails for kind: HttpResponse { status: LengthRequired, error_code: None + async fn test_create_container() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let container_client = ContainerClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("mynewcontainer"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = container_client + .create_container(Some(BlobContainerCreateOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Don't forget to az-login + // This also fails for ContainerNotFound + async fn test_get_account_info_auth() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let container_client = ContainerClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = container_client + .get_account_info(Some(BlobContainerGetAccountInfoOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } +} 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 d194bed477..c4ae13568e 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 @@ -1,2 +1,155 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. + +use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use azure_core::credentials::TokenCredential; +use azure_core::headers::HeaderName; +use azure_core::{ + AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, Response, + Result, Url, +}; +use azure_identity::DefaultAzureCredentialBuilder; +use blob_storage::blob_blob::BlobBlobGetPropertiesOptions; +use blob_storage::blob_client::BlobClientOptions; +use blob_storage::blob_container::{ + BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, + BlobContainerGetPropertiesOptions, +}; +use blob_storage::blob_service::BlobServiceGetPropertiesOptions; +use blob_storage::models::StorageServiceProperties; +use blob_storage::BlobClient as GeneratedBlobClient; +use std::sync::Arc; +use uuid::Uuid; + +use super::blob_client::BlobClient; +pub struct BlobServiceClient { + endpoint: String, + credential: Option>, + client: GeneratedBlobClient, +} + +impl BlobServiceClient { + const VERSION_ID: &'static str = ("2024-08-04"); + + pub fn new( + endpoint: String, + credential: Option>, + options: Option, + ) -> Result { + let mut options = BlobClientOptions::default(); + + // Fold in StorageHeadersPolicy policy via ClientOptions + let mut client_options = options.client_options.clone(); + let mut per_call_policies = client_options.per_call_policies().clone(); + let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); + per_call_policies.push(storage_headers_policy); + client_options.set_per_call_policies(per_call_policies); + + // Conditionally add authentication if provided + if credential.is_some() { + let oauth_token_policy = BearerTokenCredentialPolicy::new( + credential.clone().unwrap(), + ["https://storage.azure.com/.default"], + ); + let mut per_try_policies = client_options.per_call_policies().clone(); + per_try_policies.push(Arc::new(oauth_token_policy) as Arc); + client_options.set_per_try_policies(per_try_policies); + } + + // Set it after modifying everything + options.client_options = client_options.clone(); + + let client = + GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; + + Ok(Self { + endpoint: endpoint.clone(), + credential, + client: client, + }) + } + + pub async fn get_service_properties( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_service_client() + .get_properties( + String::from(Self::VERSION_ID), //svc version + Some(BlobServiceGetPropertiesOptions::default()), + ) + .await + } + + pub fn get_blob_client( + &self, + container_name: String, + blob_name: String, + options: Option, + ) -> BlobClient { + BlobClient::new( + self.endpoint.clone(), + container_name.clone(), + blob_name.clone(), + self.credential.clone(), + options, + ) + .unwrap() + } +} +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + // Also fails for ContainerClientNotFound + // Don't forget to az-login + async fn test_get_service_properties() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let service_client = BlobServiceClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + let response = service_client + .get_service_properties(Some(BlobServiceGetPropertiesOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Don't forget to az-login + async fn test_get_blob_client() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let service_client = BlobServiceClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + Some(credential.clone()), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + let blob_client = service_client.get_blob_client( + String::from("acontainer108f32e8"), + String::from("hello.txt"), + Some(BlobClientOptions::default()), + ); + + let response = blob_client + .get_blob_properties(Some(BlobBlobGetPropertiesOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } +} From d30397ceec694fa75ce88b308461bfd6169b744c Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Tue, 5 Nov 2024 15:14:58 -0800 Subject: [PATCH 07/19] Found root-cause of API failures: %-encoding --- .../blob_storage/src/generated/clients/blob_blob.rs | 1 + .../blob_storage/src/generated/clients/blob_container.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs index cfa5b45fad..0f3fe64203 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs @@ -599,6 +599,7 @@ impl BlobBlob { request.insert_header("x-ms-lease-id", lease_id); } request.insert_header("x-ms-version", version.into()); + print!("\n***{:?}***\n", request.clone()); self.pipeline.send(&mut ctx, &mut request).await } diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs index 72e8b9609d..3a39a75279 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs @@ -316,12 +316,20 @@ impl BlobContainer { let mut ctx = options.method_options.context(); let mut url = self.endpoint.clone(); let mut path = String::from("/{containerName}?restype=container"); + // print!("\npath before: {}\n", path.clone()); path = path.replace("{containerName}", &container_name.into()); + // print!("\npath after: {}\n", path.clone()); url.set_path(&path); if let Some(timeout) = options.timeout { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + // print!("\nurl after using set_path: {}\n", url.clone()); + // let injected_url = Url::parse( + // "https://vincenttranstock.blob.core.windows.net/acontainer108f32e8?restype=container", + // ) + // .expect("URL parsing failed."); + // let mut request = Request::new(injected_url, Method::Get); let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { @@ -331,6 +339,7 @@ impl BlobContainer { request.insert_header("x-ms-lease-id", lease_id); } request.insert_header("x-ms-version", version.into()); + // print!("\n***{:?}***\n", request.clone()); self.pipeline.send(&mut ctx, &mut request).await } From ba209be2e0d3bdc839f0ad2c18d1b03019beff79 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Tue, 5 Nov 2024 16:21:27 -0800 Subject: [PATCH 08/19] All written tests working except commented, double-ended issues with path --- .../src/generated/clients/blob_client.rs | 3 +- .../src/generated/clients/blob_container.rs | 30 +++++++++---- .../src/generated/clients/blob_service.rs | 8 ++++ .../src/clients/blob_container_client.rs | 43 +++++++++---------- 4 files changed, 51 insertions(+), 33 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs index 022f96bd7a..c407a5b927 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs @@ -30,7 +30,8 @@ impl BlobClient { options: Option, ) -> Result { let mut endpoint = Url::parse(endpoint.as_ref())?; - endpoint.query_pairs_mut().clear(); + // NYI GENERATED CODE SUPPORTED: Remove call to query_pairs_mut().clear() + // endpoint.query_pairs_mut().clear(); let options = options.unwrap_or_default(); Ok(Self { endpoint, diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs index 3a39a75279..c4a25b9d4e 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs @@ -295,6 +295,14 @@ impl BlobContainer { let mut path = String::from("/{containerName}?restype=account&comp=properties"); path = path.replace("{containerName}", &container_name.into()); url.set_path(&path); + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { @@ -314,22 +322,27 @@ impl BlobContainer { ) -> Result> { let options = options.unwrap_or_default(); let mut ctx = options.method_options.context(); + println!("\nWhat is endpoint: {}\n", self.endpoint.as_str()); let mut url = self.endpoint.clone(); + println!("\nStep 1: {}\n", url.as_str()); let mut path = String::from("/{containerName}?restype=container"); - // print!("\npath before: {}\n", path.clone()); path = path.replace("{containerName}", &container_name.into()); - // print!("\npath after: {}\n", path.clone()); + url.set_path(&path); + println!("\nStep 2: {}\n", url.as_str()); + if let Some(timeout) = options.timeout { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } - // print!("\nurl after using set_path: {}\n", url.clone()); - // let injected_url = Url::parse( - // "https://vincenttranstock.blob.core.windows.net/acontainer108f32e8?restype=container", - // ) - // .expect("URL parsing failed."); - // let mut request = Request::new(injected_url, Method::Get); + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { @@ -339,7 +352,6 @@ impl BlobContainer { request.insert_header("x-ms-lease-id", lease_id); } request.insert_header("x-ms-version", version.into()); - // print!("\n***{:?}***\n", request.clone()); self.pipeline.send(&mut ctx, &mut request).await } diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs index 35314284db..43dfac1aec 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs @@ -96,6 +96,14 @@ impl BlobService { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { 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 fcb3fe929e..9e96a16fe3 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 @@ -114,7 +114,6 @@ mod tests { use super::*; #[tokio::test] // Don't forget to az-login - // This fails for ContainerNotFound async fn test_get_container_properties_auth() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let container_client = ContainerClient::new( @@ -135,32 +134,30 @@ mod tests { ); } - #[tokio::test] + // #[tokio::test] // Don't forget to az-login // This fails for kind: HttpResponse { status: LengthRequired, error_code: None - async fn test_create_container() { - let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); - let container_client = ContainerClient::new( - String::from("https://vincenttranstock.blob.core.windows.net/"), - String::from("mynewcontainer"), - Some(credential), - Some(BlobClientOptions::default()), - ) - .unwrap(); - let response = container_client - .create_container(Some(BlobContainerCreateOptions::default())) - .await - .unwrap(); - print!("{:?}", response); - print!( - "\n{:?}", - response.into_body().collect_string().await.unwrap() - ); - } - + // async fn test_create_container() { + // let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + // let container_client = ContainerClient::new( + // String::from("https://vincenttranstock.blob.core.windows.net/"), + // String::from("mynewcontainer"), + // Some(credential), + // Some(BlobClientOptions::default()), + // ) + // .unwrap(); + // let response = container_client + // .create_container(Some(BlobContainerCreateOptions::default())) + // .await + // .unwrap(); + // print!("{:?}", response); + // print!( + // "\n{:?}", + // response.into_body().collect_string().await.unwrap() + // ); + // } #[tokio::test] // Don't forget to az-login - // This also fails for ContainerNotFound async fn test_get_account_info_auth() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let container_client = ContainerClient::new( From 2818038bc6cad8270fac4919444dd45799746990 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Wed, 6 Nov 2024 16:08:43 -0800 Subject: [PATCH 09/19] Finally working tags header value, working options bag --- .../src/clients/blob_client.rs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) 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 075ecd4001..cc547c4cf8 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -81,7 +81,7 @@ impl BlobClient { self.blob_name.clone(), version, //blob version String::from(Self::VERSION_ID), //svc version - Some(BlobBlobDownloadOptions::default()), + options, ) .await } @@ -145,6 +145,34 @@ mod tests { ); } + #[tokio::test] + async fn test_download_blob_if_tags_match() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("options-bag-testing"), + String::from("i_have_tags.txt"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + // Build an BlobBlobDownloadOptions that contains if_tags_match with the matching condition to {tagged: yes} + // These are expected as: ""=' Date: Mon, 11 Nov 2024 16:56:14 -0800 Subject: [PATCH 10/19] Refactor get-subclient, bring back type-state for blob types(append,page,block), questions regarding endpoint and pipeline visibility --- .../src/generated/clients/blob_client.rs | 5 +- .../src/clients/blob_client.rs | 99 +++++++++---------- .../src/clients/blob_service_client.rs | 21 ++-- .../azure_storage_blob/src/clients/mod.rs | 1 + .../azure_storage_blob/src/clients/units.rs | 9 ++ 5 files changed, 70 insertions(+), 65 deletions(-) create mode 100644 sdk/storage/azure_storage_blob/src/clients/units.rs diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs index c407a5b927..6e17c8ac3f 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs @@ -14,8 +14,9 @@ use azure_core::{ClientOptions, Pipeline, Policy, Result, RetryOptions, Transpor use std::sync::Arc; pub struct BlobClient { - endpoint: Url, - pipeline: Pipeline, + //NYI GENERATED CODE SUPPORT: endpoint & pipeline being pub + pub endpoint: Url, + pub pipeline: Pipeline, } #[derive(Clone, Debug)] 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 cc547c4cf8..99bc9387f0 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/src/clients/blob_client.rs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::clients::units::*; use crate::policies::storage_headers_policy::StorageHeadersPolicy; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; @@ -12,18 +13,20 @@ use azure_identity::DefaultAzureCredentialBuilder; use blob_storage::blob_blob::{BlobBlobDownloadOptions, BlobBlobGetPropertiesOptions}; use blob_storage::blob_client::BlobClientOptions; use blob_storage::BlobClient as GeneratedBlobClient; +use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; -pub struct BlobClient { - endpoint: String, - container_name: String, - blob_name: String, - credential: Option>, - client: GeneratedBlobClient, +pub struct BlobClient { + pub(crate) blob_type: PhantomData, + pub(crate) endpoint: String, + pub(crate) container_name: String, + pub(crate) blob_name: String, + pub(crate) credential: Option>, + pub(crate) client: GeneratedBlobClient, } -impl BlobClient { +impl BlobClient { const VERSION_ID: &'static str = ("2024-08-04"); pub fn new( @@ -60,6 +63,7 @@ impl BlobClient { GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; Ok(Self { + blob_type: PhantomData::, endpoint: endpoint.clone(), container_name: container_name.clone(), blob_name: blob_name.clone(), @@ -68,6 +72,20 @@ impl BlobClient { }) } + pub async fn as_append_blob(&self) -> BlobClient { + BlobClient { + blob_type: PhantomData::, + endpoint: self.endpoint.clone(), + container_name: self.container_name.clone(), + blob_name: self.blob_name.clone(), + credential: self.credential.clone(), + client: GeneratedBlobClient { + endpoint: self.client.endpoint.clone(), + pipeline: self.client.pipeline.clone(), + }, + } + } + pub async fn download_blob( &self, options: Option>, @@ -103,21 +121,12 @@ impl BlobClient { ) .await } +} - // pub fn get_container_client(&self) -> - - // pub async fn get_blob_properties(&self) -> Result { - // // Build the get properties request itself - // let mut request = Request::new(self.url.to_owned(), Method::Head); // This is technically cloning - // BlobClient::finalize_request(&mut request); - - // // Send the request - // let response = self.pipeline.send(&(Context::new()), &mut request).await?; - // println!("Response headers: {:?}", response); - - // // Return the entire response for now - // Ok(response) - // } +impl BlobClient { + pub async fn append_block(&self) { + todo!() + } } #[cfg(test)] @@ -216,38 +225,18 @@ mod tests { response.into_body().collect_string().await.unwrap() ); } -} -// #[tokio::test] -// async fn test_get_blob_properties() { -// let credential = DefaultAzureCredentialBuilder::default() -// .build() -// .map(|cred| Arc::new(cred) as Arc) -// .expect("Failed to build credential"); - -// // Create a Blob Client -// let my_blob_client = BlobClient::new( -// String::from("vincenttranstock"), -// String::from("acontainer108f32e8"), -// String::from("hello.txt"), -// credential, -// None, -// ); - -// // Get response -// let ret = my_blob_client -// .get_blob_properties() -// .await -// .expect("Request failed!"); -// let (status_code, headers, _response_body) = ret.deconstruct(); - -// // Assert equality -// assert_eq!(status_code, azure_core::StatusCode::Ok); -// assert_eq!( -// headers -// .get_str(&HeaderName::from_static("content-length")) -// .expect("Failed getting content-length header"), -// "10" -// ) -// } -// } + #[tokio::test] + async fn test_get_append_client() { + let blob_client = BlobClient::new( + String::from("https://vincenttranpublicac.blob.core.windows.net/"), + String::from("public"), + String::from("hello.txt"), + None, + Some(BlobClientOptions::default()), + ) + .unwrap(); + let append_block_client = blob_client.as_append_blob().await; + append_block_client.append_block(); + } +} 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 c4ae13568e..d1fd3f6e7a 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 @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::clients::units::*; use crate::policies::storage_headers_policy::StorageHeadersPolicy; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; @@ -18,6 +19,7 @@ use blob_storage::blob_container::{ use blob_storage::blob_service::BlobServiceGetPropertiesOptions; use blob_storage::models::StorageServiceProperties; use blob_storage::BlobClient as GeneratedBlobClient; +use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; @@ -88,14 +90,17 @@ impl BlobServiceClient { blob_name: String, options: Option, ) -> BlobClient { - BlobClient::new( - self.endpoint.clone(), - container_name.clone(), - blob_name.clone(), - self.credential.clone(), - options, - ) - .unwrap() + BlobClient { + blob_type: PhantomData::, + endpoint: self.client.endpoint.clone().to_string(), + container_name: container_name, + blob_name: blob_name, + credential: self.credential.clone(), + client: GeneratedBlobClient { + endpoint: self.client.endpoint.clone(), + pipeline: self.client.pipeline.clone(), + }, + } } } #[cfg(test)] diff --git a/sdk/storage/azure_storage_blob/src/clients/mod.rs b/sdk/storage/azure_storage_blob/src/clients/mod.rs index cb2f783338..fe276f69b9 100644 --- a/sdk/storage/azure_storage_blob/src/clients/mod.rs +++ b/sdk/storage/azure_storage_blob/src/clients/mod.rs @@ -4,3 +4,4 @@ mod blob_client; mod blob_container_client; mod blob_service_client; +mod units; diff --git a/sdk/storage/azure_storage_blob/src/clients/units.rs b/sdk/storage/azure_storage_blob/src/clients/units.rs new file mode 100644 index 0000000000..2bee082caa --- /dev/null +++ b/sdk/storage/azure_storage_blob/src/clients/units.rs @@ -0,0 +1,9 @@ +pub trait BlobKind {} +impl BlobKind for Unset {} +impl BlobKind for Block {} +impl BlobKind for Page {} +impl BlobKind for Append {} +pub struct Unset; +pub struct Block; +pub struct Page; +pub struct Append; From 0282be7e558defb19f8b770f45b507ed3964495a Mon Sep 17 00:00:00 2001 From: Vincent Tran Date: Mon, 11 Nov 2024 17:18:12 -0800 Subject: [PATCH 11/19] Attempt to make it one crate --- .../azure_storage_blob/blob_storage/Cargo.toml | 3 +++ .../src/clients/blob_client.rs | 6 +++--- .../src/clients/blob_container_client.rs | 12 ++++++------ .../src/clients/blob_service_client.rs | 18 +++++++++--------- .../{ => blob_storage}/src/clients/mod.rs | 0 .../{ => blob_storage}/src/clients/units.rs | 3 +++ .../src/generated/clients/blob_client.rs | 10 +++++----- .../azure_storage_blob/blob_storage/src/lib.rs | 2 ++ .../{ => blob_storage}/src/policies/mod.rs | 0 .../src/policies/storage_headers_policy.rs | 0 sdk/storage/azure_storage_blob/src/lib.rs | 3 --- 11 files changed, 31 insertions(+), 26 deletions(-) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/clients/blob_client.rs (97%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/clients/blob_container_client.rs (97%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/clients/blob_service_client.rs (94%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/clients/mod.rs (100%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/clients/units.rs (67%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/policies/mod.rs (100%) rename sdk/storage/azure_storage_blob/{ => blob_storage}/src/policies/storage_headers_policy.rs (100%) diff --git a/sdk/storage/azure_storage_blob/blob_storage/Cargo.toml b/sdk/storage/azure_storage_blob/blob_storage/Cargo.toml index 0bfe0b7f94..cb727bbf1f 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/Cargo.toml +++ b/sdk/storage/azure_storage_blob/blob_storage/Cargo.toml @@ -9,12 +9,15 @@ rust-version.workspace = true [dependencies] async-std = { workspace = true } +async-trait.workspace = true azure_core = { workspace = true } +azure_identity = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } time = { workspace = true } typespec_client_core = { workspace = true, features = ["reqwest"] } typespec_derive = { workspace = true } +uuid = { workspace = true } [dev-dependencies] tokio = { version = "1", features = ["macros", "rt-multi-thread"] } diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs similarity index 97% rename from sdk/storage/azure_storage_blob/src/clients/blob_client.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index 99bc9387f0..f4704cfa62 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -1,8 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::blob_blob::{BlobBlobDownloadOptions, BlobBlobGetPropertiesOptions}; +use crate::blob_client::BlobClientOptions; use crate::clients::units::*; use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ @@ -10,9 +13,6 @@ use azure_core::{ Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; -use blob_storage::blob_blob::{BlobBlobDownloadOptions, BlobBlobGetPropertiesOptions}; -use blob_storage::blob_client::BlobClientOptions; -use blob_storage::BlobClient as GeneratedBlobClient; use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs similarity index 97% rename from sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs index 9e96a16fe3..3c02bd0c28 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs @@ -1,7 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::blob_client::BlobClientOptions; +use crate::blob_container::{ + BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, + BlobContainerGetPropertiesOptions, +}; use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ @@ -9,12 +15,6 @@ use azure_core::{ Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; -use blob_storage::blob_client::BlobClientOptions; -use blob_storage::blob_container::{ - BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, - BlobContainerGetPropertiesOptions, -}; -use blob_storage::BlobClient as GeneratedBlobClient; use std::sync::Arc; use uuid::Uuid; pub struct ContainerClient { diff --git a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs similarity index 94% rename from sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs index d1fd3f6e7a..4ec23098eb 100644 --- a/sdk/storage/azure_storage_blob/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs @@ -1,8 +1,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +use crate::blob_blob::BlobBlobGetPropertiesOptions; +use crate::blob_client::BlobClientOptions; +use crate::blob_container::{ + BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, + BlobContainerGetPropertiesOptions, +}; +use crate::blob_service::BlobServiceGetPropertiesOptions; use crate::clients::units::*; +use crate::models::StorageServiceProperties; use crate::policies::storage_headers_policy::StorageHeadersPolicy; +use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ @@ -10,15 +19,6 @@ use azure_core::{ Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; -use blob_storage::blob_blob::BlobBlobGetPropertiesOptions; -use blob_storage::blob_client::BlobClientOptions; -use blob_storage::blob_container::{ - BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, - BlobContainerGetPropertiesOptions, -}; -use blob_storage::blob_service::BlobServiceGetPropertiesOptions; -use blob_storage::models::StorageServiceProperties; -use blob_storage::BlobClient as GeneratedBlobClient; use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; diff --git a/sdk/storage/azure_storage_blob/src/clients/mod.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/mod.rs similarity index 100% rename from sdk/storage/azure_storage_blob/src/clients/mod.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/clients/mod.rs diff --git a/sdk/storage/azure_storage_blob/src/clients/units.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/units.rs similarity index 67% rename from sdk/storage/azure_storage_blob/src/clients/units.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/clients/units.rs index 2bee082caa..e451ceb78d 100644 --- a/sdk/storage/azure_storage_blob/src/clients/units.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/units.rs @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + pub trait BlobKind {} impl BlobKind for Unset {} impl BlobKind for Block {} diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs index 6e17c8ac3f..8d18adc993 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_client.rs @@ -14,15 +14,15 @@ use azure_core::{ClientOptions, Pipeline, Policy, Result, RetryOptions, Transpor use std::sync::Arc; pub struct BlobClient { - //NYI GENERATED CODE SUPPORT: endpoint & pipeline being pub - pub endpoint: Url, - pub pipeline: Pipeline, + //NYI GENERATED CODE SUPPORT: endpoint & pipeline being pub(crate) + pub(crate) endpoint: Url, + pub(crate) pipeline: Pipeline, } #[derive(Clone, Debug)] pub struct BlobClientOptions { - // NYI GENERATED CODE SUPPORT: client_options being pub - pub client_options: ClientOptions, + // NYI GENERATED CODE SUPPORT: client_options being pub(crate) + pub(crate) client_options: ClientOptions, } impl BlobClient { diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/lib.rs b/sdk/storage/azure_storage_blob/blob_storage/src/lib.rs index ec2d89e66b..73229932a8 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/lib.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/lib.rs @@ -3,7 +3,9 @@ // 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. +pub mod clients; mod generated; +pub mod policies; pub use crate::generated::clients::*; diff --git a/sdk/storage/azure_storage_blob/src/policies/mod.rs b/sdk/storage/azure_storage_blob/blob_storage/src/policies/mod.rs similarity index 100% rename from sdk/storage/azure_storage_blob/src/policies/mod.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/policies/mod.rs diff --git a/sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs b/sdk/storage/azure_storage_blob/blob_storage/src/policies/storage_headers_policy.rs similarity index 100% rename from sdk/storage/azure_storage_blob/src/policies/storage_headers_policy.rs rename to sdk/storage/azure_storage_blob/blob_storage/src/policies/storage_headers_policy.rs diff --git a/sdk/storage/azure_storage_blob/src/lib.rs b/sdk/storage/azure_storage_blob/src/lib.rs index 97129b7561..d194bed477 100644 --- a/sdk/storage/azure_storage_blob/src/lib.rs +++ b/sdk/storage/azure_storage_blob/src/lib.rs @@ -1,5 +1,2 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. - -mod clients; -mod policies; From c71e2644306adb19ab7cb586bd3df659d10cb376 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Tue, 12 Nov 2024 16:09:06 -0800 Subject: [PATCH 12/19] Create container working, list blobs and containers working --- .../src/clients/blob_container_client.rs | 40 +++++++++++++++++- .../src/clients/blob_service_client.rs | 41 ++++++++++++++++++- .../src/generated/clients/blob_container.rs | 8 ++++ .../src/generated/clients/blob_service.rs | 8 ++++ 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs index 3c02bd0c28..8d1b795bd8 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs @@ -4,8 +4,9 @@ use crate::blob_client::BlobClientOptions; use crate::blob_container::{ BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, - BlobContainerGetPropertiesOptions, + BlobContainerGetPropertiesOptions, BlobContainerListBlobFlatSegmentOptions, }; +use crate::models::ListBlobsFlatSegmentResponse; use crate::policies::storage_headers_policy::StorageHeadersPolicy; use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; @@ -108,6 +109,20 @@ impl ContainerClient { ) .await } + + pub async fn list_blobs( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_container_client() + .list_blob_flat_segment( + self.container_name.clone(), + String::from(Self::VERSION_ID), //svc version + Some(BlobContainerListBlobFlatSegmentOptions::default()), + ) + .await + } } #[cfg(test)] mod tests { @@ -134,6 +149,29 @@ mod tests { ); } + #[tokio::test] + // Don't forget to az-login + // TODO: Look into the return type, how do we make it more comprehensible + async fn test_list_blobs_auth() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let container_client = ContainerClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = container_client + .list_blobs(Some(BlobContainerListBlobFlatSegmentOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + // #[tokio::test] // Don't forget to az-login // This fails for kind: HttpResponse { status: LengthRequired, error_code: None diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs index 4ec23098eb..d17d12f14e 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs @@ -7,9 +7,11 @@ use crate::blob_container::{ BlobContainer, BlobContainerCreateOptions, BlobContainerGetAccountInfoOptions, BlobContainerGetPropertiesOptions, }; -use crate::blob_service::BlobServiceGetPropertiesOptions; +use crate::blob_service::{ + BlobServiceGetPropertiesOptions, BlobServiceListContainersSegmentOptions, +}; use crate::clients::units::*; -use crate::models::StorageServiceProperties; +use crate::models::{ListContainersSegmentResponse, StorageServiceProperties}; use crate::policies::storage_headers_policy::StorageHeadersPolicy; use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; @@ -102,6 +104,19 @@ impl BlobServiceClient { }, } } + + pub async fn list_containers( + &self, + options: Option>, + ) -> Result> { + self.client + .get_blob_service_client() + .list_containers_segment( + String::from(Self::VERSION_ID), //svc version + Some(BlobServiceListContainersSegmentOptions::default()), + ) + .await + } } #[cfg(test)] mod tests { @@ -157,4 +172,26 @@ mod tests { response.into_body().collect_string().await.unwrap() ); } + + #[tokio::test] + // Don't forget to az-login + async fn test_list_containers() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let service_client = BlobServiceClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + let response = service_client + .list_containers(Some(BlobServiceListContainersSegmentOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } } diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs index c4a25b9d4e..1e9fd0f46f 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs @@ -392,6 +392,14 @@ impl BlobContainer { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs index 43dfac1aec..07a75440c6 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_service.rs @@ -189,6 +189,14 @@ impl BlobService { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Get); request.insert_header("accept", "application/json"); if let Some(request_id) = options.request_id { From 0d081a631eec47ae08c8a43cbba841e030094016 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Wed, 13 Nov 2024 16:51:09 -0800 Subject: [PATCH 13/19] stage_block and commit_block_list fleshed out, but too many issues to iron out --- .../blob_storage/src/clients/blob_client.rs | 167 +++++++++++++++++- .../src/clients/blob_container_client.rs | 47 ++--- 2 files changed, 190 insertions(+), 24 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index f4704cfa62..6e29d2eadb 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -2,15 +2,19 @@ // Licensed under the MIT License. use crate::blob_blob::{BlobBlobDownloadOptions, BlobBlobGetPropertiesOptions}; +use crate::blob_block_blob::{ + BlobBlockBlobCommitBlockListOptions, BlobBlockBlobStageBlockOptions, BlobBlockBlobUploadOptions, +}; use crate::blob_client::BlobClientOptions; use crate::clients::units::*; +use crate::models::BlockLookupList; use crate::policies::storage_headers_policy::StorageHeadersPolicy; use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ - AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, Response, - Result, Url, + AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, RequestContent, + Response, Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; use std::marker::PhantomData; @@ -86,6 +90,20 @@ impl BlobClient { } } + pub async fn as_block_blob(&self) -> BlobClient { + BlobClient { + blob_type: PhantomData::, + endpoint: self.endpoint.clone(), + container_name: self.container_name.clone(), + blob_name: self.blob_name.clone(), + credential: self.credential.clone(), + client: GeneratedBlobClient { + endpoint: self.client.endpoint.clone(), + pipeline: self.client.pipeline.clone(), + }, + } + } + pub async fn download_blob( &self, options: Option>, @@ -104,6 +122,25 @@ impl BlobClient { .await } + pub async fn upload_blob( + &self, + data: RequestContent>, + options: Option>, + ) -> Result> { + //For now, this will only be Block Blob hot-path + + self.client + .get_blob_block_blob_client() + .upload( + self.container_name.clone(), + self.blob_name.clone(), + data, + String::from(Self::VERSION_ID), + options, + ) + .await + } + pub async fn get_blob_properties( &self, options: Option>, @@ -129,8 +166,51 @@ impl BlobClient { } } +impl BlobClient { + pub async fn stage_block( + &self, + block_id: String, + data: Vec, + options: Option>, + ) -> Result> { + // TODO: Definitely don't do that + let content_length = i64::try_from(data.len()).unwrap(); + self.client + .get_blob_block_blob_client() + .stage_block( + RequestContent::from(data), + self.container_name.clone(), + self.blob_name.clone(), + block_id, + content_length, + String::from(BlobClient::VERSION_ID), + options, + ) + .await + } + + pub async fn commit_block_list( + &self, + blocks: BlockLookupList, + options: Option>, + ) -> Result> { + self.client + .get_blob_block_blob_client() + .commit_block_list( + RequestContent::try_from(blocks)?, + self.container_name.clone(), + self.blob_name.clone(), + String::from(BlobClient::VERSION_ID), + options, + ) + .await + } +} + #[cfg(test)] mod tests { + use azure_core::Model; + use super::*; #[tokio::test] @@ -154,6 +234,89 @@ mod tests { ); } + #[tokio::test] + // Need az login + async fn test_upload_blob() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + String::from("goodbye.txt"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + let data = b"hello world".to_vec(); + let rq = RequestContent::from(data); + let response = blob_client + .upload_blob(rq, Some(BlobBlockBlobUploadOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Need az login + // This unexpectedly is putting ?comp=block into the blob name, also seems to committing as well + async fn test_put_block_list() { + let credential: Arc = + DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + String::from("put-them-blocks1111"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + // Stage Blocks + let data1 = b"AAA".to_vec(); + let data2 = b"BBB".to_vec(); + let data3 = b"CCC".to_vec(); + let response = blob_client + .stage_block( + String::from("1"), + data1, + Some(BlobBlockBlobStageBlockOptions::default()), + ) + .await; + + print!("{:?}", response); + + // blob_client.stage_block( + // String::from("2"), + // data2, + // Some(BlobBlockBlobStageBlockOptions::default()), + // ); + // blob_client.stage_block( + // String::from("3"), + // data3, + // Some(BlobBlockBlobStageBlockOptions::default()), + // ); + + // // Commit Block List + // let block_id_vec = vec![String::from("1"), String::from("2"), String::from("3")]; + // let block_lookup_list = BlockLookupList { + // committed: None, + // latest: Some(block_id_vec), + // uncommitted: None, + // }; + + // let response = blob_client + // .commit_block_list( + // block_lookup_list, + // Some(BlobBlockBlobCommitBlockListOptions::default()), + // ) + // .await; + // print!("{:?}", response); + } + #[tokio::test] async fn test_download_blob_if_tags_match() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs index 8d1b795bd8..f5bbe517d7 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs @@ -13,7 +13,7 @@ use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, Response, - Result, Url, + Result, StatusCode, Url, }; use azure_identity::DefaultAzureCredentialBuilder; use std::sync::Arc; @@ -172,28 +172,31 @@ mod tests { ); } - // #[tokio::test] + #[tokio::test] // Don't forget to az-login - // This fails for kind: HttpResponse { status: LengthRequired, error_code: None - // async fn test_create_container() { - // let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); - // let container_client = ContainerClient::new( - // String::from("https://vincenttranstock.blob.core.windows.net/"), - // String::from("mynewcontainer"), - // Some(credential), - // Some(BlobClientOptions::default()), - // ) - // .unwrap(); - // let response = container_client - // .create_container(Some(BlobContainerCreateOptions::default())) - // .await - // .unwrap(); - // print!("{:?}", response); - // print!( - // "\n{:?}", - // response.into_body().collect_string().await.unwrap() - // ); - // } + async fn test_create_container() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let container_client = ContainerClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("mynewcontainer"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = container_client + .create_container(Some(BlobContainerCreateOptions::default())) + .await; + + match response { + Ok(x) => { + println!("Created: {:?}", x); + } + Err(e) => { + assert_eq!(e.http_status(), Some(StatusCode::Conflict)) + } + } + } + #[tokio::test] // Don't forget to az-login async fn test_get_account_info_auth() { From 39fa6b329a34cf83e9048ec12369c7456c09689c Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Wed, 13 Nov 2024 16:51:30 -0800 Subject: [PATCH 14/19] Generated code changes necessary --- .../src/generated/clients/blob_block_blob.rs | 51 +++++++++++++++++++ .../src/generated/clients/blob_container.rs | 14 +++++ 2 files changed, 65 insertions(+) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs index ae3210e657..7be07b3f46 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs @@ -34,15 +34,26 @@ impl BlobBlockBlob { let options = options.unwrap_or_default(); let mut ctx = options.method_options.context(); let mut url = self.endpoint.clone(); + //let mut path = String::from("/{containerName}/{blob}?comp=blocklist"); let mut path = String::from("/?comp=blocklist/{containerName}/{blob}"); path = path.replace("{blob}", &blob.into()); path = path.replace("{containerName}", &container_name.into()); url.set_path(&path); + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let mut url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + if let Some(timeout) = options.timeout { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + 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); @@ -121,7 +132,15 @@ impl BlobBlockBlob { request.insert_header("x-ms-tags", blob_tags_string); } request.insert_header("x-ms-version", version.into()); + + // Generated Code Issue + // Issue: MissingRequiredHeader -- "x-ms-blob-type" + // [Proposed Change Start + // request.insert_header("x-ms-blob-type", "BlockBlob"); + // [Proposed Change End]] + request.set_body(blocks); + println!("\n\n{:?}\n\n", request.url().clone()); self.pipeline.send(&mut ctx, &mut request).await } @@ -300,13 +319,23 @@ impl BlobBlockBlob { let mut path = String::from("/{containerName}/{blob}?comp=block"); path = path.replace("{blob}", &blob.into()); path = path.replace("{containerName}", &container_name.into()); + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let mut url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + url.set_path(&path); + url.query_pairs_mut() .append_pair("blockid", &block_id.into()); if let Some(timeout) = options.timeout { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string()); @@ -336,6 +365,13 @@ impl BlobBlockBlob { request.insert_header("x-ms-lease-id", lease_id); } request.insert_header("x-ms-version", version.into()); + + // Generated Code Issue + // Issue: MissingRequiredHeader -- "x-ms-blob-type" + // [Proposed Change Start + request.insert_header("x-ms-blob-type", "BlockBlob"); + // [Proposed Change End] + request.set_body(body); self.pipeline.send(&mut ctx, &mut request).await } @@ -443,6 +479,14 @@ impl BlobBlockBlob { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); if let Some(transactional_content_md5) = options.transactional_content_md5 { @@ -526,6 +570,13 @@ impl BlobBlockBlob { } request.insert_header("x-ms-version", version.into()); request.set_body(body); + + // Generated Code Issue + // Issue: MissingRequiredHeader -- "x-ms-blob-type" + // [Proposed Change Start + request.insert_header("x-ms-blob-type", "BlockBlob"); + // [Proposed Change End] + self.pipeline.send(&mut ctx, &mut request).await } } diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs index 1e9fd0f46f..cb3e20567d 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_container.rs @@ -149,6 +149,14 @@ impl BlobContainer { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); if let Some(access) = options.access { @@ -167,6 +175,12 @@ impl BlobContainer { ); } request.insert_header("x-ms-version", version.into()); + + // Generated Code Issue + // Issue: Hitting "LengthRequired" error + // [Proposed Change Start] + request.insert_header("content-length", "0"); + // [Proposed Change End] self.pipeline.send(&mut ctx, &mut request).await } From 906db1cec0a838bc169fcea48085edeaa72a991f Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Fri, 15 Nov 2024 13:52:04 -0800 Subject: [PATCH 15/19] Working overwrite options bag, example for pub(crate) options in options bag --- .../blob_storage/src/clients/blob_client.rs | 38 ++++++++++++++++++- .../src/generated/clients/blob_block_blob.rs | 2 +- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index 6e29d2eadb..7e6459233e 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -125,10 +125,16 @@ impl BlobClient { pub async fn upload_blob( &self, data: RequestContent>, - options: Option>, + overwrite: Option, + mut options: Option>, ) -> Result> { //For now, this will only be Block Blob hot-path + // Check if they want overwrite, by default overwrite=False + if overwrite.is_none() || overwrite.unwrap() == false { + options.as_mut().unwrap().if_none_match = Some(String::from("*")); + } + self.client .get_blob_block_blob_client() .upload( @@ -236,6 +242,7 @@ mod tests { #[tokio::test] // Need az login + // May fail for overwrite now since this is default overwrite=False async fn test_upload_blob() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let blob_client = BlobClient::new( @@ -250,7 +257,34 @@ mod tests { let data = b"hello world".to_vec(); let rq = RequestContent::from(data); let response = blob_client - .upload_blob(rq, Some(BlobBlockBlobUploadOptions::default())) + .upload_blob(rq, None, Some(BlobBlockBlobUploadOptions::default())) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Need az login + // May fail for overwrite now since this is default overwrite=False + async fn test_upload_blob_overwrite_true() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + String::from("goodbye.txt"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + let data = b"hello world".to_vec(); + let rq = RequestContent::from(data); + let response = blob_client + .upload_blob(rq, Some(true), Some(BlobBlockBlobUploadOptions::default())) .await .unwrap(); print!("{:?}", response); diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs index ad1f6e4d65..c714725b56 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs @@ -730,7 +730,7 @@ pub struct BlobBlockBlobUploadOptions<'a> { encryption_scope: Option, if_match: Option, if_modified_since: Option, - if_none_match: Option, + pub(crate) if_none_match: Option, // NYI: Generated Code Change to make this visible to the crate if_tags: Option, if_unmodified_since: Option, immutability_policy_expiry: Option, From 9b081bc5dd44e06cbdba26bd948f1b5f06b76147 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Fri, 15 Nov 2024 15:58:46 -0800 Subject: [PATCH 16/19] Working setting tags on upload, sample helper --- .../blob_storage/src/clients/blob_client.rs | 92 ++++++++++++++++++- .../src/generated/clients/blob_block_blob.rs | 2 +- 2 files changed, 90 insertions(+), 4 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index 7e6459233e..bda3a5ac66 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -17,6 +17,7 @@ use azure_core::{ Response, Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; +use std::collections::HashMap; use std::marker::PhantomData; use std::sync::Arc; use uuid::Uuid; @@ -122,10 +123,45 @@ impl BlobClient { .await } + fn url_encode(input: &str) -> String { + // TODO: Use some built-in or make this.. better :) + // URL-encode the input string + input + .chars() + .map(|c| match c { + ' ' => "%20".to_string(), + '&' => "\u{0026}".to_string(), + _ => c.to_string(), + }) + .collect() + } + + fn hashmap_to_query_string(params: HashMap) -> String { + // TODO: Make this better + // Convert the HashMap to a query string + // Fun fact: these are NOT ordered. None of the built-in collections track order of insertion + let mut query_string = String::new(); + for (key, value) in ¶ms { + query_string.push_str(&format!("{}={}", key, value)); + if !query_string.is_empty() { + query_string.push('&'); + } + } + + // Remove extra & sign + let mut chars = query_string.chars(); + chars.next_back(); + query_string = String::from(chars.as_str()); + + // URL-encode the query string + Self::url_encode(&query_string) + } + pub async fn upload_blob( &self, data: RequestContent>, overwrite: Option, + tags: Option>, mut options: Option>, ) -> Result> { //For now, this will only be Block Blob hot-path @@ -135,6 +171,15 @@ impl BlobClient { options.as_mut().unwrap().if_none_match = Some(String::from("*")); } + // Parse tags if any, convert to server-acceptable format + match tags { + Some(tag) => { + let parsed_tags = Self::hashmap_to_query_string(tag); + options.as_mut().unwrap().blob_tags_string = Some(parsed_tags) + } + None => {} + } + self.client .get_blob_block_blob_client() .upload( @@ -257,7 +302,7 @@ mod tests { let data = b"hello world".to_vec(); let rq = RequestContent::from(data); let response = blob_client - .upload_blob(rq, None, Some(BlobBlockBlobUploadOptions::default())) + .upload_blob(rq, None, None, Some(BlobBlockBlobUploadOptions::default())) .await .unwrap(); print!("{:?}", response); @@ -269,7 +314,6 @@ mod tests { #[tokio::test] // Need az login - // May fail for overwrite now since this is default overwrite=False async fn test_upload_blob_overwrite_true() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let blob_client = BlobClient::new( @@ -284,7 +328,49 @@ mod tests { let data = b"hello world".to_vec(); let rq = RequestContent::from(data); let response = blob_client - .upload_blob(rq, Some(true), Some(BlobBlockBlobUploadOptions::default())) + .upload_blob( + rq, + Some(true), + None, + Some(BlobBlockBlobUploadOptions::default()), + ) + .await + .unwrap(); + print!("{:?}", response); + print!( + "\n{:?}", + response.into_body().collect_string().await.unwrap() + ); + } + + #[tokio::test] + // Need az login + async fn test_upload_blob_overwrite_true_with_tags() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranstock.blob.core.windows.net/"), + String::from("acontainer108f32e8"), + String::from("i-got-tags.txt"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + + // Create tags + let mut tags_hashmap = HashMap::new(); + tags_hashmap.insert("tag1 name".to_string(), "my tag".to_string()); + tags_hashmap.insert("tag2".to_string(), "secondtag".to_string()); + tags_hashmap.insert("tag3".to_string(), "thirdtag".to_string()); + + let data = b"hello world".to_vec(); + let rq = RequestContent::from(data); + let response = blob_client + .upload_blob( + rq, + Some(true), + Some(tags_hashmap), + Some(BlobBlockBlobUploadOptions::default()), + ) .await .unwrap(); print!("{:?}", response); diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs index c714725b56..6fbb0c6a87 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs @@ -723,7 +723,7 @@ pub struct BlobBlockBlobUploadOptions<'a> { blob_content_language: Option, blob_content_md5: Option, blob_content_type: Option, - blob_tags_string: Option, + pub(crate) blob_tags_string: Option, // NYI: Generated Code Change to make this visible to the crate encryption_algorithm: Option, encryption_key: Option, encryption_key_sha256: Option, From 96d5ca879399b80ee07000f7469cce11ef7fa7c8 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Mon, 18 Nov 2024 17:11:07 -0800 Subject: [PATCH 17/19] Slight cleanup, ranged downloads --- .../blob_storage/src/clients/blob_client.rs | 54 ++++++++++++++++--- .../src/generated/clients/blob_blob.rs | 2 +- 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index bda3a5ac66..3c14e734b3 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -13,8 +13,8 @@ use crate::BlobClient as GeneratedBlobClient; use azure_core::credentials::TokenCredential; use azure_core::headers::HeaderName; use azure_core::{ - AsClientOptions, BearerTokenCredentialPolicy, Context, Method, Policy, Request, RequestContent, - Response, Result, Url, + AsClientOptions, BearerTokenCredentialPolicy, Context, Error, Method, Policy, Request, + RequestContent, Response, Result, Url, }; use azure_identity::DefaultAzureCredentialBuilder; use std::collections::HashMap; @@ -107,10 +107,31 @@ impl BlobClient { pub async fn download_blob( &self, - options: Option>, + offset: Option, + length: Option, + mut options: Option>, ) -> Result>> { // This hard-coded value still works, even though this is technically a bug for version_id let version = String::from("80bc3c5e-3bb7-95f6-6c57-8ceb2c9155"); + + // If length and offset is provided, calculate and build range str + if length.is_some() { + // If length is provided, offset must be provided + if offset.is_none() { + // Error::with_message( + // ErrorKind::Other, + // "If length is provided, offset must be provided", + // ); + }; + + let range_str = format!( + "bytes={}-{}", + offset.unwrap(), + offset.unwrap() + length.unwrap() - 1 // Service uses inclusive end index + ); + options.as_mut().unwrap().range = Some(range_str) + } + self.client .get_blob_blob_client() .download( @@ -266,16 +287,17 @@ mod tests { #[tokio::test] async fn test_download_blob() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let blob_client = BlobClient::new( String::from("https://vincenttranpublicac.blob.core.windows.net/"), String::from("public"), String::from("hello.txt"), - None, + Some(credential), Some(BlobClientOptions::default()), ) .unwrap(); let response = blob_client - .download_blob(Some(BlobBlobDownloadOptions::default())) + .download_blob(None, None, Some(BlobBlobDownloadOptions::default())) .await .unwrap(); print!("{:?}", response); @@ -285,6 +307,24 @@ mod tests { ); } + #[tokio::test] + async fn test_download_blob_ranged() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); + let blob_client = BlobClient::new( + String::from("https://vincenttranpublicac.blob.core.windows.net/"), + String::from("public"), + String::from("hello.txt"), + Some(credential), + Some(BlobClientOptions::default()), + ) + .unwrap(); + let response = blob_client + .download_blob(Some(0), Some(4), Some(BlobBlobDownloadOptions::default())) + .await + .unwrap(); + assert_eq!(response.into_body().collect_string().await.unwrap(), "rust") + } + #[tokio::test] // Need az login // May fail for overwrite now since this is default overwrite=False @@ -455,7 +495,7 @@ mod tests { let download_options_builder = BlobBlobDownloadOptions::builder().with_if_tags(if_tags); let mut download_options = download_options_builder.build(); let response = blob_client - .download_blob(Some(download_options)) + .download_blob(None, None, Some(download_options)) .await .unwrap(); print!("{:?}", response); @@ -499,7 +539,7 @@ mod tests { ) .unwrap(); let response = blob_client - .download_blob(Some(BlobBlobDownloadOptions::default())) + .download_blob(None, None, Some(BlobBlobDownloadOptions::default())) .await .unwrap(); print!("{:?}", response); diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs index cfa5b45fad..eea3d1d4b8 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_blob.rs @@ -1395,7 +1395,7 @@ pub struct BlobBlobDownloadOptions<'a> { if_unmodified_since: Option, lease_id: Option, method_options: ClientMethodOptions<'a>, - range: Option, + pub(crate) range: Option, range_content_crc64: Option, range_content_md5: Option, request_id: Option, From e1e96f3c224e74044cf2c37a73dcdc8c13b2270a Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Tue, 19 Nov 2024 15:40:04 -0800 Subject: [PATCH 18/19] blob_client.rs all passing w/ asserts --- .../blob_storage/src/clients/blob_client.rs | 62 ++++++++----------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index 3c14e734b3..5f84243138 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -39,16 +39,17 @@ impl BlobClient { container_name: String, blob_name: String, credential: Option>, - options: Option, + mut options: Option, ) -> Result { let mut options = BlobClientOptions::default(); // Fold in StorageHeadersPolicy policy via ClientOptions - let mut client_options = options.client_options.clone(); - let mut per_call_policies = client_options.per_call_policies().clone(); + let mut per_call_policies = options.client_options.per_call_policies().clone(); let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); per_call_policies.push(storage_headers_policy); - client_options.set_per_call_policies(per_call_policies); + options + .client_options + .set_per_call_policies(per_call_policies); // Conditionally add authentication if provided if credential.is_some() { @@ -56,14 +57,13 @@ impl BlobClient { credential.clone().unwrap(), ["https://storage.azure.com/.default"], ); - let mut per_try_policies = client_options.per_call_policies().clone(); + let mut per_try_policies = options.client_options.per_call_policies().clone(); per_try_policies.push(Arc::new(oauth_token_policy) as Arc); - client_options.set_per_try_policies(per_try_policies); + options + .client_options + .set_per_try_policies(per_try_policies); } - // Set it after modifying everything - options.client_options = client_options.clone(); - let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; @@ -114,14 +114,11 @@ impl BlobClient { // This hard-coded value still works, even though this is technically a bug for version_id let version = String::from("80bc3c5e-3bb7-95f6-6c57-8ceb2c9155"); - // If length and offset is provided, calculate and build range str + // If length and offset is provided, calculate and build range String if length.is_some() { // If length is provided, offset must be provided if offset.is_none() { - // Error::with_message( - // ErrorKind::Other, - // "If length is provided, offset must be provided", - // ); + // Traditionally in other SDKs, we would do input validation that if length provided, offset is provided. Raise Err? }; let range_str = format!( @@ -145,7 +142,6 @@ impl BlobClient { } fn url_encode(input: &str) -> String { - // TODO: Use some built-in or make this.. better :) // URL-encode the input string input .chars() @@ -158,9 +154,8 @@ impl BlobClient { } fn hashmap_to_query_string(params: HashMap) -> String { - // TODO: Make this better - // Convert the HashMap to a query string - // Fun fact: these are NOT ordered. None of the built-in collections track order of insertion + // Convert the customer-provided HashMap to a valid query String + // Fun Fact: HashMaps insertions are NOT ordered. None of the built-in collections track order of insertion. let mut query_string = String::new(); for (key, value) in ¶ms { query_string.push_str(&format!("{}={}", key, value)); @@ -174,7 +169,7 @@ impl BlobClient { chars.next_back(); query_string = String::from(chars.as_str()); - // URL-encode the query string + // URL-encode the query String Self::url_encode(&query_string) } @@ -226,7 +221,7 @@ impl BlobClient { self.blob_name.clone(), version, //blob version String::from(Self::VERSION_ID), //svc version - Some(BlobBlobGetPropertiesOptions::default()), + options, ) .await } @@ -239,13 +234,13 @@ impl BlobClient { } impl BlobClient { + // TODO: Still not working, likely something wrong with path building and possibly encoding pub async fn stage_block( &self, block_id: String, data: Vec, options: Option>, ) -> Result> { - // TODO: Definitely don't do that let content_length = i64::try_from(data.len()).unwrap(); self.client .get_blob_block_blob_client() @@ -261,6 +256,7 @@ impl BlobClient { .await } + // TODO: Still not working, likely something wrong with path building and possibly encoding pub async fn commit_block_list( &self, blocks: BlockLookupList, @@ -327,7 +323,6 @@ mod tests { #[tokio::test] // Need az login - // May fail for overwrite now since this is default overwrite=False async fn test_upload_blob() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let blob_client = BlobClient::new( @@ -343,13 +338,14 @@ mod tests { let rq = RequestContent::from(data); let response = blob_client .upload_blob(rq, None, None, Some(BlobBlockBlobUploadOptions::default())) - .await - .unwrap(); - print!("{:?}", response); - print!( - "\n{:?}", - response.into_body().collect_string().await.unwrap() - ); + .await; + + match response { + Ok(response) => {} + Err(error) => { + assert_eq!(error.http_status(), Some(azure_core::StatusCode::Conflict)) + } + } } #[tokio::test] @@ -376,11 +372,6 @@ mod tests { ) .await .unwrap(); - print!("{:?}", response); - print!( - "\n{:?}", - response.into_body().collect_string().await.unwrap() - ); } #[tokio::test] @@ -507,11 +498,12 @@ mod tests { #[tokio::test] async fn test_get_blob_properties() { + let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let blob_client = BlobClient::new( String::from("https://vincenttranpublicac.blob.core.windows.net/"), String::from("public"), String::from("hello.txt"), - None, + Some(credential), Some(BlobClientOptions::default()), ) .unwrap(); From a597ebf3e28b78ebf89c6b2afd42e7308da4b7d5 Mon Sep 17 00:00:00 2001 From: vincenttran-msft Date: Thu, 21 Nov 2024 11:40:14 -0800 Subject: [PATCH 19/19] Code cleanup --- .../blob_storage/src/clients/blob_client.rs | 4 +-- .../src/clients/blob_container_client.rs | 29 ++++++++++--------- .../src/clients/blob_service_client.rs | 23 +++++++-------- .../src/generated/clients/blob_block_blob.rs | 16 +++++----- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs index 5f84243138..dbdbf55927 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_client.rs @@ -191,7 +191,7 @@ impl BlobClient { match tags { Some(tag) => { let parsed_tags = Self::hashmap_to_query_string(tag); - options.as_mut().unwrap().blob_tags_string = Some(parsed_tags) + (options.as_mut().unwrap()).blob_tags_string = Some(parsed_tags) } None => {} } @@ -420,7 +420,7 @@ mod tests { let blob_client = BlobClient::new( String::from("https://vincenttranstock.blob.core.windows.net/"), String::from("acontainer108f32e8"), - String::from("put-them-blocks1111"), + String::from("puttheblock"), Some(credential), Some(BlobClientOptions::default()), ) diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs index f5bbe517d7..5cfc644307 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_container_client.rs @@ -32,16 +32,17 @@ impl ContainerClient { endpoint: String, container_name: String, credential: Option>, - options: Option, + mut options: Option, ) -> Result { let mut options = BlobClientOptions::default(); // Fold in StorageHeadersPolicy policy via ClientOptions - let mut client_options = options.client_options.clone(); - let mut per_call_policies = client_options.per_call_policies().clone(); + let mut per_call_policies = options.client_options.per_call_policies().clone(); let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); per_call_policies.push(storage_headers_policy); - client_options.set_per_call_policies(per_call_policies); + options + .client_options + .set_per_call_policies(per_call_policies); // Conditionally add authentication if provided if credential.is_some() { @@ -49,14 +50,13 @@ impl ContainerClient { credential.clone().unwrap(), ["https://storage.azure.com/.default"], ); - let mut per_try_policies = client_options.per_call_policies().clone(); + let mut per_try_policies = options.client_options.per_call_policies().clone(); per_try_policies.push(Arc::new(oauth_token_policy) as Arc); - client_options.set_per_try_policies(per_try_policies); + options + .client_options + .set_per_try_policies(per_try_policies); } - // Set it after modifying everything - options.client_options = client_options.clone(); - let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; @@ -77,7 +77,7 @@ impl ContainerClient { .create( self.container_name.clone(), String::from(Self::VERSION_ID), //svc version - Some(BlobContainerCreateOptions::default()), + options, ) .await } @@ -91,7 +91,7 @@ impl ContainerClient { .get_properties( self.container_name.clone(), String::from(Self::VERSION_ID), //svc version - Some(BlobContainerGetPropertiesOptions::default()), + options, ) .await } @@ -105,7 +105,7 @@ impl ContainerClient { .get_account_info( self.container_name.clone(), String::from(Self::VERSION_ID), //svc version - Some(BlobContainerGetAccountInfoOptions::default()), + options, ) .await } @@ -119,7 +119,7 @@ impl ContainerClient { .list_blob_flat_segment( self.container_name.clone(), String::from(Self::VERSION_ID), //svc version - Some(BlobContainerListBlobFlatSegmentOptions::default()), + options, ) .await } @@ -178,7 +178,7 @@ mod tests { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); let container_client = ContainerClient::new( String::from("https://vincenttranstock.blob.core.windows.net/"), - String::from("mynewcontainer"), + String::from("mynewcontainere"), Some(credential), Some(BlobClientOptions::default()), ) @@ -186,6 +186,7 @@ mod tests { let response = container_client .create_container(Some(BlobContainerCreateOptions::default())) .await; + println!("{:?}", response); match response { Ok(x) => { diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs index d17d12f14e..11bff34d4b 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/clients/blob_service_client.rs @@ -38,16 +38,17 @@ impl BlobServiceClient { pub fn new( endpoint: String, credential: Option>, - options: Option, + mut options: Option, ) -> Result { let mut options = BlobClientOptions::default(); // Fold in StorageHeadersPolicy policy via ClientOptions - let mut client_options = options.client_options.clone(); - let mut per_call_policies = client_options.per_call_policies().clone(); + let mut per_call_policies = options.client_options.per_call_policies().clone(); let storage_headers_policy = Arc::new(StorageHeadersPolicy::new()); per_call_policies.push(storage_headers_policy); - client_options.set_per_call_policies(per_call_policies); + options + .client_options + .set_per_call_policies(per_call_policies); // Conditionally add authentication if provided if credential.is_some() { @@ -55,14 +56,13 @@ impl BlobServiceClient { credential.clone().unwrap(), ["https://storage.azure.com/.default"], ); - let mut per_try_policies = client_options.per_call_policies().clone(); + let mut per_try_policies = options.client_options.per_call_policies().clone(); per_try_policies.push(Arc::new(oauth_token_policy) as Arc); - client_options.set_per_try_policies(per_try_policies); + options + .client_options + .set_per_try_policies(per_try_policies); } - // Set it after modifying everything - options.client_options = client_options.clone(); - let client = GeneratedBlobClient::with_no_credential(endpoint.clone(), Some(options.clone()))?; @@ -81,7 +81,7 @@ impl BlobServiceClient { .get_blob_service_client() .get_properties( String::from(Self::VERSION_ID), //svc version - Some(BlobServiceGetPropertiesOptions::default()), + options, ) .await } @@ -113,7 +113,7 @@ impl BlobServiceClient { .get_blob_service_client() .list_containers_segment( String::from(Self::VERSION_ID), //svc version - Some(BlobServiceListContainersSegmentOptions::default()), + options, ) .await } @@ -123,7 +123,6 @@ mod tests { use super::*; #[tokio::test] - // Also fails for ContainerClientNotFound // Don't forget to az-login async fn test_get_service_properties() { let credential = DefaultAzureCredentialBuilder::default().build().unwrap(); diff --git a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs index 6fbb0c6a87..b39b175261 100644 --- a/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs +++ b/sdk/storage/azure_storage_blob/blob_storage/src/generated/clients/blob_block_blob.rs @@ -320,13 +320,6 @@ impl BlobBlockBlob { path = path.replace("{blob}", &blob.into()); path = path.replace("{containerName}", &container_name.into()); - // Generated Code Issue - // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() - // [Proposed Change Start] - // Before URL is sent to request, replace "%3F" -> "?" - let mut url = Url::parse(&url.as_str().replace("%3F", "?"))?; - // [Proposed Change End] - url.set_path(&path); url.query_pairs_mut() @@ -335,6 +328,15 @@ impl BlobBlockBlob { url.query_pairs_mut() .append_pair("timeout", &timeout.to_string()); } + + // Generated Code Issue + // Issue: Some characters, '?' are being %-encoded when they shouldn't be. This is due to the use of set_path() + // [Proposed Change Start] + // Before URL is sent to request, replace "%3F" -> "?" + let mut url = Url::parse(&url.as_str().replace("%3F", "?"))?; + // [Proposed Change End] + + println!("What URL gets added to request: {:?}", url); let mut request = Request::new(url, Method::Put); request.insert_header("accept", "application/json"); request.insert_header("content-length", content_length.to_string());