1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
17 
18 #include "google/cloud/storage/hmac_key_metadata.h"
19 #include "google/cloud/storage/internal/logging_client.h"
20 #include "google/cloud/storage/internal/parameter_pack_validation.h"
21 #include "google/cloud/storage/internal/policy_document_request.h"
22 #include "google/cloud/storage/internal/retry_client.h"
23 #include "google/cloud/storage/internal/signed_url_requests.h"
24 #include "google/cloud/storage/internal/tuple_filter.h"
25 #include "google/cloud/storage/list_buckets_reader.h"
26 #include "google/cloud/storage/list_hmac_keys_reader.h"
27 #include "google/cloud/storage/list_objects_and_prefixes_reader.h"
28 #include "google/cloud/storage/list_objects_reader.h"
29 #include "google/cloud/storage/notification_event_type.h"
30 #include "google/cloud/storage/notification_payload_format.h"
31 #include "google/cloud/storage/oauth2/google_credentials.h"
32 #include "google/cloud/storage/object_rewriter.h"
33 #include "google/cloud/storage/object_stream.h"
34 #include "google/cloud/storage/retry_policy.h"
35 #include "google/cloud/storage/upload_options.h"
36 #include "google/cloud/storage/version.h"
37 #include "google/cloud/internal/throw_delegate.h"
38 #include "google/cloud/status.h"
39 #include "google/cloud/status_or.h"
40 #include "absl/meta/type_traits.h"
41 #include <type_traits>
42 
43 namespace google {
44 namespace cloud {
45 namespace storage {
46 namespace testing {
47 class ClientTester;
48 }  // namespace testing
49 inline namespace STORAGE_CLIENT_NS {
50 namespace internal {
51 class NonResumableParallelUploadState;
52 class ResumableParallelUploadState;
53 }  // namespace internal
54 /**
55  * The Google Cloud Storage (GCS) Client.
56  *
57  * This is the main class to interact with GCS. It provides member functions to
58  * invoke all the APIs in the service.
59  *
60  * @par Performance
61  * Creating an object of this type is a relatively low-cost operation.
62  * Connections to the service are created on demand. Copy-assignment and
63  * copy-construction are also relatively low-cost operations, they should be
64  * comparable to copying a few shared pointers. The first request (or any
65  * request that requires a new connection) incurs the cost of creating the
66  * connection and authenticating with the service. Note that the library may
67  * need to perform other bookeeping operations that may impact performance.
68  * For example, access tokens need to be refreshed from time to time, and this
69  * may impact the performance of some operations.
70  *
71  * @par Thread-safety
72  * Instances of this class created via copy-construction or copy-assignment
73  * share the underlying pool of connections. Access to these copies via multiple
74  * threads is guaranteed to work. Two threads operating on the same instance of
75  * this class is not guaranteed to work.
76  *
77  * @par Credentials
78  * The default approach for creating a Client uses Google Application Default
79  * %Credentials (ADCs). Because finding or loading ADCs can fail, the returned
80  * `StatusOr<Client>` from `CreateDefaultClient()` should be verified before
81  * using it. However, explicitly passing `Credentials` when creating a Client
82  * does not have the same potential to fail, so the resulting `Client` is not
83  * wrapped in a `StatusOr`.  If you wish to use `AnonymousCredentials` or to
84  * supply a specific `Credentials` type, you can use the functions declared in
85  * google_credentials.h:
86  * @code
87  * namespace gcs = google::cloud::storage;
88  *
89  * // Implicitly use ADCs:
90  * StatusOr<gcs::Client> client = gcs::Client::CreateDefaultClient();
91  * if (!client) {
92  *   // Handle failure and return.
93  * }
94  *
95  * // Or explicitly use ADCs:
96  * auto creds = gcs::oauth2::GoogleDefaultCredentials();
97  * if (!creds) {
98  *   // Handle failure and return.
99  * }
100  * // Status was OK, so create a Client with the given Credentials.
101  * gcs::Client client(gcs::ClientOptions(*creds));
102  *
103  * // Use service account credentials from a JSON keyfile:
104  * std::string path = "/path/to/keyfile.json";
105  * auto creds =
106  *     gcs::oauth2::CreateServiceAccountCredentialsFromJsonFilePath(path);
107  * if (!creds) {
108  *   // Handle failure and return.
109  * }
110  * gcs::Client client(gcs::ClientOptions(*creds));
111  *
112  * // Use Compute Engine credentials for the instance's default service account.
113  * gcs::Client client(
114  *     gcs::ClientOptions(gcs::oauth2::CreateComputeEngineCredentials()));
115  *
116  * // Use no credentials:
117  * gcs::Client client(
118  *     gcs::ClientOptions(gcs::oauth2::CreateAnonymousCredentials()));
119  * @endcode
120  *
121  * @par Error Handling
122  * This class uses `StatusOr<T>` to report errors. When an operation fails to
123  * perform its work the returned `StatusOr<T>` contains the error details. If
124  * the `ok()` member function in the `StatusOr<T>` returns `true` then it
125  * contains the expected result. Please consult the
126  * [`StatusOr<T>` documentation](#google::cloud::v1::StatusOr) for more details.
127  *
128  * @code
129  * namespace gcs = google::cloud::storage;
130  * gcs::Client client = ...;
131  * google::cloud::StatusOr<gcs::BucketMetadata> bucket_metadata =
132  *     client.GetBucketMetadata("my-bucket");
133  *
134  * if (!bucket_metadata) {
135  *   std::cerr << "Error getting metadata for my-bucket: "
136  *             << bucket_metadata.status() << "\n";
137  *   return;
138  * }
139  *
140  * // Use bucket_metadata as a smart pointer here, e.g.:
141  * std::cout << "The generation for " << bucket_metadata->name() " is "
142  *           << bucket_metadata->generation() << "\n";
143  * @endcode
144  *
145  * In addition, the @ref index "main page" contains examples using `StatusOr<T>`
146  * to handle errors.
147  *
148  * @par Retry, Backoff, and Idempotency Policies
149  *
150  * The library automatically retries requests that fail with transient errors,
151  * and follows the
152  * [recommended
153  * practice](https://cloud.google.com/storage/docs/exponential-backoff) to
154  * backoff between retries.
155  *
156  * The default policies are to continue retrying for up to 15 minutes, and to
157  * use truncated (at 5 minutes) exponential backoff, doubling the maximum
158  * backoff period between retries. Likewise, the idempotency policy is
159  * configured to retry all operations.
160  *
161  * The application can override these policies when constructing objects of this
162  * class. The documentation for the constructors show examples of this in
163  * action.
164  *
165  * @see https://cloud.google.com/storage/ for an overview of GCS.
166  *
167  * @see https://cloud.google.com/storage/docs/key-terms for an introduction of
168  *     the key terms used in GCS.
169  *
170  * @see https://cloud.google.com/storage/docs/json_api/ for an overview of the
171  *     underlying API.
172  *
173  * @see https://cloud.google.com/docs/authentication/production for details
174  *     about Application Default %Credentials.
175  *
176  * @see #google::cloud::v1::StatusOr.
177  *
178  * @see `LimitedTimeRetryPolicy` and `LimitedErrorCountRetryPolicy` for
179  * alternative retry policies.
180  *
181  * @see `ExponentialBackoffPolicy` to configure different parameters for the
182  * exponential backoff policy.
183  *
184  * @see `AlwaysRetryIdempotencyPolicy` and `StrictIdempotencyPolicy` for
185  * alternative idempotency policies.
186  */
187 class Client {
188  public:
189   /**
190    * Creates the default client type given the options.
191    *
192    * @param options the client options, these are used to control credentials,
193    *   buffer sizes, etc.
194    * @param policies the client policies, these control the behavior of the
195    *   client, for example, how to backoff when an operation needs to be
196    *   retried, or what operations cannot be retried because they are not
197    *   idempotent.
198    *
199    * @par Idempotency Policy Example
200    * @snippet storage_object_samples.cc insert object strict idempotency
201    *
202    * @par Modified Retry Policy Example
203    * @snippet storage_object_samples.cc insert object modified retry
204    */
205   template <typename... Policies>
Client(ClientOptions options,Policies &&...policies)206   explicit Client(ClientOptions options, Policies&&... policies)
207       : Client(CreateDefaultInternalClient(std::move(options)),
208                std::forward<Policies>(policies)...) {}
209 
210   /**
211    * Creates the default client type given the credentials and policies.
212    *
213    * @param credentials a set of credentials to initialize the `ClientOptions`.
214    * @param policies the client policies, these control the behavior of the
215    *   client, for example, how to backoff when an operation needs to be
216    *   retried, or what operations cannot be retried because they are not
217    *   idempotent.
218    *
219    * @par Idempotency Policy Example
220    * @snippet storage_object_samples.cc insert object strict idempotency
221    *
222    * @par Modified Retry Policy Example
223    * @snippet storage_object_samples.cc insert object modified retry
224    */
225   template <typename... Policies>
Client(std::shared_ptr<oauth2::Credentials> credentials,Policies &&...policies)226   explicit Client(std::shared_ptr<oauth2::Credentials> credentials,
227                   Policies&&... policies)
228       : Client(ClientOptions(std::move(credentials)),
229                std::forward<Policies>(policies)...) {}
230 
231   /// Builds a client and maybe override the retry, idempotency, and/or backoff
232   /// policies.
233   template <typename... Policies>
Client(std::shared_ptr<internal::RawClient> client,Policies &&...policies)234   explicit Client(std::shared_ptr<internal::RawClient> client,
235                   Policies&&... policies)
236       : raw_client_(
237             Decorate(std::move(client), std::forward<Policies>(policies)...)) {}
238 
239   /// Define a tag to disable automatic decorations of the RawClient.
240   struct NoDecorations {};
241 
242   /// Builds a client with a specific RawClient, without decorations.
Client(std::shared_ptr<internal::RawClient> client,NoDecorations)243   explicit Client(std::shared_ptr<internal::RawClient> client, NoDecorations)
244       : raw_client_(std::move(client)) {}
245 
246   /// Create a Client using ClientOptions::CreateDefaultClientOptions().
247   static StatusOr<Client> CreateDefaultClient();
248 
249   /// Access the underlying `RawClient`.
raw_client()250   std::shared_ptr<internal::RawClient> raw_client() const {
251     return raw_client_;
252   }
253 
254   //@{
255   /**
256    * @name Bucket operations.
257    *
258    * Buckets are the basic containers that hold your data. Everything that you
259    * store in GCS must be contained in a bucket. You can use buckets to organize
260    * your data and control access to your data, but unlike directories and
261    * folders, you cannot nest buckets.
262    *
263    * @see https://cloud.google.com/storage/docs/key-terms#buckets for more
264    * information about GCS buckets.
265    */
266   /**
267    * Fetches the list of buckets for a given project.
268    *
269    * @param project_id the project to query.
270    * @param options a list of optional query parameters and/or request headers.
271    *     Valid types for this operation include `MaxResults`, `Prefix`,
272    *     `UserProject`, and `Projection`.
273    *
274    * @par Idempotency
275    * This is a read-only operation and is always idempotent.
276    *
277    * @par Example
278    * @snippet storage_bucket_samples.cc list buckets for project
279    */
280   template <typename... Options>
ListBucketsForProject(std::string const & project_id,Options &&...options)281   ListBucketsReader ListBucketsForProject(std::string const& project_id,
282                                           Options&&... options) {
283     internal::ListBucketsRequest request(project_id);
284     request.set_multiple_options(std::forward<Options>(options)...);
285     auto client = raw_client_;
286     return google::cloud::internal::MakePaginationRange<ListBucketsReader>(
287         request,
288         [client](internal::ListBucketsRequest const& r) {
289           return client->ListBuckets(r);
290         },
291         [](internal::ListBucketsResponse r) { return std::move(r.items); });
292   }
293 
294   /**
295    * Fetches the list of buckets for the default project.
296    *
297    * The default project is required to be configured in the `ClientOptions`
298    * used to construct this object. If the application does not set the project
299    * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
300    * used. If neither the environment variable is set, nor a value is set
301    * explicitly by the application, the returned `ListBucketsReader` will
302    * return an error status when used.
303    *
304    * @param options a list of optional query parameters and/or request headers.
305    *     Valid types for this operation include `MaxResults`, `Prefix`,
306    *     `UserProject`, and `Projection`.
307    *
308    * @par Idempotency
309    * This is a read-only operation and is always idempotent.
310    *
311    * @par Example
312    * @snippet storage_bucket_samples.cc list buckets
313    */
314   template <typename... Options>
ListBuckets(Options &&...options)315   ListBucketsReader ListBuckets(Options&&... options) {
316     auto const& project_id = raw_client_->client_options().project_id();
317     return ListBucketsForProject(project_id, std::forward<Options>(options)...);
318   }
319 
320   /**
321    * Creates a new Google Cloud Storage bucket using the default project. If
322    * the default project is not configured the server will reject the request,
323    * and this function returns the error status.
324    *
325    * @param bucket_name the name of the new bucket.
326    * @param metadata the metadata for the new Bucket.  The `name` field is
327    *     ignored in favor of @p bucket_name.
328    * @param options a list of optional query parameters and/or request headers.
329    *     Valid types for this operation include `PredefinedAcl`,
330    *     `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
331    *
332    * @par Idempotency
333    * This operation is always idempotent. It fails if the bucket already exists.
334    *
335    * @par Example
336    * @snippet storage_bucket_samples.cc create bucket
337    *
338    * @see Before enabling Uniform Bucket Level Access please review the
339    *     [feature documentation][ubla-link], as well as
340    *     ["Should you use uniform bucket-level access ?"][ubla-should-link].
341    *
342    * [ubla-link]:
343    * https://cloud.google.com/storage/docs/uniform-bucket-level-access
344    * [ubla-should-link]:
345    * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
346    */
347   template <typename... Options>
CreateBucket(std::string bucket_name,BucketMetadata metadata,Options &&...options)348   StatusOr<BucketMetadata> CreateBucket(std::string bucket_name,
349                                         BucketMetadata metadata,
350                                         Options&&... options) {
351     auto const& project_id = raw_client_->client_options().project_id();
352     return CreateBucketForProject(std::move(bucket_name), project_id,
353                                   std::move(metadata),
354                                   std::forward<Options>(options)...);
355   }
356 
357   /**
358    * Creates a new Google Cloud Storage Bucket in a given project.
359    *
360    * @param bucket_name the name of the new bucket.
361    * @param project_id the id of the project that will host the new bucket.
362    * @param metadata the metadata for the new Bucket.  The `name` field is
363    *     ignored in favor of @p bucket_name.
364    * @param options a list of optional query parameters and/or request headers.
365    *     Valid types for this operation include `PredefinedAcl`,
366    *     `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
367    *
368    * @par Idempotency
369    * This operation is always idempotent. It fails if the bucket already exists.
370    *
371    * @par Example
372    * @snippet storage_bucket_samples.cc create bucket for project
373    *
374    * @see Before enabling Uniform Bucket Level Access please review the
375    *     [feature documentation][ubla-link], as well as
376    *     ["Should you use uniform bucket-level access ?"][ubla-should-link].
377    *
378    * [ubla-link]:
379    * https://cloud.google.com/storage/docs/uniform-bucket-level-access
380    * [ubla-should-link]:
381    * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
382    */
383   template <typename... Options>
CreateBucketForProject(std::string bucket_name,std::string project_id,BucketMetadata metadata,Options &&...options)384   StatusOr<BucketMetadata> CreateBucketForProject(std::string bucket_name,
385                                                   std::string project_id,
386                                                   BucketMetadata metadata,
387                                                   Options&&... options) {
388     metadata.set_name(std::move(bucket_name));
389     internal::CreateBucketRequest request(std::move(project_id),
390                                           std::move(metadata));
391     request.set_multiple_options(std::forward<Options>(options)...);
392     return raw_client_->CreateBucket(request);
393   }
394 
395   /**
396    * Fetches the bucket metadata.
397    *
398    * @param bucket_name query metadata information about this bucket.
399    * @param options a list of optional query parameters and/or request headers.
400    *     Valid types for this operation include `IfMetagenerationMatch`,
401    *     `IfMetagenerationNotMatch`, `UserProject`, and `Projection`.
402    *
403    * @par Idempotency
404    * This is a read-only operation and is always idempotent.
405    *
406    * @par Example
407    * @snippet storage_bucket_samples.cc get bucket metadata
408    */
409   template <typename... Options>
GetBucketMetadata(std::string const & bucket_name,Options &&...options)410   StatusOr<BucketMetadata> GetBucketMetadata(std::string const& bucket_name,
411                                              Options&&... options) {
412     internal::GetBucketMetadataRequest request(bucket_name);
413     request.set_multiple_options(std::forward<Options>(options)...);
414     return raw_client_->GetBucketMetadata(request);
415   }
416 
417   /**
418    * Deletes a Google Cloud Storage Bucket.
419    *
420    * @param bucket_name the bucket to be deleted.
421    * @param options a list of optional query parameters and/or request headers.
422    *     Valid types for this operation include `IfMetagenerationMatch`,
423    *     `IfMetagenerationNotMatch`, and `UserProject`.
424    *
425    * @par Idempotency
426    * This operation is only idempotent if restricted by pre-conditions, in this
427    * case, `IfMetagenerationMatch`.
428    *
429    * @par Example
430    * @snippet storage_bucket_samples.cc delete bucket
431    */
432   template <typename... Options>
DeleteBucket(std::string const & bucket_name,Options &&...options)433   Status DeleteBucket(std::string const& bucket_name, Options&&... options) {
434     internal::DeleteBucketRequest request(bucket_name);
435     request.set_multiple_options(std::forward<Options>(options)...);
436     return raw_client_->DeleteBucket(request).status();
437   }
438 
439   /**
440    * Updates the metadata in a Google Cloud Storage Bucket.
441    *
442    * A `Buckets: update` request changes *all* the writeable attributes of a
443    * bucket, in contrast, a `Buckets: patch` request only changes the subset of
444    * the attributes included in the request. This function creates a
445    * `Buckets: update` request to change the writable attributes in
446    * `BucketMetadata`.
447    *
448    * @param bucket_name the name of the new bucket.
449    * @param metadata the new metadata for the Bucket.  The `name` field is
450    *     ignored in favor of @p bucket_name.
451    * @param options a list of optional query parameters and/or request headers.
452    *     Valid types for this operation include `IfMetagenerationMatch`,
453    *     `IfMetagenerationNotMatch`, `PredefinedAcl`,
454    *     `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
455    *
456    * @par Idempotency
457    * This operation is only idempotent if restricted by pre-conditions, in this
458    * case,`IfMetagenerationMatch`.
459    *
460    * @par Example
461    * @snippet storage_bucket_samples.cc update bucket
462    *
463    * @see Before enabling Uniform Bucket Level Access please review the
464    *     [feature documentation][ubla-link], as well as
465    *     ["Should you use uniform bucket-level access ?"][ubla-should-link].
466    *
467    * [ubla-link]:
468    * https://cloud.google.com/storage/docs/uniform-bucket-level-access
469    * [ubla-should-link]:
470    * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
471    */
472   template <typename... Options>
UpdateBucket(std::string bucket_name,BucketMetadata metadata,Options &&...options)473   StatusOr<BucketMetadata> UpdateBucket(std::string bucket_name,
474                                         BucketMetadata metadata,
475                                         Options&&... options) {
476     metadata.set_name(std::move(bucket_name));
477     internal::UpdateBucketRequest request(std::move(metadata));
478     request.set_multiple_options(std::forward<Options>(options)...);
479     return raw_client_->UpdateBucket(request);
480   }
481 
482   /**
483    * Computes the difference between two BucketMetadata objects and patches a
484    * bucket based on that difference.
485    *
486    * A `Buckets: update` request changes *all* the writeable attributes of a
487    * bucket, in contrast, a `Buckets: patch` request only changes the subset of
488    * the attributes included in the request.
489    *
490    * This function creates a patch request to change the writeable attributes in
491    * @p original to the values in @p updated.  Non-writeable attributes are
492    * ignored, and attributes not present in @p updated are removed. Typically
493    * this function is used after the application obtained a value with
494    * `GetBucketMetadata` and has modified these parameters.
495    *
496    * @param bucket_name the bucket to be updated.
497    * @param original the initial value of the bucket metadata.
498    * @param updated the updated value for the bucket metadata.
499    * @param options a list of optional query parameters and/or request headers.
500    *     Valid types for this operation include `IfMetagenerationMatch`,
501    *     `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
502    *
503    * @par Idempotency
504    * This operation is only idempotent if restricted by pre-conditions, in this
505    * case, `IfMetagenerationMatch`.
506    *
507    * @par Example
508    * @snippet storage_bucket_samples.cc patch bucket storage class
509    *
510    * @see Before enabling Uniform Bucket Level Access please review the
511    *     [feature documentation][ubla-link], as well as
512    *     ["Should you use uniform bucket-level access?"][ubla-should-link].
513    *
514    * [ubla-link]:
515    * https://cloud.google.com/storage/docs/uniform-bucket-level-access
516    * [ubla-should-link]:
517    * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
518    */
519   template <typename... Options>
PatchBucket(std::string bucket_name,BucketMetadata const & original,BucketMetadata const & updated,Options &&...options)520   StatusOr<BucketMetadata> PatchBucket(std::string bucket_name,
521                                        BucketMetadata const& original,
522                                        BucketMetadata const& updated,
523                                        Options&&... options) {
524     internal::PatchBucketRequest request(std::move(bucket_name), original,
525                                          updated);
526     request.set_multiple_options(std::forward<Options>(options)...);
527     return raw_client_->PatchBucket(request);
528   }
529 
530   /**
531    * Patches the metadata in a Google Cloud Storage Bucket given a desired set
532    * changes.
533    *
534    * A `Buckets: update` request changes *all* the writeable attributes of a
535    * bucket, in contrast, a `Buckets: patch` request only changes the subset of
536    * the attributes included in the request. This function creates a patch
537    * request based on the given `BucketMetadataPatchBuilder` which represents
538    * the desired set of changes.
539    *
540    * @param bucket_name the bucket to be updated.
541    * @param builder the set of updates to perform in the Bucket.
542    * @param options a list of optional query parameters and/or request headers.
543    *     Valid types for this operation include `IfMetagenerationMatch`,
544    *     `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
545    *
546    * @par Idempotency
547    * This operation is only idempotent if restricted by pre-conditions, in this
548    * case, `IfMetagenerationMatch`.
549    *
550    * @par Example
551    * @snippet storage_bucket_samples.cc patch bucket storage class with builder
552    *
553    * @see Before enabling Uniform Bucket Level Access please review the
554    *     [feature documentation][ubla-link], as well as
555    *     ["Should you use uniform bucket-level access ?"][ubla-should-link].
556    *
557    * [ubla-link]:
558    * https://cloud.google.com/storage/docs/uniform-bucket-level-access
559    * [ubla-should-link]:
560    * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
561    */
562   template <typename... Options>
PatchBucket(std::string bucket_name,BucketMetadataPatchBuilder const & builder,Options &&...options)563   StatusOr<BucketMetadata> PatchBucket(
564       std::string bucket_name, BucketMetadataPatchBuilder const& builder,
565       Options&&... options) {
566     internal::PatchBucketRequest request(std::move(bucket_name), builder);
567     request.set_multiple_options(std::forward<Options>(options)...);
568     return raw_client_->PatchBucket(request);
569   }
570 
571   /**
572    * Fetches the [IAM policy](@ref google::cloud::v1::IamPolicy) for a Bucket.
573    *
574    * Google Cloud Identity & Access Management (IAM) lets administrators
575    * authorize who can take action on specific resources, including Google
576    * Cloud Storage Buckets. This operation allows you to query the IAM policies
577    * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
578    * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
579    * documentation describes
580    * [the
581    * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
582    * between legacy Bucket ACLs and IAM policies.
583    *
584    * Consult
585    * [the
586    * documentation](https://cloud.google.com/storage/docs/access-control/iam)
587    * for a more detailed description of IAM policies and their use in
588    * Google Cloud Storage.
589    *
590    * @param bucket_name query metadata information about this bucket.
591    * @param options a list of optional query parameters and/or request headers.
592    *     Valid types for this operation include `UserProject`.
593    *
594    * @deprecated this function is deprecated; it doesn't support conditional
595    *     bindings and will not support any other features to come; please use
596    *     `GetNativeBucketIamPolicy` instead.
597    *     TODO(#2857): Use proper deprecation attributes.
598    *
599    * @par Idempotency
600    * This is a read-only operation and is always idempotent.
601    *
602    * @par Example
603    * @snippet storage_bucket_iam_samples.cc get bucket iam policy
604    *
605    * @see #google::cloud::v1::IamPolicy for details about the `IamPolicy` class.
606    */
607   template <typename... Options>
GetBucketIamPolicy(std::string const & bucket_name,Options &&...options)608   StatusOr<IamPolicy> GetBucketIamPolicy(std::string const& bucket_name,
609                                          Options&&... options) {
610     internal::GetBucketIamPolicyRequest request(bucket_name);
611     request.set_multiple_options(std::forward<Options>(options)...);
612     return raw_client_->GetBucketIamPolicy(request);
613   }
614 
615   /**
616    * Fetches the native [IAM policy](@ref google::cloud::v1::IamPolicy) for a
617    * Bucket.
618    *
619    * Google Cloud Identity & Access Management (IAM) lets administrators
620    * authorize who can take action on specific resources, including Google
621    * Cloud Storage Buckets. This operation allows you to query the IAM policies
622    * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
623    * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
624    * documentation describes
625    * [the
626    * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
627    * between legacy Bucket ACLs and IAM policies.
628    *
629    * Consult
630    * [the
631    * documentation](https://cloud.google.com/storage/docs/access-control/iam)
632    * for a more detailed description of IAM policies and their use in
633    * Google Cloud Storage.
634    *
635    * @param bucket_name query metadata information about this bucket.
636    * @param options a list of optional query parameters and/or request headers.
637    *     Valid types for this operation include `UserProject`.
638    *
639    * @par Idempotency
640    * This is a read-only operation and is always idempotent.
641    *
642    * @par Example
643    * @snippet storage_bucket_iam_samples.cc native get bucket iam policy
644    *
645    * @see #google::cloud::v1::IamPolicy for details about the `IamPolicy` class.
646    */
647   template <typename... Options>
GetNativeBucketIamPolicy(std::string const & bucket_name,Options &&...options)648   StatusOr<NativeIamPolicy> GetNativeBucketIamPolicy(
649       std::string const& bucket_name, Options&&... options) {
650     internal::GetBucketIamPolicyRequest request(bucket_name);
651     request.set_multiple_options(std::forward<Options>(options)...);
652     return raw_client_->GetNativeBucketIamPolicy(request);
653   }
654 
655   /**
656    * Sets the [IAM Policy](@ref google::cloud::v1::IamPolicy) for a Bucket.
657    *
658    * Google Cloud Identity & Access Management (IAM) lets administrators
659    * authorize who can take action on specific resources, including Google
660    * Cloud Storage Buckets. This operation allows you to set the IAM policies
661    * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
662    * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
663    * documentation describes
664    * [the
665    * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
666    * between legacy Bucket ACLs and IAM policies.
667    *
668    * Consult
669    * [the
670    * documentation](https://cloud.google.com/storage/docs/access-control/iam)
671    * for a more detailed description of IAM policies their use in
672    * Google Cloud Storage.
673    *
674    * @note The server rejects requests where the ETag value of the policy does
675    *   not match the current ETag. Effectively this means that applications must
676    *   use `GetBucketIamPolicy()` to fetch the current value and ETag before
677    *   calling `SetBucketIamPolicy()`. Applications should use optimistic
678    *   concurrency control techniques to retry changes in case some other
679    *   application modified the IAM policy between the `GetBucketIamPolicy`
680    *   and `SetBucketIamPolicy` calls.
681    *
682    * @param bucket_name query metadata information about this bucket.
683    * @param iam_policy the new IAM policy.
684    * @param options a list of optional query parameters and/or request headers.
685    *     Valid types for this operation include `UserProject`.
686    *
687    * @par Idempotency
688    * This operation is only idempotent if restricted by pre-conditions, in this
689    * case, `IfMetagenerationMatch`.
690    *
691    * @deprecated this function is deprecated; it doesn't support conditional
692    *     bindings and will not support any other features to come; please use
693    *     `SetNativeBucketIamPolicy` instead.
694    *     TODO(#2857): Use proper deprecation attributes.
695    *
696    * @par Example: adding a new member
697    * @snippet storage_bucket_iam_samples.cc add bucket iam member
698    *
699    * @par Example: removing a IAM member
700    * @snippet storage_bucket_iam_samples.cc remove bucket iam member
701    *
702    * @see #google::cloud::v1::IamPolicy for details about the `IamPolicy` class.
703    */
704   template <typename... Options>
SetBucketIamPolicy(std::string const & bucket_name,IamPolicy const & iam_policy,Options &&...options)705   StatusOr<IamPolicy> SetBucketIamPolicy(std::string const& bucket_name,
706                                          IamPolicy const& iam_policy,
707                                          Options&&... options) {
708     internal::SetBucketIamPolicyRequest request(bucket_name, iam_policy);
709     request.set_multiple_options(std::forward<Options>(options)...);
710     return raw_client_->SetBucketIamPolicy(request);
711   }
712 
713   /**
714    * Sets the native [IAM Policy](@ref google::cloud::v1::IamPolicy) for a
715    * Bucket.
716    *
717    * Google Cloud Identity & Access Management (IAM) lets administrators
718    * authorize who can take action on specific resources, including Google
719    * Cloud Storage Buckets. This operation allows you to set the IAM policies
720    * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
721    * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
722    * documentation describes
723    * [the
724    * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
725    * between legacy Bucket ACLs and IAM policies.
726    *
727    * Consult
728    * [the
729    * documentation](https://cloud.google.com/storage/docs/access-control/iam)
730    * for a more detailed description of IAM policies their use in
731    * Google Cloud Storage.
732    *
733    * @note The server rejects requests where the ETag value of the policy does
734    *   not match the current ETag. Effectively this means that applications must
735    *   use `GetBucketIamPolicy()` to fetch the current value and ETag before
736    *   calling `SetBucketIamPolicy()`. Applications should use optimistic
737    *   concurrency control techniques to retry changes in case some other
738    *   application modified the IAM policy between the `GetBucketIamPolicy`
739    *   and `SetBucketIamPolicy` calls.
740    *
741    * @param bucket_name query metadata information about this bucket.
742    * @param iam_policy the new IAM policy.
743    * @param options a list of optional query parameters and/or request headers.
744    *     Valid types for this operation include `UserProject`.
745    *
746    * @par Idempotency
747    * This operation is only idempotent if restricted by pre-conditions, in this
748    * case, `IfMetagenerationMatch`.
749    *
750    * @par Example: adding a new member
751    * @snippet storage_bucket_iam_samples.cc native add bucket iam member
752    *
753    * @par Example: removing a IAM member
754    * @snippet storage_bucket_iam_samples.cc native remove bucket iam member
755    *
756    * @see #google::cloud::v1::IamPolicy for details about the `IamPolicy` class.
757    */
758   template <typename... Options>
SetNativeBucketIamPolicy(std::string const & bucket_name,NativeIamPolicy const & iam_policy,Options &&...options)759   StatusOr<NativeIamPolicy> SetNativeBucketIamPolicy(
760       std::string const& bucket_name, NativeIamPolicy const& iam_policy,
761       Options&&... options) {
762     internal::SetNativeBucketIamPolicyRequest request(bucket_name, iam_policy);
763     request.set_multiple_options(std::forward<Options>(options)...);
764     return raw_client_->SetNativeBucketIamPolicy(request);
765   }
766 
767   /**
768    * Tests the IAM permissions of the caller against a Bucket.
769    *
770    * Google Cloud Identity & Access Management (IAM) lets administrators
771    * authorize who can take action on specific resources, including Google
772    * Cloud Storage Buckets. This operation tests the permissions of the caller
773    * for a Bucket. You must provide a list of permissions, this API will return
774    * the subset of those permissions that the current caller has in the given
775    * Bucket.
776    *
777    * Consult
778    * [the
779    * documentation](https://cloud.google.com/storage/docs/access-control/iam)
780    * for a more detailed description of IAM policies their use in
781    * Google Cloud Storage.
782    *
783    * @param bucket_name query metadata information about this bucket.
784    * @param permissions the list of permissions to check.
785    * @param options a list of optional query parameters and/or request headers.
786    *     Valid types for this operation include `UserProject`.
787    *
788    * @par Idempotency
789    * This is a read-only operation and is always idempotent.
790    *
791    * @par Example
792    * @snippet storage_bucket_iam_samples.cc test bucket iam permissions
793    */
794   template <typename... Options>
TestBucketIamPermissions(std::string bucket_name,std::vector<std::string> permissions,Options &&...options)795   StatusOr<std::vector<std::string>> TestBucketIamPermissions(
796       std::string bucket_name, std::vector<std::string> permissions,
797       Options&&... options) {
798     internal::TestBucketIamPermissionsRequest request(std::move(bucket_name),
799                                                       std::move(permissions));
800     request.set_multiple_options(std::forward<Options>(options)...);
801     auto result = raw_client_->TestBucketIamPermissions(request);
802     if (!result) {
803       return std::move(result).status();
804     }
805     return std::move(result.value().permissions);
806   }
807 
808   /**
809    * Locks the retention policy for a bucket.
810    *
811    * @warning Locking a retention policy is an irreversible action. Once locked,
812    *     you must delete the entire bucket in order to "remove" the bucket's
813    *     retention policy. However, before you can delete the bucket, you must
814    *     be able to delete all the objects in the bucket, which itself is only
815    *     possible if all the objects have reached the retention period set by
816    *     the retention policy.
817    *
818    * The [Bucket Lock
819    * feature](https://cloud.google.com/storage/docs/bucket-lock) allows you to
820    * configure a data retention policy for a Cloud Storage bucket that governs
821    * how long objects in the bucket must be retained. The feature also allows
822    * you to lock the data retention policy, permanently preventing the policy
823    * from being reduced or removed.
824    *
825    * @param bucket_name the name of the bucket.
826    * @param metageneration the expected value of the metageneration on the
827    *     bucket. The request will fail if the metageneration does not match the
828    *     current value.
829    * @param options a list of optional query parameters and/or request headers.
830    *     Valid types for this operation include `UserProject`.
831    *
832    * @par Idempotency
833    * This operation is always idempotent because the `metageneration` parameter
834    * is always required, and it acts as a pre-condition on the operation.
835    *
836    * @par Example: lock the retention policy
837    * @snippet storage_retention_policy_samples.cc lock retention policy
838    *
839    * @par Example: get the current retention policy
840    * @snippet storage_retention_policy_samples.cc get retention policy
841    *
842    * @par Example: set the current retention policy
843    * @snippet storage_retention_policy_samples.cc set retention policy
844    *
845    * @par Example: remove the retention policy
846    * @snippet storage_retention_policy_samples.cc remove retention policy
847    *
848    * @see https://cloud.google.com/storage/docs/bucket-lock for a description of
849    *     the Bucket Lock feature.
850    *
851    * @see https://cloud.google.com/storage/docs/using-bucket-lock for examples
852    *     of how to use the Bucket Lock and retention policy features.
853    */
854   template <typename... Options>
LockBucketRetentionPolicy(std::string const & bucket_name,std::uint64_t metageneration,Options &&...options)855   StatusOr<BucketMetadata> LockBucketRetentionPolicy(
856       std::string const& bucket_name, std::uint64_t metageneration,
857       Options&&... options) {
858     internal::LockBucketRetentionPolicyRequest request(bucket_name,
859                                                        metageneration);
860     request.set_multiple_options(std::forward<Options>(options)...);
861     return raw_client_->LockBucketRetentionPolicy(request);
862   }
863   //@}
864 
865   //@{
866   /**
867    * @name Object operations
868    *
869    * Objects are the individual pieces of data that you store in GCS. Objects
870    * have two components: *object data* and *object metadata*. Object data
871    * (sometimes referred to as *media*) is typically a file that you want
872    * to store in GCS. Object metadata is information that describe various
873    * object qualities.
874    *
875    * @see https://cloud.google.com/storage/docs/key-terms#objects for more
876    * information about GCS objects.
877    */
878   /**
879    * Creates an object given its name and contents.
880    *
881    * @param bucket_name the name of the bucket that will contain the object.
882    * @param object_name the name of the object to be created.
883    * @param contents the contents (media) for the new object.
884    * @param options a list of optional query parameters and/or request headers.
885    *     Valid types for this operation include `ContentEncoding`,
886    *     `ContentType`, `Crc32cChecksumValue`, `DisableCrc32cChecksum`,
887    *     `DisableMD5Hash`, `EncryptionKey`, `IfGenerationMatch`,
888    *     `IfGenerationNotMatch`, `IfMetagenerationMatch`,
889    *     `IfMetagenerationNotMatch`, `KmsKeyName`, `MD5HashValue`,
890    *     `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
891    *
892    * @par Idempotency
893    * This operation is only idempotent if restricted by pre-conditions, in this
894    * case, `IfGenerationMatch`.
895    *
896    * @par Example
897    * @snippet storage_object_samples.cc insert object
898    *
899    * @par Example
900    * @snippet storage_object_samples.cc insert object multipart
901    */
902   template <typename... Options>
InsertObject(std::string const & bucket_name,std::string const & object_name,std::string contents,Options &&...options)903   StatusOr<ObjectMetadata> InsertObject(std::string const& bucket_name,
904                                         std::string const& object_name,
905                                         std::string contents,
906                                         Options&&... options) {
907     internal::InsertObjectMediaRequest request(bucket_name, object_name,
908                                                std::move(contents));
909     request.set_multiple_options(std::forward<Options>(options)...);
910     return raw_client_->InsertObjectMedia(request);
911   }
912 
913   /**
914    * Copies an existing object.
915    *
916    * Use `CopyObject` to copy between objects in the same location and storage
917    * class.  Copying objects across locations or storage classes can fail for
918    * large objects and retrying the operation will not succeed.
919    *
920    * @note Prefer using `RewriteObject()` to copy objects, `RewriteObject()` can
921    *     copy objects to different locations, with different storage class,
922    *     and/or with different encryption keys.
923    *
924    * @param source_bucket_name the name of the bucket that contains the object
925    *     to be copied.
926    * @param source_object_name the name of the object to copy.
927    * @param destination_bucket_name the name of the bucket that will contain the
928    *     new object.
929    * @param destination_object_name the name of the new object.
930    * @param options a list of optional query parameters and/or request headers.
931    *     Valid types for this operation include `DestinationPredefinedAcl`,
932    *     `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
933    *     `IfMetagenerationMatch`, `IfMetagenerationNotMatch`,
934    *     `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
935    *     `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
936    *     `Projection`, `SourceGeneration`, `UserProject`, and
937    *     `WithObjectMetadata`.
938    *
939    * @par Idempotency
940    * This operation is only idempotent if restricted by pre-conditions, in this
941    * case, `IfGenerationMatch`.
942    *
943    * @par Example
944    * @snippet storage_object_samples.cc copy object
945    *
946    * @par Example: copy an encrypted object
947    * @snippet storage_object_csek_samples.cc copy encrypted object
948    *
949    * @see https://cloud.google.com/storage/docs/json_api/v1/objects/copy for
950    *   a full description of the advantages of `Objects: rewrite` over
951    *   `Objects: copy`.
952    */
953   template <typename... Options>
CopyObject(std::string source_bucket_name,std::string source_object_name,std::string destination_bucket_name,std::string destination_object_name,Options &&...options)954   StatusOr<ObjectMetadata> CopyObject(std::string source_bucket_name,
955                                       std::string source_object_name,
956                                       std::string destination_bucket_name,
957                                       std::string destination_object_name,
958                                       Options&&... options) {
959     internal::CopyObjectRequest request(
960         std::move(source_bucket_name), std::move(source_object_name),
961         std::move(destination_bucket_name), std::move(destination_object_name));
962     request.set_multiple_options(std::forward<Options>(options)...);
963     return raw_client_->CopyObject(request);
964   }
965 
966   /**
967    * Fetches the object metadata.
968    *
969    * @param bucket_name the bucket containing the object.
970    * @param object_name the object name.
971    * @param options a list of optional query parameters and/or request headers.
972    *     Valid types for this operation include `Generation`,
973    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
974    *     `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
975    *
976    * @par Idempotency
977    * This is a read-only operation and is always idempotent.
978    *
979    * @par Example
980    * @snippet storage_object_samples.cc get object metadata
981    */
982   template <typename... Options>
GetObjectMetadata(std::string const & bucket_name,std::string const & object_name,Options &&...options)983   StatusOr<ObjectMetadata> GetObjectMetadata(std::string const& bucket_name,
984                                              std::string const& object_name,
985                                              Options&&... options) {
986     internal::GetObjectMetadataRequest request(bucket_name, object_name);
987     request.set_multiple_options(std::forward<Options>(options)...);
988     return raw_client_->GetObjectMetadata(request);
989   }
990 
991   /**
992    * Lists the objects in a bucket.
993    *
994    * @param bucket_name the name of the bucket to list.
995    * @param options a list of optional query parameters and/or request headers.
996    *     Valid types for this operation include
997    *     `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `UserProject`,
998    *     `Projection`, `Prefix`, `Delimiter`, `StartOffset`, `EndOffset`, and
999    *     `Versions`.
1000    *
1001    * @par Idempotency
1002    * This is a read-only operation and is always idempotent.
1003    *
1004    * @par Example
1005    * @snippet storage_object_samples.cc list objects
1006    */
1007   template <typename... Options>
ListObjects(std::string const & bucket_name,Options &&...options)1008   ListObjectsReader ListObjects(std::string const& bucket_name,
1009                                 Options&&... options) {
1010     internal::ListObjectsRequest request(bucket_name);
1011     request.set_multiple_options(std::forward<Options>(options)...);
1012     auto client = raw_client_;
1013     return google::cloud::internal::MakePaginationRange<ListObjectsReader>(
1014         request,
1015         [client](internal::ListObjectsRequest const& r) {
1016           return client->ListObjects(r);
1017         },
1018         [](internal::ListObjectsResponse r) { return std::move(r.items); });
1019   }
1020 
1021   /**
1022    * Lists the objects and prefixes in a bucket.
1023    *
1024    * @param bucket_name the name of the bucket to list.
1025    * @param options a list of optional query parameters and/or request headers.
1026    *     Valid types for this operation include
1027    *     `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `UserProject`,
1028    *     `Projection`, `Prefix`, `Delimiter`, `StartOffset`, `EndOffset`, and
1029    *     `Versions`.
1030    *
1031    * @par Idempotency
1032    * This is a read-only operation and is always idempotent.
1033    *
1034    * @par Example
1035    * @snippet storage_object_samples.cc list objects and prefixes
1036    */
1037   template <typename... Options>
ListObjectsAndPrefixes(std::string const & bucket_name,Options &&...options)1038   ListObjectsAndPrefixesReader ListObjectsAndPrefixes(
1039       std::string const& bucket_name, Options&&... options) {
1040     internal::ListObjectsRequest request(bucket_name);
1041     request.set_multiple_options(std::forward<Options>(options)...);
1042     auto client = raw_client_;
1043     return google::cloud::internal::MakePaginationRange<
1044         ListObjectsAndPrefixesReader>(
1045         request,
1046         [client](internal::ListObjectsRequest const& r) {
1047           return client->ListObjects(r);
1048         },
1049         [](internal::ListObjectsResponse r) {
1050           std::vector<ObjectOrPrefix> result;
1051           for (auto& item : r.items) {
1052             result.emplace_back(std::move(item));
1053           }
1054           for (auto& prefix : r.prefixes) {
1055             result.emplace_back(std::move(prefix));
1056           }
1057           internal::SortObjectsAndPrefixes(result);
1058           return result;
1059         });
1060   }
1061 
1062   /**
1063    * Reads the contents of an object.
1064    *
1065    * Returns an object derived from `std::istream` which can be used to read the
1066    * contents of the GCS blob. The application should check the `badbit` (e.g.
1067    * by calling `stream.bad()`) on the returned object to detect if there was
1068    * an error reading from the blob. If `badbit` is set, the application can
1069    * check the `status()` variable to get details about the failure.
1070    * Applications can also set the exception mask on the returned stream, in
1071    * which case an exception is thrown if an error is detected.
1072    *
1073    * @param bucket_name the name of the bucket that contains the object.
1074    * @param object_name the name of the object to be read.
1075    * @param options a list of optional query parameters and/or request headers.
1076    *     Valid types for this operation include `DisableCrc32cChecksum`,
1077    *     `DisableMD5Hash`, `IfGenerationMatch`, `EncryptionKey`, `Generation`,
1078    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1079    *     `IfMetagenerationNotMatch`, `ReadFromOffset`, `ReadRange`, `ReadLast`
1080    *     and `UserProject`.
1081    *
1082    * @par Idempotency
1083    * This is a read-only operation and is always idempotent.
1084    *
1085    * @par Example
1086    * @snippet storage_object_samples.cc read object
1087    *
1088    * @par Example
1089    * @snippet storage_object_samples.cc read object range
1090    *
1091    * @par Example: read a object encrypted with a CSEK.
1092    * @snippet storage_object_csek_samples.cc read encrypted object
1093    */
1094   template <typename... Options>
ReadObject(std::string const & bucket_name,std::string const & object_name,Options &&...options)1095   ObjectReadStream ReadObject(std::string const& bucket_name,
1096                               std::string const& object_name,
1097                               Options&&... options) {
1098     struct HasReadRange
1099         : public absl::disjunction<std::is_same<ReadRange, Options>...> {};
1100     struct HasReadFromOffset
1101         : public absl::disjunction<std::is_same<ReadFromOffset, Options>...> {};
1102     struct HasReadLast
1103         : public absl::disjunction<std::is_same<ReadLast, Options>...> {};
1104 
1105     struct HasIncompatibleRangeOptions
1106         : public std::integral_constant<bool, HasReadLast::value &&
1107                                                   (HasReadFromOffset::value ||
1108                                                    HasReadRange::value)> {};
1109 
1110     static_assert(!HasIncompatibleRangeOptions::value,
1111                   "Cannot set ReadLast option with either ReadFromOffset or "
1112                   "ReadRange.");
1113 
1114     internal::ReadObjectRangeRequest request(bucket_name, object_name);
1115     request.set_multiple_options(std::forward<Options>(options)...);
1116     return ReadObjectImpl(request);
1117   }
1118 
1119   /**
1120    * Writes contents into an object.
1121    *
1122    * This creates a `std::ostream` object to upload contents. The application
1123    * can use either the regular `operator<<()`, or `std::ostream::write()` to
1124    * upload data.
1125    *
1126    * This function always uses [resumable uploads][resumable-link]. The
1127    * application can provide a `#RestoreResumableUploadSession()` option to
1128    * resume a previously created upload. The returned object has accessors to
1129    * query the session id and the next byte expected by GCS.
1130    *
1131    * @note When resuming uploads it is the application's responsibility to save
1132    *     the session id to restart the upload later. Likewise, it is the
1133    *     application's responsibility to query the next expected byte and send
1134    *     the remaining data without gaps or duplications.
1135    *
1136    * For small uploads we recommend using `InsertObject`, consult
1137    * [the documentation][how-to-upload-link] for details.
1138    *
1139    * If the application does not provide a `#RestoreResumableUploadSession()`
1140    * option, or it provides the `#NewResumableUploadSession()` option then a new
1141    * resumable upload session is created.
1142    *
1143    * To perform efficient uploads applications should consider using unbuffered
1144    * I/O operations on the returned stream (aka `std::ostream::write()`).
1145    * Application developers should consider the following properties of
1146    * resumable uploads to use this API efficiently:
1147    *
1148    * - Resumable uploads are performed in "chunks" sent to GCS, these chunks
1149    *   are committed and saved at least until the session is deleted (or garbage
1150    *   collected, approximately after 7 days.)
1151    * - The size of these chunks (except the last one) must be a multiple of the
1152    *   upload quantum (256KiB).
1153    * - Uploading a chunk that is not a multiple of the quantum implicitly
1154    *   finalizes the upload.
1155    *
1156    * The library, therefore, *must* buffer any data that does not fill a full
1157    * quantum. If you are interested in avoiding data copies you should always
1158    * provide the library with buffers that fit in this quantum.
1159    *
1160    * In addition, applications should consider providing large buffers as the
1161    * library waits until GCS confirms that the chunk is uploaded before
1162    * returning control to the application. Naturally there is a tradeoff between
1163    * copying data to prepare large buffers vs. sending many small buffers and
1164    * paying the network costs for each.  We recommend that you use buffers in
1165    * the 16MiB to 64MiB range for best performance.
1166    *
1167    * @param bucket_name the name of the bucket that contains the object.
1168    * @param object_name the name of the object to be read.
1169    * @param options a list of optional query parameters and/or request headers.
1170    *   Valid types for this operation include `ContentEncoding`, `ContentType`,
1171    *   `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1172    *   `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1173    *   `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1174    *   `MD5HashValue`, `PredefinedAcl`, `Projection`,
1175    *   `UseResumableUploadSession`, `UserProject`, `WithObjectMetadata` and
1176    *   `UploadContentLength`.
1177    *
1178    * @par Idempotency
1179    * This operation is only idempotent if restricted by pre-conditions, in this
1180    * case, `IfGenerationMatch`.
1181    *
1182    * @par Example
1183    * @snippet storage_object_samples.cc write object
1184    *
1185    * @par Example: write an object with a CMEK.
1186    * @snippet storage_object_cmek_samples.cc write object with kms key
1187    *
1188    * @par Example: starting a resumable upload.
1189    * @snippet storage_object_resumable_write_samples.cc start resumable upload
1190    *
1191    * @par Example: resuming a resumable upload.
1192    * @snippet storage_object_resumable_write_samples.cc resume resumable upload
1193    *
1194    * @see [Resumable Uploads][resumable-link] for more information about
1195    *     resumable uploads.
1196    *
1197    * [resumable-link]: https://cloud.google.com/storage/docs/resumable-uploads
1198    * [how-to-upload-link]:
1199    * https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload
1200    */
1201   template <typename... Options>
WriteObject(std::string const & bucket_name,std::string const & object_name,Options &&...options)1202   ObjectWriteStream WriteObject(std::string const& bucket_name,
1203                                 std::string const& object_name,
1204                                 Options&&... options) {
1205     internal::ResumableUploadRequest request(bucket_name, object_name);
1206     request.set_multiple_options(std::forward<Options>(options)...);
1207     return WriteObjectImpl(request);
1208   }
1209 
1210   /**
1211    * Uploads a file to an object.
1212    *
1213    * @note
1214    * Only regular files are supported. If you need to upload the results of
1215    * reading a device, Named Pipe, FIFO, or other type of file system object
1216    * that is **not** a regular file then `WriteObject()` is probably a better
1217    * alternative.
1218    *
1219    * @param file_name the name of the file to be uploaded.
1220    * @param bucket_name the name of the bucket that contains the object.
1221    * @param object_name the name of the object to be read.
1222    * @param options a list of optional query parameters and/or request headers.
1223    *   Valid types for this operation include `ContentEncoding`, `ContentType`,
1224    *   `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1225    *   `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1226    *   `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1227    *   `MD5HashValue`, `PredefinedAcl`, `Projection`, `UserProject`,
1228    *   `UploadFromOffset`, `UploadLimit` and `WithObjectMetadata`.
1229    *
1230    * @par Idempotency
1231    * This operation is only idempotent if restricted by pre-conditions, in this
1232    * case, `IfGenerationMatch`.
1233    *
1234    * @par Example
1235    * @snippet storage_object_file_transfer_samples.cc upload file
1236    *
1237    * @par Example: manually selecting a resumable upload
1238    * @snippet storage_object_file_transfer_samples.cc upload file resumable
1239    */
1240   template <typename... Options>
UploadFile(std::string const & file_name,std::string const & bucket_name,std::string const & object_name,Options &&...options)1241   StatusOr<ObjectMetadata> UploadFile(std::string const& file_name,
1242                                       std::string const& bucket_name,
1243                                       std::string const& object_name,
1244                                       Options&&... options) {
1245     // Determine, at compile time, which version of UploadFileImpl we should
1246     // call. This needs to be done at compile time because ObjectInsertMedia
1247     // does not support (nor should it support) the UseResumableUploadSession
1248     // option.
1249     using HasUseResumableUpload =
1250         absl::disjunction<std::is_same<UseResumableUploadSession, Options>...>;
1251     return UploadFileImpl(file_name, bucket_name, object_name,
1252                           HasUseResumableUpload{},
1253                           std::forward<Options>(options)...);
1254   }
1255 
1256   /**
1257    * Cancel a resumable upload.
1258    *
1259    * @param upload_session_url the url of the upload session. Returned by
1260    * `ObjectWriteStream::resumable_session_id`.
1261    * @param options a list of optional query parameters and/or request headers.
1262    *   Valid types for this operation include `UserProject`.
1263    *
1264    * @par Idempotency
1265    * This operation is always idempotent because it only acts on a specific
1266    * `upload_session_url`.
1267    */
1268   template <typename... Options>
DeleteResumableUpload(std::string const & upload_session_url,Options &&...options)1269   Status DeleteResumableUpload(std::string const& upload_session_url,
1270                                Options&&... options) {
1271     internal::DeleteResumableUploadRequest request(upload_session_url);
1272     request.set_multiple_options(std::forward<Options>(options)...);
1273     return raw_client_->DeleteResumableUpload(request).status();
1274   }
1275 
1276   /**
1277    * Downloads a Cloud Storage object to a file.
1278    *
1279    * @param bucket_name the name of the bucket that contains the object.
1280    * @param object_name the name of the object to be downloaded.
1281    * @param file_name the name of the destination file that will have the object
1282    *   media.
1283    * @param options a list of optional query parameters and/or request headers.
1284    *   Valid types for this operation include `IfGenerationMatch`,
1285    *   `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1286    *   `IfMetagenerationNotMatch`, `Generation`, `ReadFromOffset`, `ReadRange`,
1287    *   and `UserProject`.
1288    *
1289    * @par Idempotency
1290    * This is a read-only operation and is always idempotent.
1291    *
1292    * @par Example
1293    * @snippet storage_object_file_transfer_samples.cc download file
1294    */
1295   template <typename... Options>
DownloadToFile(std::string const & bucket_name,std::string const & object_name,std::string const & file_name,Options &&...options)1296   Status DownloadToFile(std::string const& bucket_name,
1297                         std::string const& object_name,
1298                         std::string const& file_name, Options&&... options) {
1299     internal::ReadObjectRangeRequest request(bucket_name, object_name);
1300     request.set_multiple_options(std::forward<Options>(options)...);
1301     return DownloadFileImpl(request, file_name);
1302   }
1303 
1304   /**
1305    * Deletes an object.
1306    *
1307    * @param bucket_name the name of the bucket that contains the object.
1308    * @param object_name the name of the object to be deleted.
1309    * @param options a list of optional query parameters and/or request headers.
1310    *     Valid types for this operation include `Generation`,
1311    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1312    *     `IfMetagenerationNotMatch`, and `UserProject`.
1313    *
1314    * @par Idempotency
1315    * This operation is only idempotent if:
1316    * - restricted by pre-conditions, in this case, `IfGenerationMatch`
1317    * - or, if it applies to only one object version via `Generation`.
1318    *
1319    * @par Example
1320    * @snippet storage_object_samples.cc delete object
1321    */
1322   template <typename... Options>
DeleteObject(std::string const & bucket_name,std::string const & object_name,Options &&...options)1323   Status DeleteObject(std::string const& bucket_name,
1324                       std::string const& object_name, Options&&... options) {
1325     internal::DeleteObjectRequest request(bucket_name, object_name);
1326     request.set_multiple_options(std::forward<Options>(options)...);
1327     return raw_client_->DeleteObject(request).status();
1328   }
1329 
1330   /**
1331    * Updates the metadata in a Google Cloud Storage Object.
1332    *
1333    * @param bucket_name the name of the bucket that contains the object.
1334    * @param object_name the name of the object.
1335    * @param metadata the new metadata for the Object.  Only the writeable fields
1336    *     accepted by the `Objects: update` API are used, all other fields are
1337    *     ignored. In particular, note that `bucket` and `name` are ignored in
1338    *     favor of @p bucket_name and @p object_name.
1339    * @param options a list of optional query parameters and/or request headers.
1340    *     Valid types for this operation include `Generation`,
1341    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1342    *     `IfMetagenerationNotMatch`, `PredefinedAcl`,
1343    *     `Projection`, and `UserProject`.
1344    *
1345    * @par Idempotency
1346    * This operation is only idempotent if restricted by pre-conditions, in this
1347    * case, `IfMetagenerationMatch`.
1348    *
1349    * @par Example
1350    * @snippet storage_object_samples.cc update object metadata
1351    */
1352   template <typename... Options>
UpdateObject(std::string bucket_name,std::string object_name,ObjectMetadata metadata,Options &&...options)1353   StatusOr<ObjectMetadata> UpdateObject(std::string bucket_name,
1354                                         std::string object_name,
1355                                         ObjectMetadata metadata,
1356                                         Options&&... options) {
1357     internal::UpdateObjectRequest request(
1358         std::move(bucket_name), std::move(object_name), std::move(metadata));
1359     request.set_multiple_options(std::forward<Options>(options)...);
1360     return raw_client_->UpdateObject(request);
1361   }
1362 
1363   /**
1364    * Patches the metadata in a Google Cloud Storage Object.
1365    *
1366    * This function creates a patch request to change the writeable attributes in
1367    * @p original to the values in @p updated.  Non-writeable attributes are
1368    * ignored, and attributes not present in @p updated are removed. Typically
1369    * this function is used after the application obtained a value with
1370    * `GetObjectMetadata` and has modified these parameters.
1371    *
1372    * @param bucket_name the bucket that contains the object to be updated.
1373    * @param object_name the object to be updated.
1374    * @param original the initial value of the object metadata.
1375    * @param updated the updated value for the object metadata.
1376    * @param options a list of optional query parameters and/or request headers.
1377    *     Valid types for this operation include `Generation`,
1378    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1379    *     `IfMetagenerationNotMatch`, `PredefinedAcl`,
1380    *     `Projection`, and `UserProject`.
1381    *
1382    * @par Idempotency
1383    * This operation is only idempotent if restricted by pre-conditions, in this
1384    * case, `IfMetagenerationMatch`.
1385    *
1386    * @par Example
1387    * @snippet storage_object_samples.cc patch object delete metadata
1388    */
1389   template <typename... Options>
PatchObject(std::string bucket_name,std::string object_name,ObjectMetadata const & original,ObjectMetadata const & updated,Options &&...options)1390   StatusOr<ObjectMetadata> PatchObject(std::string bucket_name,
1391                                        std::string object_name,
1392                                        ObjectMetadata const& original,
1393                                        ObjectMetadata const& updated,
1394                                        Options&&... options) {
1395     internal::PatchObjectRequest request(
1396         std::move(bucket_name), std::move(object_name), original, updated);
1397     request.set_multiple_options(std::forward<Options>(options)...);
1398     return raw_client_->PatchObject(request);
1399   }
1400 
1401   /**
1402    * Patches the metadata in a Google Cloud Storage Object.
1403    *
1404    * This function creates a patch request based on the given @p builder.
1405    * Typically this function is used when the application needs to set an
1406    * object's metadata fields regardless of their previous value (i.e. when
1407    * calling GetObjectMetadata first is not necessary).
1408    *
1409    * @param bucket_name the bucket that contains the object to be updated.
1410    * @param object_name the object to be updated.
1411    * @param builder the set of updates to perform in the Object metadata.
1412    * @param options a list of optional query parameters and/or request headers.
1413    *     Valid types for this operation include `Generation`,
1414    *     `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1415    *     `IfMetagenerationNotMatch`, `PredefinedAcl`,
1416    *     `Projection`, and `UserProject`.
1417    *
1418    * @par Idempotency
1419    * This operation is only idempotent if restricted by pre-conditions, in this
1420    * case, `IfMetagenerationMatch`.
1421    *
1422    * @par Example
1423    * @snippet storage_object_samples.cc patch object content type
1424    */
1425   template <typename... Options>
PatchObject(std::string bucket_name,std::string object_name,ObjectMetadataPatchBuilder const & builder,Options &&...options)1426   StatusOr<ObjectMetadata> PatchObject(
1427       std::string bucket_name, std::string object_name,
1428       ObjectMetadataPatchBuilder const& builder, Options&&... options) {
1429     internal::PatchObjectRequest request(std::move(bucket_name),
1430                                          std::move(object_name), builder);
1431     request.set_multiple_options(std::forward<Options>(options)...);
1432     return raw_client_->PatchObject(request);
1433   }
1434 
1435   /**
1436    * Composes existing objects into a new object in the same bucket.
1437    *
1438    * @param bucket_name the name of the bucket used for source object and
1439    *     destination object.
1440    * @param source_objects objects used to compose `destination_object_name`.
1441    * @param destination_object_name the composed object name.
1442    * @param options a list of optional query parameters and/or request headers.
1443    *     Valid types for this operation include
1444    *      `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1445    *      `IfMetagenerationMatch`, `KmsKeyName`, `UserProject`, and
1446    *      `WithObjectMetadata`.
1447    *
1448    * @par Idempotency
1449    * This operation is only idempotent if restricted by pre-conditions, in this
1450    * case, `IfGenerationMatch`.
1451    *
1452    * @par Example
1453    * @snippet storage_object_samples.cc compose object
1454    *
1455    * @par Example: using encrypted objects with CSEK
1456    * @snippet storage_object_csek_samples.cc compose object csek
1457    */
1458   template <typename... Options>
ComposeObject(std::string bucket_name,std::vector<ComposeSourceObject> source_objects,std::string destination_object_name,Options &&...options)1459   StatusOr<ObjectMetadata> ComposeObject(
1460       std::string bucket_name, std::vector<ComposeSourceObject> source_objects,
1461       std::string destination_object_name, Options&&... options) {
1462     internal::ComposeObjectRequest request(std::move(bucket_name),
1463                                            std::move(source_objects),
1464                                            std::move(destination_object_name));
1465     request.set_multiple_options(std::forward<Options>(options)...);
1466     return raw_client_->ComposeObject(request);
1467   }
1468 
1469   /**
1470    * Creates an `ObjectRewriter` to copy the source object.
1471    *
1472    * Applications use this function to reliably copy objects across [location
1473    * boundaries](https://cloud.google.com/storage/docs/locations), and to
1474    * rewrite objects with different encryption keys. The operation returns a
1475    * `ObjectRewriter`, which the application can use to initiate the copy and to
1476    * iterate if the copy requires more than one call to complete.
1477    *
1478    * @note Application developers should be aware that rewriting large objects
1479    *     may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1480    *     may be required to completely rewrite an object.
1481    *
1482    * @param source_bucket_name the name of the bucket containing the source
1483    *     object.
1484    * @param source_object_name the name of the source object.
1485    * @param destination_bucket_name where the destination object will be
1486    *     located.
1487    * @param destination_object_name what to name the destination object.
1488    * @param options a list of optional query parameters and/or request headers.
1489    *     Valid types for this operation include `DestinationKmsKeyName`,
1490    *      `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1491    *      `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1492    *      `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1493    *      `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1494    *      `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1495    *      `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1496    *
1497    * @par Idempotency
1498    * This operation is only idempotent if restricted by pre-conditions, in this
1499    * case, `IfGenerationMatch`.
1500    *
1501    * @par Example
1502    * @snippet storage_object_rewrite_samples.cc rewrite object non blocking
1503    *
1504    * @par Example
1505    * @snippet storage_object_rewrite_samples.cc rewrite object resume
1506    */
1507   template <typename... Options>
RewriteObject(std::string source_bucket_name,std::string source_object_name,std::string destination_bucket_name,std::string destination_object_name,Options &&...options)1508   ObjectRewriter RewriteObject(std::string source_bucket_name,
1509                                std::string source_object_name,
1510                                std::string destination_bucket_name,
1511                                std::string destination_object_name,
1512                                Options&&... options) {
1513     return ResumeRewriteObject(
1514         std::move(source_bucket_name), std::move(source_object_name),
1515         std::move(destination_bucket_name), std::move(destination_object_name),
1516         std::string{}, std::forward<Options>(options)...);
1517   }
1518 
1519   /**
1520    * Creates an `ObjectRewriter` to resume a previously created rewrite.
1521    *
1522    * Applications use this function to resume a rewrite operation, possibly
1523    * created with `RewriteObject()`. Rewrite can reliably copy objects across
1524    * location boundaries, and can rewrite objects with different encryption
1525    * keys. For large objects this operation can take a long time, thus
1526    * applications should consider checkpointing the rewrite token (accessible in
1527    * the `ObjectRewriter`) and restarting the operation in the event the program
1528    * is terminated.
1529    *
1530    * @note Application developers should be aware that rewriting large objects
1531    *     may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1532    *     may be required to completely rewrite an object.
1533    *
1534    * @param source_bucket_name the name of the bucket containing the source
1535    *     object.
1536    * @param source_object_name the name of the source object.
1537    * @param destination_bucket_name where the destination object will be
1538    *     located.
1539    * @param destination_object_name what to name the destination object.
1540    * @param rewrite_token the token from a previous successful rewrite
1541    *     iteration. Can be the empty string, in which case this starts a new
1542    *     rewrite operation.
1543    * @param options a list of optional query parameters and/or request headers.
1544    *     Valid types for this operation include `DestinationKmsKeyName`,
1545    *      `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1546    *      `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1547    *      `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1548    *      `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1549    *      `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1550    *      `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1551    *
1552    * @par Idempotency
1553    * This operation is only idempotent if restricted by pre-conditions, in this
1554    * case, `IfGenerationMatch`.
1555    *
1556    * @par Example
1557    * @snippet storage_object_rewrite_samples.cc rewrite object resume
1558    */
1559   template <typename... Options>
ResumeRewriteObject(std::string source_bucket_name,std::string source_object_name,std::string destination_bucket_name,std::string destination_object_name,std::string rewrite_token,Options &&...options)1560   ObjectRewriter ResumeRewriteObject(std::string source_bucket_name,
1561                                      std::string source_object_name,
1562                                      std::string destination_bucket_name,
1563                                      std::string destination_object_name,
1564                                      std::string rewrite_token,
1565                                      Options&&... options) {
1566     internal::RewriteObjectRequest request(
1567         std::move(source_bucket_name), std::move(source_object_name),
1568         std::move(destination_bucket_name), std::move(destination_object_name),
1569         std::move(rewrite_token));
1570     request.set_multiple_options(std::forward<Options>(options)...);
1571     return ObjectRewriter(raw_client_, std::move(request));
1572   }
1573 
1574   /**
1575    * Rewrites the object, blocking until the rewrite completes, and returns the
1576    * resulting `ObjectMetadata`.
1577    *
1578    * Applications use this function to reliably copy objects across [location
1579    * boundaries](https://cloud.google.com/storage/docs/locations), and to
1580    * rewrite objects with different encryption keys. The operation blocks until
1581    * the rewrite completes, and returns the resulting `ObjectMetadata`.
1582    *
1583    * @note Application developers should be aware that rewriting large objects
1584    *     may take multiple hours. In such cases the application should consider
1585    *     using `RewriteObject()` or `ResumeRewriteObject()`.
1586    *
1587    * @param source_bucket_name the name of the bucket containing the source
1588    *     object.
1589    * @param source_object_name the name of the source object.
1590    * @param destination_bucket_name where the destination object will be
1591    *     located.
1592    * @param destination_object_name what to name the destination object.
1593    * @param options a list of optional query parameters and/or request headers.
1594    *     Valid types for this operation include `DestinationKmsKeyName`,
1595    *      `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1596    *      `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1597    *      `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1598    *      `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1599    *      `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1600    *      `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1601    *
1602    * @return The metadata of the newly created object.
1603    *
1604    * @par Idempotency
1605    * This operation is only idempotent if restricted by pre-conditions, in this
1606    * case, `IfGenerationMatch`.
1607    *
1608    * @par Example
1609    * @snippet storage_object_rewrite_samples.cc rewrite object
1610    *
1611    * @par Example: using rewrite object to rotate the encryption key
1612    * @snippet storage_object_csek_samples.cc rotate encryption key
1613    *
1614    * @par Example: using rewrite object to rename an object
1615    * @snippet storage_object_rewrite_samples.cc rename object
1616    */
1617   template <typename... Options>
RewriteObjectBlocking(std::string source_bucket_name,std::string source_object_name,std::string destination_bucket_name,std::string destination_object_name,Options &&...options)1618   StatusOr<ObjectMetadata> RewriteObjectBlocking(
1619       std::string source_bucket_name, std::string source_object_name,
1620       std::string destination_bucket_name, std::string destination_object_name,
1621       Options&&... options) {
1622     return ResumeRewriteObject(std::move(source_bucket_name),
1623                                std::move(source_object_name),
1624                                std::move(destination_bucket_name),
1625                                std::move(destination_object_name),
1626                                std::string{}, std::forward<Options>(options)...)
1627         .Result();
1628   }
1629   //@}
1630 
1631   //@{
1632   /**
1633    * @name Bucket Access Control List operations.
1634    *
1635    * You can control who has access to your GCS buckets and objects as
1636    * well as what level of access they have.
1637    *
1638    * @note In most cases, you should use IAM permissions instead of ACLs to
1639    * control access to buckets.
1640    *
1641    * @note All buckets are owned by the project owners group. Project owners
1642    *     are granted `OWNER` permissions to all buckets inside their project.
1643    *     Bucket and object ownership cannot be changed by modifying ACLs.
1644    *
1645    * @note When you apply a new ACL to a bucket, GCS adds `OWNER` permission to
1646    *     the bucket if you omit the grants. You cannot remove the project owners
1647    *     group from a bucket ACL. Attempts to do so will appear to succeed, but
1648    *     the service will add the project owners group into the new ACL before
1649    *     applying it.
1650    *
1651    * @see https://cloud.google.com/storage/docs/access-control/ for more
1652    *     information about access control in GCS.
1653    *
1654    * @see
1655    * https://cloud.google.com/storage/docs/access-control/lists#defaultbuckets
1656    *     for more details about the default owners for a bucket.
1657    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1658    *     the format of the @p entity parameters.
1659    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1660    *     for the format of the @p role parameters.
1661    */
1662   /**
1663    * Retrieves the list of `BucketAccessControl` items for a bucket.
1664    *
1665    * @param bucket_name the name of the bucket.
1666    * @param options a list of optional query parameters and/or request headers.
1667    *     Valid types for this operation include `UserProject`.
1668    *
1669    * @par Idempotency
1670    * This is a read-only operation and is always idempotent.
1671    *
1672    * @par Example
1673    * @snippet storage_bucket_acl_samples.cc list bucket acl
1674    */
1675   template <typename... Options>
ListBucketAcl(std::string const & bucket_name,Options &&...options)1676   StatusOr<std::vector<BucketAccessControl>> ListBucketAcl(
1677       std::string const& bucket_name, Options&&... options) {
1678     internal::ListBucketAclRequest request(bucket_name);
1679     request.set_multiple_options(std::forward<Options>(options)...);
1680     auto items = raw_client_->ListBucketAcl(request);
1681     if (!items) {
1682       return std::move(items).status();
1683     }
1684     return std::move(items.value().items);
1685   }
1686 
1687   /**
1688    * Creates a new entry in a bucket ACL.
1689    *
1690    * @param bucket_name the name of the bucket.
1691    * @param entity the name of the entity added to the ACL.
1692    * @param role the role of the entity.
1693    * @param options a list of optional query parameters and/or request headers.
1694    *     Valid types for this operation include `UserProject`.
1695    *
1696    * @par Idempotency
1697    * This operation is only idempotent if restricted by pre-conditions. There
1698    * are no pre-conditions for this operation that can make it idempotent.
1699    *
1700    * @par Example
1701    * @snippet storage_bucket_acl_samples.cc create bucket acl
1702    *
1703    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1704    *     the format of the @p entity parameter.
1705    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1706    *     for the format of the @p role parameter.
1707    */
1708   template <typename... Options>
CreateBucketAcl(std::string const & bucket_name,std::string const & entity,std::string const & role,Options &&...options)1709   StatusOr<BucketAccessControl> CreateBucketAcl(std::string const& bucket_name,
1710                                                 std::string const& entity,
1711                                                 std::string const& role,
1712                                                 Options&&... options) {
1713     internal::CreateBucketAclRequest request(bucket_name, entity, role);
1714     request.set_multiple_options(std::forward<Options>(options)...);
1715     return raw_client_->CreateBucketAcl(request);
1716   }
1717 
1718   /**
1719    * Deletes an entry from a bucket ACL.
1720    *
1721    * @param bucket_name the name of the bucket.
1722    * @param entity the name of the entity added to the ACL.
1723    * @param options a list of optional query parameters and/or request headers.
1724    *     Valid types for this operation include `UserProject`.
1725    *
1726    * @par Idempotency
1727    * This operation is only idempotent if restricted by pre-conditions. There
1728    * are no pre-conditions for this operation that can make it idempotent.
1729    *
1730    * @par Example
1731    * @snippet storage_bucket_acl_samples.cc delete bucket acl
1732    *
1733    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1734    *     the format of the @p entity parameter.
1735    */
1736   template <typename... Options>
DeleteBucketAcl(std::string const & bucket_name,std::string const & entity,Options &&...options)1737   Status DeleteBucketAcl(std::string const& bucket_name,
1738                          std::string const& entity, Options&&... options) {
1739     internal::DeleteBucketAclRequest request(bucket_name, entity);
1740     request.set_multiple_options(std::forward<Options>(options)...);
1741     return raw_client_->DeleteBucketAcl(request).status();
1742   }
1743 
1744   /**
1745    * Gets the value of an existing bucket ACL.
1746    *
1747    * @param bucket_name the name of the bucket to query.
1748    * @param entity the name of the entity to query.
1749    * @param options a list of optional query parameters and/or request headers.
1750    *     Valid types for this operation include `UserProject`.
1751    *
1752    * @par Idempotency
1753    * This is a read-only operation and is always idempotent.
1754    *
1755    * @par Example
1756    * @snippet storage_bucket_acl_samples.cc get bucket acl
1757    *
1758    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1759    *     the format of the @p entity parameter.
1760    */
1761   template <typename... Options>
GetBucketAcl(std::string const & bucket_name,std::string const & entity,Options &&...options)1762   StatusOr<BucketAccessControl> GetBucketAcl(std::string const& bucket_name,
1763                                              std::string const& entity,
1764                                              Options&&... options) {
1765     internal::GetBucketAclRequest request(bucket_name, entity);
1766     request.set_multiple_options(std::forward<Options>(options)...);
1767     return raw_client_->GetBucketAcl(request);
1768   }
1769 
1770   /**
1771    * Updates the value of an existing bucket ACL.
1772    *
1773    * @note
1774    * For changing BucketAccessControl, the Patch and Update APIs basically offer
1775    * the same functionality. The only field that can be modified by either API
1776    * is `role`, and it may only be set to a new value (it cannot be removed).
1777    * The API is offered for consistency with the other resource types where
1778    * Patch and Update APIs have different semantics.
1779    *
1780    * @param bucket_name the name of the bucket.
1781    * @param acl the new ACL value. Note that only the writable values of the ACL
1782    *   will be modified by the server.
1783    * @param options a list of optional query parameters and/or request headers.
1784    *     Valid types for this operation include `UserProject`.
1785    *
1786    * @par Idempotency
1787    * This operation is only idempotent if restricted by pre-conditions. There
1788    * are no pre-conditions for this operation that can make it idempotent.
1789    *
1790    * @par Example
1791    * @snippet storage_bucket_acl_samples.cc update bucket acl
1792    *
1793    * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1794    *     for additional details on what fields are writeable.
1795    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1796    *     the format of the @p entity parameter.
1797    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1798    *     for the format of the @p role parameter.
1799    */
1800   template <typename... Options>
UpdateBucketAcl(std::string const & bucket_name,BucketAccessControl const & acl,Options &&...options)1801   StatusOr<BucketAccessControl> UpdateBucketAcl(std::string const& bucket_name,
1802                                                 BucketAccessControl const& acl,
1803                                                 Options&&... options) {
1804     internal::UpdateBucketAclRequest request(bucket_name, acl.entity(),
1805                                              acl.role());
1806     request.set_multiple_options(std::forward<Options>(options)...);
1807     return raw_client_->UpdateBucketAcl(request);
1808   }
1809 
1810   /**
1811    * Patches the value of an existing bucket ACL.
1812    *
1813    * Computes the delta between a previous value for an BucketAccessControl and
1814    * the new value for an BucketAccessControl and apply that delta.
1815    *
1816    * @note
1817    * For changing BucketAccessControl, the Patch and Update APIs basically offer
1818    * the same functionality. The only field that can be modified by either API
1819    * is `role`, and it may only be set to a new value (it cannot be removed).
1820    * The API is offered for consistency with the other resource types where
1821    * Patch and Update APIs have different semantics.
1822    *
1823    * @param bucket_name the name of the bucket.
1824    * @param entity the identifier for the user, group, service account, or
1825    *     predefined set of actors holding the permission.
1826    * @param original_acl the original ACL value.
1827    * @param new_acl the new ACL value. Note that only changes on writeable
1828    *     fields will be accepted by the server.
1829    * @param options a list of optional query parameters and/or request headers.
1830    *     Valid types for this operation include `UserProject`, and the standard
1831    *     options available to all operations.
1832    *
1833    * @par Idempotency
1834    * This operation is only idempotent if restricted by pre-conditions. There
1835    * are no pre-conditions for this operation that can make it idempotent.
1836    *
1837    * @par Example
1838    * @snippet storage_bucket_acl_samples.cc patch bucket acl
1839    *
1840    * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1841    *     for additional details on what fields are writeable.
1842    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1843    *     the format of the @p entity parameters.
1844    */
1845   template <typename... Options>
PatchBucketAcl(std::string const & bucket_name,std::string const & entity,BucketAccessControl const & original_acl,BucketAccessControl const & new_acl,Options &&...options)1846   StatusOr<BucketAccessControl> PatchBucketAcl(
1847       std::string const& bucket_name, std::string const& entity,
1848       BucketAccessControl const& original_acl,
1849       BucketAccessControl const& new_acl, Options&&... options) {
1850     internal::PatchBucketAclRequest request(bucket_name, entity, original_acl,
1851                                             new_acl);
1852     request.set_multiple_options(std::forward<Options>(options)...);
1853     return raw_client_->PatchBucketAcl(request);
1854   }
1855 
1856   /**
1857    * Patches the value of an existing bucket ACL.
1858    *
1859    * This API allows the application to patch an BucketAccessControl without
1860    * having to read the current value.
1861    *
1862    * @note
1863    * For changing BucketAccessControl, the Patch and Update APIs basically offer
1864    * the same functionality. The only field that can be modified by either API
1865    * is `role`, and it may only be set to a new value (it cannot be removed).
1866    * The API is offered for consistency with the other resource types where
1867    * Patch and Update APIs have different semantics.
1868    *
1869    * @param bucket_name the name of the bucket.
1870    * @param entity the identifier for the user, group, service account, or
1871    *     predefined set of actors holding the permission.
1872    * @param builder a builder ready to create the patch.
1873    * @param options a list of optional query parameters and/or request
1874    *     headers. Valid types for this operation include `Generation`,
1875    *     `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
1876    *
1877    * @par Idempotency
1878    * This operation is only idempotent if restricted by pre-conditions. There
1879    * are no pre-conditions for this operation that can make it idempotent.
1880    *
1881    * @par Example
1882    * @snippet storage_bucket_acl_samples.cc patch bucket acl no-read
1883    *
1884    * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1885    *     for additional details on what fields are writeable.
1886    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1887    *     the format of the @p entity parameters.
1888    */
1889   template <typename... Options>
PatchBucketAcl(std::string const & bucket_name,std::string const & entity,BucketAccessControlPatchBuilder const & builder,Options &&...options)1890   StatusOr<BucketAccessControl> PatchBucketAcl(
1891       std::string const& bucket_name, std::string const& entity,
1892       BucketAccessControlPatchBuilder const& builder, Options&&... options) {
1893     internal::PatchBucketAclRequest request(bucket_name, entity, builder);
1894     request.set_multiple_options(std::forward<Options>(options)...);
1895     return raw_client_->PatchBucketAcl(request);
1896   }
1897   //@}
1898 
1899   //@{
1900   /**
1901    * @name Object Access Control List operations.
1902    *
1903    * You can control who has access to your GCS buckets and objects as
1904    * well as what level of access they have.
1905    *
1906    * @note When you upload (create) an object the entity that uploads the object
1907    *     is listed as the object owner. This can be a user or a service account,
1908    *     depending on what credentials are used to authenticate with GCS.
1909    *     Object ownership cannot be changed by modifying ACLs. You can change
1910    *     object ownership only by overwriting the object while authenticated as
1911    *     the desired owner.
1912    *
1913    * @note When you apply a new ACL to an object, GCS adds `OWNER` permission to
1914    *     the object if you omit the grants.
1915    *
1916    * @see https://cloud.google.com/storage/docs/access-control/ for more
1917    *     information about access control in GCS.
1918    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1919    *     the format of the @p entity parameters.
1920    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1921    *     for the format of the @p role parameters.
1922    */
1923   /**
1924    * Retrieves the list of ObjectAccessControl items for an object.
1925    *
1926    * @param bucket_name the name of the bucket that contains the object.
1927    * @param object_name the name of the object to be deleted.
1928    * @param options a list of optional query parameters and/or request headers.
1929    *     Valid types for this operation include `Generation`, and `UserProject`.
1930    *
1931    * @par Idempotency
1932    * This is a read-only operation and is always idempotent.
1933    *
1934    * @par Example
1935    * @snippet storage_object_acl_samples.cc list object acl
1936    */
1937   template <typename... Options>
ListObjectAcl(std::string const & bucket_name,std::string const & object_name,Options &&...options)1938   StatusOr<std::vector<ObjectAccessControl>> ListObjectAcl(
1939       std::string const& bucket_name, std::string const& object_name,
1940       Options&&... options) {
1941     internal::ListObjectAclRequest request(bucket_name, object_name);
1942     request.set_multiple_options(std::forward<Options>(options)...);
1943     auto result = raw_client_->ListObjectAcl(request);
1944     if (!result) {
1945       return std::move(result).status();
1946     }
1947     return std::move(result.value().items);
1948   }
1949 
1950   /**
1951    * Creates a new entry in the object ACL.
1952    *
1953    * @param bucket_name the name of the bucket that contains the object.
1954    * @param object_name the name of the object.
1955    * @param entity the name of the entity added to the ACL.
1956    * @param role the role of the entity.
1957    * @param options a list of optional query parameters and/or request headers.
1958    *     Valid types for this operation include `Generation`, and `UserProject`.
1959    *
1960    * @par Idempotency
1961    * This operation is only idempotent if restricted by pre-conditions. There
1962    * are no pre-conditions for this operation that can make it idempotent.
1963    *
1964    * @par Example
1965    * @snippet storage_object_acl_samples.cc create object acl
1966    *
1967    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1968    *     the format of the @p entity parameter.
1969    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1970    *     for the format of the @p role parameter.
1971    */
1972   template <typename... Options>
CreateObjectAcl(std::string const & bucket_name,std::string const & object_name,std::string const & entity,std::string const & role,Options &&...options)1973   StatusOr<ObjectAccessControl> CreateObjectAcl(std::string const& bucket_name,
1974                                                 std::string const& object_name,
1975                                                 std::string const& entity,
1976                                                 std::string const& role,
1977                                                 Options&&... options) {
1978     internal::CreateObjectAclRequest request(bucket_name, object_name, entity,
1979                                              role);
1980     request.set_multiple_options(std::forward<Options>(options)...);
1981     return raw_client_->CreateObjectAcl(request);
1982   }
1983 
1984   /**
1985    * Deletes one access control entry in one object.
1986    *
1987    * @param bucket_name the name of the bucket that contains the object.
1988    * @param object_name the name of the object to be deleted.
1989    * @param entity the name of the entity (user, team, group) to be removed from
1990    *   the Object's ACL.
1991    * @param options a list of optional query parameters and/or request headers.
1992    *     Valid types for this operation include `Generation`, and `UserProject`.
1993    *
1994    * @par Idempotency
1995    * This operation is only idempotent if restricted by pre-conditions. There
1996    * are no pre-conditions for this operation that can make it idempotent.
1997    *
1998    * @par Example
1999    * @snippet storage_object_acl_samples.cc delete object acl
2000    *
2001    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2002    *     the format of the @p entity parameters.
2003    */
2004   template <typename... Options>
DeleteObjectAcl(std::string const & bucket_name,std::string const & object_name,std::string const & entity,Options &&...options)2005   Status DeleteObjectAcl(std::string const& bucket_name,
2006                          std::string const& object_name,
2007                          std::string const& entity, Options&&... options) {
2008     internal::DeleteObjectAclRequest request(bucket_name, object_name, entity);
2009     request.set_multiple_options(std::forward<Options>(options)...);
2010     return raw_client_->DeleteObjectAcl(request).status();
2011   }
2012 
2013   /**
2014    * Gets the value of an existing object ACL.
2015    *
2016    * @param bucket_name the name of the bucket that contains the object.
2017    * @param object_name the name of the object.
2018    * @param entity the name of the entity added to the ACL.
2019    * @param options a list of optional query parameters and/or request headers.
2020    *     Valid types for this operation include `Generation`, and `UserProject`.
2021    *
2022    * @par Idempotency
2023    * This is a read-only operation and is always idempotent.
2024    *
2025    * @par Example
2026    * @snippet storage_object_acl_samples.cc print file acl for user
2027    *
2028    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2029    *     the format of the @p entity parameters.
2030    */
2031   template <typename... Options>
GetObjectAcl(std::string const & bucket_name,std::string const & object_name,std::string const & entity,Options &&...options)2032   StatusOr<ObjectAccessControl> GetObjectAcl(std::string const& bucket_name,
2033                                              std::string const& object_name,
2034                                              std::string const& entity,
2035                                              Options&&... options) {
2036     internal::GetObjectAclRequest request(bucket_name, object_name, entity);
2037     request.set_multiple_options(std::forward<Options>(options)...);
2038     return raw_client_->GetObjectAcl(request);
2039   }
2040 
2041   /**
2042    * Updates the value of an existing object ACL.
2043    *
2044    * @note
2045    * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2046    * the same functionality. The only field that can be modified by either API
2047    * is `role`, and it may only be set to a new value (it cannot be removed).
2048    * The API is offered for consistency with the other resource types where
2049    * Patch and Update APIs have different semantics.
2050    *
2051    * @param bucket_name the name of the bucket that contains the object.
2052    * @param object_name the name of the object.
2053    * @param acl the new ACL value. Note that only the writable values of the ACL
2054    *   will be modified by the server.
2055    * @param options a list of optional query parameters and/or request
2056    *     Valid types for this operation include `Generation`, and `UserProject`.
2057    *
2058    * @par Idempotency
2059    * This operation is only idempotent if restricted by pre-conditions. There
2060    * are no pre-conditions for this operation that can make it idempotent.
2061    *
2062    * @par Example
2063    * @snippet storage_object_acl_samples.cc update object acl
2064    *
2065    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2066    *     the format of the @p entity parameters.
2067    * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2068    *     for additional details on what fields are writeable.
2069    */
2070   template <typename... Options>
UpdateObjectAcl(std::string const & bucket_name,std::string const & object_name,ObjectAccessControl const & acl,Options &&...options)2071   StatusOr<ObjectAccessControl> UpdateObjectAcl(std::string const& bucket_name,
2072                                                 std::string const& object_name,
2073                                                 ObjectAccessControl const& acl,
2074                                                 Options&&... options) {
2075     internal::UpdateObjectAclRequest request(bucket_name, object_name,
2076                                              acl.entity(), acl.role());
2077     request.set_multiple_options(std::forward<Options>(options)...);
2078     return raw_client_->UpdateObjectAcl(request);
2079   }
2080 
2081   /**
2082    * Patches the value of an existing object ACL.
2083    *
2084    * Compute the delta between a previous value for an ObjectAccessControl and
2085    * the new value for an ObjectAccessControl and apply that delta.
2086    *
2087    * @note
2088    * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2089    * the same functionality. The only field that can be modified by either API
2090    * is `role`, and it may only be set to a new value (it cannot be removed).
2091    * The API is offered for consistency with the other resource types where
2092    * Patch and Update APIs have different semantics.
2093    *
2094    * @param bucket_name the name of the bucket that contains the object.
2095    * @param object_name the name of the object.
2096    * @param entity the identifier for the user, group, service account, or
2097    *     predefined set of actors holding the permission.
2098    * @param original_acl the original ACL value.
2099    * @param new_acl the new ACL value. Note that only changes on writeable
2100    *     fields will be accepted by the server.
2101    * @param options a list of optional query parameters and/or request
2102    *     headers. Valid types for this operation include `Generation`,
2103    *     `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2104    *
2105    * @par Idempotency
2106    * This operation is only idempotent if restricted by pre-conditions. There
2107    * are no pre-conditions for this operation that can make it idempotent.
2108    *
2109    * @par Example
2110    * @snippet storage_object_acl_samples.cc patch object acl
2111    *
2112    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2113    *     the format of the @p entity parameters.
2114    * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2115    *     for additional details on what fields are writeable.
2116    */
2117   template <typename... Options>
PatchObjectAcl(std::string const & bucket_name,std::string const & object_name,std::string const & entity,ObjectAccessControl const & original_acl,ObjectAccessControl const & new_acl,Options &&...options)2118   StatusOr<ObjectAccessControl> PatchObjectAcl(
2119       std::string const& bucket_name, std::string const& object_name,
2120       std::string const& entity, ObjectAccessControl const& original_acl,
2121       ObjectAccessControl const& new_acl, Options&&... options) {
2122     internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2123                                             original_acl, new_acl);
2124     request.set_multiple_options(std::forward<Options>(options)...);
2125     return raw_client_->PatchObjectAcl(request);
2126   }
2127 
2128   /**
2129    * Patches the value of an existing object ACL.
2130    *
2131    * This API allows the application to patch an ObjectAccessControl without
2132    * having to read the current value.
2133    *
2134    * @note
2135    * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2136    * the same functionality. The only field that can be modified by either API
2137    * is `role`, and it may only be set to a new value (it cannot be removed).
2138    * The API is offered for consistency with the other resource types where
2139    * Patch and Update APIs have different semantics.
2140    *
2141    * @param bucket_name the name of the bucket that contains the object.
2142    * @param object_name the name of the object.
2143    * @param entity the identifier for the user, group, service account, or
2144    *     predefined set of actors holding the permission.
2145    * @param builder a builder ready to create the patch.
2146    * @param options a list of optional query parameters and/or request
2147    *     headers. Valid types for this operation include `Generation`,
2148    *     `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2149    *
2150    * @par Idempotency
2151    * This operation is only idempotent if restricted by pre-conditions. There
2152    * are no pre-conditions for this operation that can make it idempotent.
2153    *
2154    * @par Example
2155    * @snippet storage_object_acl_samples.cc patch object acl no-read
2156    *
2157    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2158    *     the format of the @p entity parameters.
2159    * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2160    *     for additional details on what fields are writeable.
2161    */
2162   template <typename... Options>
PatchObjectAcl(std::string const & bucket_name,std::string const & object_name,std::string const & entity,ObjectAccessControlPatchBuilder const & builder,Options &&...options)2163   StatusOr<ObjectAccessControl> PatchObjectAcl(
2164       std::string const& bucket_name, std::string const& object_name,
2165       std::string const& entity, ObjectAccessControlPatchBuilder const& builder,
2166       Options&&... options) {
2167     internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2168                                             builder);
2169     request.set_multiple_options(std::forward<Options>(options)...);
2170     return raw_client_->PatchObjectAcl(request);
2171   }
2172   //@}
2173 
2174   //@{
2175   /**
2176    * @name Bucket Default Object Access Control List operations.
2177    *
2178    * When you upload an object to GCS without specifying an ACL, the object is
2179    * created with the Default Object ACL for its bucket. These operations are
2180    * used to query and modify the Default Object ACL of a bucket.
2181    *
2182    * @see
2183    * https://cloud.google.com/storage/docs/access-control/lists#defaultobjects
2184    *     for more information on default object ACLs.
2185    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2186    *     the format of the @p entity parameters.
2187    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2188    *     for the format of the @p role parameters.
2189    */
2190   /**
2191    * Retrieves the default object ACL for a bucket as a vector of
2192    * `ObjectAccessControl` items.
2193    *
2194    * The default object ACL sets the ACL for any object created in the bucket,
2195    * unless a different ACL is specified when the object is created.
2196    *
2197    * @param bucket_name the name of the bucket.
2198    * @param options a list of optional query parameters and/or request headers.
2199    *     Valid types for this operation include `UserProject`.
2200    *
2201    * @par Idempotency
2202    * This is a read-only operation and is always idempotent.
2203    *
2204    * @par Example
2205    * @snippet storage_default_object_acl_samples.cc list default object acl
2206    *
2207    * @see
2208    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2209    */
2210   template <typename... Options>
ListDefaultObjectAcl(std::string const & bucket_name,Options &&...options)2211   StatusOr<std::vector<ObjectAccessControl>> ListDefaultObjectAcl(
2212       std::string const& bucket_name, Options&&... options) {
2213     internal::ListDefaultObjectAclRequest request(bucket_name);
2214     request.set_multiple_options(std::forward<Options>(options)...);
2215     auto response = raw_client_->ListDefaultObjectAcl(request);
2216     if (!response) {
2217       return std::move(response).status();
2218     }
2219     return std::move(response.value().items);
2220   }
2221 
2222   /**
2223    * Creates a new entry in the default object ACL for a bucket.
2224    *
2225    * The default object ACL sets the ACL for any object created in the bucket,
2226    * unless a different ACL is specified when the object is created.
2227    *
2228    * @param bucket_name the name of the bucket.
2229    * @param entity the name of the entity added to the ACL.
2230    * @param role the role of the entity.
2231    * @param options a list of optional query parameters and/or request headers.
2232    *     Valid types for this operation include `UserProject`.
2233    *
2234    * @par Idempotency
2235    * This operation is only idempotent if restricted by pre-conditions. There
2236    * are no pre-conditions for this operation that can make it idempotent.
2237    *
2238    * @par Example
2239    * @snippet storage_default_object_acl_samples.cc create default object acl
2240    *
2241    * @see
2242    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2243    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2244    *     the format of the @p entity parameter.
2245    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2246    *     for the format of the @p role parameter.
2247    */
2248   template <typename... Options>
CreateDefaultObjectAcl(std::string const & bucket_name,std::string const & entity,std::string const & role,Options &&...options)2249   StatusOr<ObjectAccessControl> CreateDefaultObjectAcl(
2250       std::string const& bucket_name, std::string const& entity,
2251       std::string const& role, Options&&... options) {
2252     internal::CreateDefaultObjectAclRequest request(bucket_name, entity, role);
2253     request.set_multiple_options(std::forward<Options>(options)...);
2254     return raw_client_->CreateDefaultObjectAcl(request);
2255   }
2256 
2257   /**
2258    * Deletes an entry from the default object ACL in a bucket.
2259    *
2260    * The default object ACL sets the ACL for any object created in the bucket,
2261    * unless a different ACL is specified when the object is created.
2262    *
2263    * @param bucket_name the name of the bucket.
2264    * @param entity the name of the entity added to the ACL.
2265    * @param options a list of optional query parameters and/or request headers.
2266    *     Valid types for this operation include `UserProject`.
2267    *
2268    * @par Idempotency
2269    * This operation is only idempotent if restricted by pre-conditions. There
2270    * are no pre-conditions for this operation that can make it idempotent.
2271    *
2272    * @par Example
2273    * @snippet storage_default_object_acl_samples.cc delete default object acl
2274    *
2275    * @see
2276    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2277    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2278    *     the format of the @p entity parameter.
2279    */
2280   template <typename... Options>
DeleteDefaultObjectAcl(std::string const & bucket_name,std::string const & entity,Options &&...options)2281   Status DeleteDefaultObjectAcl(std::string const& bucket_name,
2282                                 std::string const& entity,
2283                                 Options&&... options) {
2284     internal::DeleteDefaultObjectAclRequest request(bucket_name, entity);
2285     request.set_multiple_options(std::forward<Options>(options)...);
2286     return raw_client_->DeleteDefaultObjectAcl(request).status();
2287   }
2288 
2289   /**
2290    * Gets the value of a default object ACL in a bucket.
2291    *
2292    * The default object ACL sets the ACL for any object created in the bucket,
2293    * unless a different ACL is specified when the object is created.
2294    *
2295    * @param bucket_name the name of the bucket.
2296    * @param entity the name of the entity.
2297    * @param options a list of optional query parameters and/or request headers.
2298    *     Valid types for this operation include `UserProject`.
2299    *
2300    * @par Idempotency
2301    * This is a read-only operation and is always idempotent.
2302    *
2303    * @par Example
2304    * @snippet storage_default_object_acl_samples.cc get default object acl
2305    *
2306    * @see
2307    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2308    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2309    *     the format of the @p entity parameter.
2310    */
2311   template <typename... Options>
GetDefaultObjectAcl(std::string const & bucket_name,std::string const & entity,Options &&...options)2312   StatusOr<ObjectAccessControl> GetDefaultObjectAcl(
2313       std::string const& bucket_name, std::string const& entity,
2314       Options&&... options) {
2315     internal::GetDefaultObjectAclRequest request(bucket_name, entity);
2316     request.set_multiple_options(std::forward<Options>(options)...);
2317     return raw_client_->GetDefaultObjectAcl(request);
2318   }
2319 
2320   /**
2321    * Updates the value of an existing default object ACL.
2322    *
2323    * The default object ACL sets the ACL for any object created in the bucket,
2324    * unless a different ACL is specified when the object is created.
2325    *
2326    * @note
2327    * For changing default object access controls, the Patch and Update APIs
2328    * basically offer the same functionality. The only field that can be modified
2329    * by either API is `role`, and it may only be set to a new value (it cannot
2330    * be removed). The API is offered for consistency with the other resource
2331    * types where Patch and Update APIs have different semantics.
2332    *
2333    * @param bucket_name the name of the bucket.
2334    * @param acl the new ACL value. Note that only the writable values of the ACL
2335    *   will be modified by the server.
2336    * @param options a list of optional query parameters and/or request
2337    *     Valid types for this operation include `UserProject`.
2338    *
2339    * @par Idempotency
2340    * This operation is only idempotent if restricted by pre-conditions. There
2341    * are no pre-conditions for this operation that can make it idempotent.
2342    *
2343    * @par Example
2344    * @snippet storage_default_object_acl_samples.cc update default object acl
2345    *
2346    * @see
2347    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2348    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2349    *     the format of the @p entity parameter.
2350    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2351    *     for the format of the @p role parameter.
2352    */
2353   template <typename... Options>
UpdateDefaultObjectAcl(std::string const & bucket_name,ObjectAccessControl const & acl,Options &&...options)2354   StatusOr<ObjectAccessControl> UpdateDefaultObjectAcl(
2355       std::string const& bucket_name, ObjectAccessControl const& acl,
2356       Options&&... options) {
2357     internal::UpdateDefaultObjectAclRequest request(bucket_name, acl.entity(),
2358                                                     acl.role());
2359     request.set_multiple_options(std::forward<Options>(options)...);
2360     return raw_client_->UpdateDefaultObjectAcl(request);
2361   }
2362 
2363   /**
2364    * Patches the value of an existing default object ACL.
2365    *
2366    * Compute the delta between a previous and new values for a default object
2367    * access control, and apply that delta.
2368    *
2369    * @note
2370    * For changing default object access controls, the Patch and Update APIs
2371    * basically offer the same functionality. The only field that can be modified
2372    * by either API is `role`, and it may only be set to a new value (it cannot
2373    * be removed). The API is offered for consistency with the other resource
2374    * types where Patch and Update APIs have different semantics.
2375    *
2376    * @param bucket_name the name of the bucket.
2377    * @param entity the identifier for the user, group, service account, or
2378    *     predefined set of actors holding the permission.
2379    * @param original_acl the original ACL value.
2380    * @param new_acl the new ACL value. Note that only changes on writeable
2381    *     fields will be accepted by the server.
2382    * @param options a list of optional query parameters and/or request
2383    *     headers. Valid types for this operation include `UserProject`, as well
2384    *     as the standard parameters, such as `IfMatchEtag`, and
2385    *     `IfNoneMatchEtag`.
2386    *
2387    * @par Idempotency
2388    * This operation is only idempotent if restricted by pre-conditions. There
2389    * are no pre-conditions for this operation that can make it idempotent.
2390    *
2391    * @par Example
2392    * @snippet storage_default_object_acl_samples.cc patch default object acl
2393    *
2394    * @see
2395    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2396    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2397    *     the format of the @p entity parameter.
2398    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2399    *     for the format of the @p role parameter.
2400    */
2401   template <typename... Options>
PatchDefaultObjectAcl(std::string const & bucket_name,std::string const & entity,ObjectAccessControl const & original_acl,ObjectAccessControl const & new_acl,Options &&...options)2402   StatusOr<ObjectAccessControl> PatchDefaultObjectAcl(
2403       std::string const& bucket_name, std::string const& entity,
2404       ObjectAccessControl const& original_acl,
2405       ObjectAccessControl const& new_acl, Options&&... options) {
2406     internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2407                                                    original_acl, new_acl);
2408     request.set_multiple_options(std::forward<Options>(options)...);
2409     return raw_client_->PatchDefaultObjectAcl(request);
2410   }
2411 
2412   /**
2413    * Patches the value of an existing default object ACL.
2414    *
2415    * This API allows the application to patch an ObjectAccessControl without
2416    * having to read the current value.
2417    *
2418    * @note
2419    * For changing default object access controls, the Patch and Update APIs
2420    * basically offer the same functionality. The only field that can be modified
2421    * by either API is `role`, and it may only be set to a new value (it cannot
2422    * be removed). The API is offered for consistency with the other resource
2423    * types where Patch and Update APIs have different semantics.
2424    *
2425    * @param bucket_name the name of the bucket.
2426    * @param entity the identifier for the user, group, service account, or
2427    *     predefined set of actors holding the permission.
2428    * @param builder a builder ready to create the patch.
2429    * @param options a list of optional query parameters and/or request
2430    *     headers. Valid types for this operation include `UserProject`, as well
2431    *     as the standard parameters, such as `IfMatchEtag`, and
2432    *     `IfNoneMatchEtag`.
2433    *
2434    * @par Idempotency
2435    * This operation is only idempotent if restricted by pre-conditions. There
2436    * are no pre-conditions for this operation that can make it idempotent.
2437    *
2438    * @par Example
2439    * @snippet storage_default_object_acl_samples.cc patch default object acl
2440    * no-read
2441    *
2442    * @see
2443    * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2444    * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2445    *     the format of the @p entity parameter.
2446    * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2447    *     for the format of the @p role parameter.
2448    */
2449   template <typename... Options>
PatchDefaultObjectAcl(std::string const & bucket_name,std::string const & entity,ObjectAccessControlPatchBuilder const & builder,Options &&...options)2450   StatusOr<ObjectAccessControl> PatchDefaultObjectAcl(
2451       std::string const& bucket_name, std::string const& entity,
2452       ObjectAccessControlPatchBuilder const& builder, Options&&... options) {
2453     internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2454                                                    builder);
2455     request.set_multiple_options(std::forward<Options>(options)...);
2456     return raw_client_->PatchDefaultObjectAcl(request);
2457   }
2458   //@}
2459 
2460   //@{
2461   /**
2462    * @name Service account operations.
2463    *
2464    * Service accounts allow applications to authenticate and access GCP
2465    * resources and services. When acting on your behalf, GCS uses such a service
2466    * account. GCS creates one service account per project. These operations
2467    * allow you to query the GCS service account for a project.
2468    *
2469    * @see https://cloud.google.com/storage/docs/projects#service-accounts for
2470    *     more information on service accounts.
2471    */
2472   /**
2473    * Gets the GCS service account for a given project.
2474    *
2475    * A service account is a special Google account that belongs to your
2476    * application, virtual machine, or to a Google service when acting on your
2477    * behalf.  This API allows you to discover the GCS service account for the
2478    * @p project_id project.
2479    *
2480    * @param project_id the project to query.
2481    * @param options a list of optional query parameters and/or request headers.
2482    *     Valid types for this operation include `UserProject`.
2483    *
2484    * @par Idempotency
2485    * This is a read-only operation and is always idempotent.
2486    *
2487    * @par Example
2488    * @snippet storage_service_account_samples.cc get service account for project
2489    *
2490    * @see https://cloud.google.com/iam/docs/service-accounts for general
2491    *     information on Google Cloud Platform service accounts.
2492    */
2493   template <typename... Options>
GetServiceAccountForProject(std::string const & project_id,Options &&...options)2494   StatusOr<ServiceAccount> GetServiceAccountForProject(
2495       std::string const& project_id, Options&&... options) {
2496     internal::GetProjectServiceAccountRequest request(project_id);
2497     request.set_multiple_options(std::forward<Options>(options)...);
2498     return raw_client_->GetServiceAccount(request);
2499   }
2500 
2501   /**
2502    * Gets the GCS service account for the default project.
2503    *
2504    * A service account is a special Google account that belongs to your
2505    * application, virtual machine, or to a Google service when acting on your
2506    * behalf.  This API allows you to discover the GCS service account for the
2507    * default project associated with this object.
2508    *
2509    * The default project is required to be configured in the `ClientOptions`
2510    * used to construct this object. If the application does not set the project
2511    * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
2512    * used. If neither the environment variable is set, nor a value is set
2513    * explicitly by the application, the server will reject the request and this
2514    * function will return the error status.
2515    *
2516    * @param options a list of optional query parameters and/or request headers.
2517    *     Valid types for this operation include `UserProject`.
2518    *
2519    * @par Idempotency
2520    * This is a read-only operation and is always idempotent.
2521    *
2522    * @par Example
2523    * @snippet storage_service_account_samples.cc get service account
2524    *
2525    * @see https://cloud.google.com/iam/docs/service-accounts for general
2526    *     information on Google Cloud Platform service accounts.
2527    */
2528   template <typename... Options>
GetServiceAccount(Options &&...options)2529   StatusOr<ServiceAccount> GetServiceAccount(Options&&... options) {
2530     auto const& project_id = raw_client_->client_options().project_id();
2531     return GetServiceAccountForProject(project_id,
2532                                        std::forward<Options>(options)...);
2533   }
2534 
2535   /**
2536    * List the available HMAC keys.
2537    *
2538    * @warning This GCS feature is not GA, it is subject to change without
2539    *     notice.
2540    *
2541    * @param options a list of optional query parameters and/or request headers.
2542    *     In addition to the options common to all requests, this operation
2543    *     accepts `Deleted` `MaxResults`, `OverrideDefaultProject`,
2544    *     `ServiceAccountFilter`, and `UserProject`.
2545    *
2546    * @return A range to iterate over the available HMAC keys.
2547    *
2548    * @par Idempotency
2549    * This is a read-only operation and is always idempotent.
2550    *
2551    * @par Example
2552    * @snippet storage_service_account_samples.cc list hmac keys
2553    *
2554    * @par Example
2555    * @snippet storage_service_account_samples.cc list hmac keys service account
2556    *
2557    * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2558    *     general information on using HMAC keys for Google Cloud Platform
2559    *     service accounts authentication.
2560    *
2561    * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2562    *     for a detailed description on how to use the feature.
2563    */
2564   template <typename... Options>
ListHmacKeys(Options &&...options)2565   ListHmacKeysReader ListHmacKeys(Options&&... options) {
2566     auto const& project_id = raw_client_->client_options().project_id();
2567     internal::ListHmacKeysRequest request(project_id);
2568     request.set_multiple_options(std::forward<Options>(options)...);
2569     auto client = raw_client_;
2570     return google::cloud::internal::MakePaginationRange<ListHmacKeysReader>(
2571         request,
2572         [client](internal::ListHmacKeysRequest const& r) {
2573           return client->ListHmacKeys(r);
2574         },
2575         [](internal::ListHmacKeysResponse r) { return std::move(r.items); });
2576   }
2577 
2578   /**
2579    * Create a new HMAC key.
2580    *
2581    * @warning This GCS feature is not GA, it is subject to change without
2582    *     notice.
2583    *
2584    * @param service_account the service account email where you want to create
2585    *     the new HMAC key.
2586    * @param options a list of optional query parameters and/or request headers.
2587    *     In addition to the options common to all requests, this operation
2588    *     accepts `OverrideDefaultProject`.
2589    *
2590    * @return This operation returns the new HMAC key metadata *and* the HMAC key
2591    *   secret (encoded as a base64 string). This is the only request that
2592    *   returns the secret.
2593    *
2594    * @par Idempotency
2595    * This operation is not idempotent. Retrying the operation will create a new
2596    * key each time.
2597    *
2598    * @par Example
2599    * @snippet storage_service_account_samples.cc create hmac key
2600    *
2601    * @par Example
2602    * @snippet storage_service_account_samples.cc create hmac key project
2603    *
2604    * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2605    *     general information on using HMAC keys for Google Cloud Platform
2606    *     service accounts authentication.
2607    *
2608    * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2609    *     for a detailed description on how to use the feature.
2610    */
2611   template <typename... Options>
CreateHmacKey(std::string service_account,Options &&...options)2612   StatusOr<std::pair<HmacKeyMetadata, std::string>> CreateHmacKey(
2613       std::string service_account, Options&&... options) {
2614     auto const& project_id = raw_client_->client_options().project_id();
2615     internal::CreateHmacKeyRequest request(project_id,
2616                                            std::move(service_account));
2617     request.set_multiple_options(std::forward<Options>(options)...);
2618     auto result = raw_client_->CreateHmacKey(request);
2619     if (!result) {
2620       return result.status();
2621     }
2622     return std::make_pair(std::move(result->metadata),
2623                           std::move(result->secret));
2624   }
2625 
2626   /**
2627    * Delete a HMAC key in a given project.
2628    *
2629    * @warning This GCS feature is not GA, it is subject to change without
2630    *     notice.
2631    *
2632    * @param access_id the HMAC key `access_id()` that you want to delete.  Each
2633    *     HMAC key is assigned an `access_id()` attribute at creation time.
2634    * @param options a list of optional query parameters and/or request headers.
2635    *     In addition to the options common to all requests, this operation
2636    *     accepts `OverrideDefaultProject`.
2637    *
2638    * @return This operation returns the new HMAC key metadata.
2639    *
2640    * @par Idempotency
2641    * This operation is always idempotent. An access id identifies a single HMAC
2642    * key, calling the operation multiple times can succeed only once.
2643    *
2644    * @par Example
2645    * @snippet storage_service_account_samples.cc delete hmac key
2646    *
2647    * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2648    *     general information on using HMAC keys for Google Cloud Platform
2649    *     service accounts authentication.
2650    *
2651    * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2652    *     for a detailed description on how to use the feature.
2653    */
2654   template <typename... Options>
DeleteHmacKey(std::string access_id,Options &&...options)2655   Status DeleteHmacKey(std::string access_id, Options&&... options) {
2656     auto const& project_id = raw_client_->client_options().project_id();
2657     internal::DeleteHmacKeyRequest request(project_id, std::move(access_id));
2658     request.set_multiple_options(std::forward<Options>(options)...);
2659     return raw_client_->DeleteHmacKey(request).status();
2660   }
2661 
2662   /**
2663    * Get an existing HMAC key in a given project.
2664    *
2665    * @warning This GCS feature is not GA, it is subject to change without
2666    *     notice.
2667    *
2668    * @param access_id the HMAC key `access_id()` that you want to delete.  Each
2669    *     HMAC key is assigned an `access_id()` attribute at creation time.
2670    * @param options a list of optional query parameters and/or request headers.
2671    *     In addition to the options common to all requests, this operation
2672    *     accepts `OverrideDefaultProject`.
2673    *
2674    * @return This operation returns the new HMAC key metadata.
2675    *
2676    * @par Idempotency
2677    * This is a read-only operation and therefore it is always idempotent.
2678    *
2679    * @par Example
2680    * @snippet storage_service_account_samples.cc get hmac key
2681    *
2682    * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2683    *     general information on using HMAC keys for Google Cloud Platform
2684    *     service accounts authentication.
2685    *
2686    * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2687    *     for a detailed description on how to use the feature.
2688    */
2689   template <typename... Options>
GetHmacKey(std::string access_id,Options &&...options)2690   StatusOr<HmacKeyMetadata> GetHmacKey(std::string access_id,
2691                                        Options&&... options) {
2692     auto const& project_id = raw_client_->client_options().project_id();
2693     internal::GetHmacKeyRequest request(project_id, std::move(access_id));
2694     request.set_multiple_options(std::forward<Options>(options)...);
2695     return raw_client_->GetHmacKey(request);
2696   }
2697 
2698   /**
2699    * Update an existing HMAC key in a given project.
2700    *
2701    * @warning This GCS feature is not GA, it is subject to change without
2702    *     notice.
2703    *
2704    * @param access_id the HMAC key `access_id()` that you want to delete.  Each
2705    *     HMAC key is assigned an `access_id()` attribute at creation time.
2706    * @param resource the desired changes to the HMAC key resource. Only the
2707    *     `state` field may be changed. The `etag` field may be set but it is
2708    *     only used as a pre-condition, the application cannot set the `etag`.
2709    * @param options a list of optional query parameters and/or request headers.
2710    *     In addition to the options common to all requests, this operation
2711    *     accepts `OverrideDefaultProject`.
2712    *
2713    * @return This operation returns the new HMAC key metadata.
2714    *
2715    * @par Idempotency
2716    * This operation is only idempotent if the `etag` attribute in @p resource
2717    * is set, or if the `IfMatchEtag` option is set.
2718    *
2719    * @par Example
2720    * @snippet storage_service_account_samples.cc update hmac key
2721    *
2722    * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2723    *     general information on using HMAC keys for Google Cloud Platform
2724    *     service accounts authentication.
2725    *
2726    * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2727    *     for a detailed description on how to use the feature.
2728    */
2729   template <typename... Options>
UpdateHmacKey(std::string access_id,HmacKeyMetadata resource,Options &&...options)2730   StatusOr<HmacKeyMetadata> UpdateHmacKey(std::string access_id,
2731                                           HmacKeyMetadata resource,
2732                                           Options&&... options) {
2733     auto const& project_id = raw_client_->client_options().project_id();
2734     internal::UpdateHmacKeyRequest request(project_id, std::move(access_id),
2735                                            std::move(resource));
2736     request.set_multiple_options(std::forward<Options>(options)...);
2737     return raw_client_->UpdateHmacKey(request);
2738   }
2739   //@}
2740 
2741   //@{
2742   /// @name Signed URL support operations.
2743   /**
2744    * Create a V2 signed URL for the given parameters.
2745    *
2746    * @note By default URLs created with this function expire after 7 days.
2747    *
2748    * @note The application must ensure that any URL created with this function
2749    *     is a valid request via the XML API. For example, the options for
2750    *     bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2751    *     not all sub-resources are valid for objects.  Likewise, only a single
2752    *     sub-resource may be retrieved in each request.
2753    *
2754    * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2755    *     `PUT`, `HEAD`, etc. are valid values.
2756    * @param bucket_name the name of the bucket.
2757    * @param object_name the name of the object, note that the object may not
2758    *     exist for signed URLs that upload new objects. Use an empty string for
2759    *     requests that only affect a bucket.
2760    * @param options a list of optional parameters for the signed URL, this
2761    *     include: `ExpirationTime`, `MD5HashValue`, `ContentType`,
2762    *     `SigningAccount`, `SigningAccountDelegates`,
2763    *     `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2764    *     `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2765    *     option has any effect.
2766    *
2767    * @par Helper Functions
2768    *
2769    * The following functions create a `AddSubResourceOption` with less
2770    * opportunities for typos in the sub-resource name: `WithAcl()`,
2771    * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2772    * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2773    * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2774    *
2775    * Likewise, the following helper functions can create properly formatted
2776    * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2777    * `WithGenerationMarker()`, `WithMarker()`,
2778    * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2779    * `WithUserProject()`.
2780    *
2781    * @return the signed URL.
2782    *
2783    * @par Example
2784    * @snippet storage_signed_url_v2_samples.cc sign url v2
2785    *
2786    * @par Example
2787    * @snippet storage_signed_url_v2_samples.cc create put signed url v2
2788    *
2789    * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2790    *     a general description of signed URLs and how they can be used.
2791    *
2792    * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2793    *     description of the XML API.
2794    */
2795   template <typename... Options>
CreateV2SignedUrl(std::string verb,std::string bucket_name,std::string object_name,Options &&...options)2796   StatusOr<std::string> CreateV2SignedUrl(std::string verb,
2797                                           std::string bucket_name,
2798                                           std::string object_name,
2799                                           Options&&... options) {
2800     internal::V2SignUrlRequest request(std::move(verb), std::move(bucket_name),
2801                                        std::move(object_name));
2802     request.set_multiple_options(std::forward<Options>(options)...);
2803     return SignUrlV2(request);
2804   }
2805 
2806   /**
2807    * Create a V4 signed URL for the given parameters.
2808    *
2809    * @note By default URLs created with this function expire after 7 days.
2810    *
2811    * @note The application must ensure that any URL created with this function
2812    *     is a valid request via the XML API. For example, the options for
2813    *     bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2814    *     not all sub-resources are valid for objects.  Likewise, only a single
2815    *     sub-resource may be retrieved in each request.
2816    *
2817    * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2818    *     `PUT`, `HEAD`, etc. are valid values.
2819    * @param bucket_name the name of the bucket.
2820    * @param object_name the name of the object, note that the object may not
2821    *     exist for signed URLs that upload new objects. Use an empty string for
2822    *     requests that only affect a bucket.
2823    * @param options a list of optional parameters for the signed URL, this
2824    *     include: `SignedUrlTimestamp`, `SignedUrlDuration`, `MD5HashValue`,
2825    *     `ContentType`, `SigningAccount`, `SigningAccountDelegates`,
2826    *     `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2827    *     `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2828    *     option has any effect.
2829    *
2830    * @par Helper Functions
2831    *
2832    * The following functions create a `AddSubResourceOption` with less
2833    * opportunities for typos in the sub-resource name: `WithAcl()`,
2834    * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2835    * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2836    * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2837    *
2838    * Likewise, the following helper functions can create properly formatted
2839    * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2840    * `WithGenerationMarker()`, `WithMarker()`,
2841    * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2842    * `WithUserProject()`.
2843    *
2844    * @return the signed URL.
2845    *
2846    * @par Example
2847    * @snippet storage_signed_url_v4_samples.cc sign url v4
2848    *
2849    * @par Example
2850    * @snippet storage_signed_url_v4_samples.cc create put signed url v4
2851    *
2852    * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2853    *     a general description of signed URLs and how they can be used.
2854    *
2855    * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2856    *     description of the XML API.
2857    */
2858   template <typename... Options>
CreateV4SignedUrl(std::string verb,std::string bucket_name,std::string object_name,Options &&...options)2859   StatusOr<std::string> CreateV4SignedUrl(std::string verb,
2860                                           std::string bucket_name,
2861                                           std::string object_name,
2862                                           Options&&... options) {
2863     internal::V4SignUrlRequest request(std::move(verb), std::move(bucket_name),
2864                                        std::move(object_name));
2865     request.set_multiple_options(std::forward<Options>(options)...);
2866     return SignUrlV4(std::move(request));
2867   }
2868   //@}
2869 
2870   /**
2871    * Create a signed policy document.
2872    *
2873    * @note The application must ensure that any document created with this
2874    * function contains valid conditions. This function does not do any error
2875    * checking, e.g. that a `ExactMatchObject()` condition contains two
2876    * elements. Using the provided helper functions can prevent errors.
2877    *
2878    * @note It is the application's responsibility to construct a POST request
2879    * based on the value returned by this function.  For example, a web
2880    * application can create a HTML form containing these fields, the result of
2881    * which is a POST request to GCS.
2882    *
2883    * @param document the policy document.
2884    * @param options a list of optional parameters, this includes:
2885    *      `SigningAccount`, and `SigningAccountDelegates`.
2886    *
2887    * @par Helper Functions
2888    * The following functions create a `PolicyDocumentCondition` with less
2889    * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2890    * `ExactMatch()`, `ContentLengthRange()`.
2891    *
2892    * @par Example
2893    * @snippet storage_policy_doc_samples.cc create signed policy document
2894    *
2895    * @see
2896    * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2897    *     for a general description of policy documents and how they can be used.
2898    *
2899    * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2900    *     description of the XML API.
2901    */
2902   template <typename... Options>
CreateSignedPolicyDocument(PolicyDocument document,Options &&...options)2903   StatusOr<PolicyDocumentResult> CreateSignedPolicyDocument(
2904       PolicyDocument document, Options&&... options) {
2905     internal::PolicyDocumentRequest request(std::move(document));
2906     request.set_multiple_options(std::forward<Options>(options)...);
2907     return SignPolicyDocument(request);
2908   }
2909 
2910   /**
2911    * Create a signed V4 policy document.
2912    *
2913    * @note The application must ensure that any document created with this
2914    * function contains valid conditions. This function does not do any error
2915    * checking, e.g. that a `ExactMatchObject()` condition contains two
2916    * elements. Using the provided helper functions can prevent errors.
2917    *
2918    * @note It is the application's responsibility to construct a POST request
2919    * based on the value returned by this function.  For example, a web
2920    * application can create a HTML form containing these fields, the result of
2921    * which is a POST request to GCS.
2922    *
2923    * @param document the policy document.
2924    * @param options a list of optional parameters, this includes:
2925    * `AddExtensionFieldOption`, `BucketBoundHostname`, `PredefinedAcl`,
2926    * `Scheme`, `SigningAccountDelegates`, `SigningAccount`, `VirtualHostname`
2927    *
2928    * @par Helper Functions
2929    * The following functions create a `PolicyDocumentCondition` with less
2930    * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2931    * `ExactMatch()`, `ContentLengthRange()`.
2932    *
2933    * @par Example
2934    * @snippet storage_policy_doc_samples.cc create signed policy document v4
2935    *
2936    * @see
2937    * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2938    *     for a general description of policy documents and how they can be used.
2939    *
2940    * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2941    *     description of the XML API.
2942    */
2943   template <typename... Options>
GenerateSignedPostPolicyV4(PolicyDocumentV4 document,Options &&...options)2944   StatusOr<PolicyDocumentV4Result> GenerateSignedPostPolicyV4(
2945       PolicyDocumentV4 document, Options&&... options) {
2946     internal::PolicyDocumentV4Request request(std::move(document));
2947     request.set_multiple_options(std::forward<Options>(options)...);
2948     return SignPolicyDocumentV4(std::move(request));
2949   }
2950 
2951   //@{
2952   /**
2953    * @name Pub/Sub operations.
2954    *
2955    * Cloud Pub/Sub Notifications sends information about changes to objects in
2956    * your buckets to Cloud Pub/Sub, where the information is added to a Cloud
2957    * Pub/Sub topic of your choice in the form of messages.
2958    *
2959    * @see https://cloud.google.com/storage/docs/pubsub-notifications for more
2960    *     information about Cloud Pub/Sub in the context of GCS.
2961    */
2962   /**
2963    * Retrieves the list of Notifications for a Bucket.
2964    *
2965    * Cloud Pub/Sub Notifications sends information about changes to objects
2966    * in your buckets to Google Cloud Pub/Sub service.
2967    *
2968    * @param bucket_name the name of the bucket.
2969    * @param options a list of optional query parameters and/or request headers.
2970    *     Valid types for this operation include `UserProject`.
2971    *
2972    * @par Idempotency
2973    * This is a read-only operation and is always idempotent.
2974    *
2975    * @par Example
2976    * @snippet storage_notification_samples.cc list notifications
2977    */
2978   template <typename... Options>
ListNotifications(std::string const & bucket_name,Options &&...options)2979   StatusOr<std::vector<NotificationMetadata>> ListNotifications(
2980       std::string const& bucket_name, Options&&... options) {
2981     internal::ListNotificationsRequest request(bucket_name);
2982     request.set_multiple_options(std::forward<Options>(options)...);
2983     auto result = raw_client_->ListNotifications(request);
2984     if (!result) {
2985       return std::move(result).status();
2986     }
2987     return std::move(result).value().items;
2988   }
2989 
2990   /**
2991    * Creates a new notification config for a Bucket.
2992    *
2993    * Cloud Pub/Sub Notifications sends information about changes to objects
2994    * in your buckets to Google Cloud Pub/Sub service. You can create multiple
2995    * notifications per Bucket, with different topics and filtering options.
2996    *
2997    * @param bucket_name the name of the bucket.
2998    * @param topic_name the Google Cloud Pub/Sub topic that will receive the
2999    *     notifications. This requires the full name of the topic, i.e.:
3000    *     `projects/<PROJECT_ID>/topics/<TOPIC_ID>`.
3001    * @param payload_format how will the data be formatted in the notifications,
3002    *     consider using the helpers in the `payload_format` namespace, or
3003    *     specify one of the valid formats defined in:
3004    *     https://cloud.google.com/storage/docs/json_api/v1/notifications
3005    * @param metadata define any optional parameters for the notification, such
3006    *     as the list of event types, or any custom attributes.
3007    * @param options a list of optional query parameters and/or request headers.
3008    *     Valid types for this operation include `UserProject`.
3009    *
3010    * @par Idempotency
3011    * This operation is only idempotent if restricted by pre-conditions. There
3012    * are no pre-conditions for this operation that can make it idempotent.
3013    *
3014    * @par Example
3015    * @snippet storage_notification_samples.cc create notification
3016    *
3017    * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3018    *     information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3019    *
3020    * @see https://cloud.google.com/pubsub/ for general information on Google
3021    *     Cloud Pub/Sub service.
3022    */
3023   template <typename... Options>
CreateNotification(std::string const & bucket_name,std::string const & topic_name,std::string const & payload_format,NotificationMetadata metadata,Options &&...options)3024   StatusOr<NotificationMetadata> CreateNotification(
3025       std::string const& bucket_name, std::string const& topic_name,
3026       std::string const& payload_format, NotificationMetadata metadata,
3027       Options&&... options) {
3028     metadata.set_topic(topic_name).set_payload_format(payload_format);
3029     internal::CreateNotificationRequest request(bucket_name, metadata);
3030     request.set_multiple_options(std::forward<Options>(options)...);
3031     return raw_client_->CreateNotification(request);
3032   }
3033 
3034   /**
3035    * Gets the details about a notification config in a given Bucket.
3036    *
3037    * Cloud Pub/Sub Notifications sends information about changes to objects
3038    * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3039    * notifications per Bucket, with different topics and filtering options. This
3040    * function fetches the detailed information for a given notification config.
3041    *
3042    * @param bucket_name the name of the bucket.
3043    * @param notification_id the id of the notification config.
3044    * @param options a list of optional query parameters and/or request headers.
3045    *     Valid types for this operation include `UserProject`.
3046    *
3047    * @par Idempotency
3048    * This is a read-only operation and is always idempotent.
3049    *
3050    * @par Example
3051    * @snippet storage_notification_samples.cc get notification
3052    *
3053    * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3054    *     information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3055    *
3056    * @see https://cloud.google.com/pubsub/ for general information on Google
3057    *     Cloud Pub/Sub service.
3058    */
3059   template <typename... Options>
GetNotification(std::string const & bucket_name,std::string const & notification_id,Options &&...options)3060   StatusOr<NotificationMetadata> GetNotification(
3061       std::string const& bucket_name, std::string const& notification_id,
3062       Options&&... options) {
3063     internal::GetNotificationRequest request(bucket_name, notification_id);
3064     request.set_multiple_options(std::forward<Options>(options)...);
3065     return raw_client_->GetNotification(request);
3066   }
3067 
3068   /**
3069    * Delete an existing notification config in a given Bucket.
3070    *
3071    * Cloud Pub/Sub Notifications sends information about changes to objects
3072    * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3073    * notifications per Bucket, with different topics and filtering options. This
3074    * function deletes one of the notification configs.
3075    *
3076    * @param bucket_name the name of the bucket.
3077    * @param notification_id the id of the notification config.
3078    * @param options a list of optional query parameters and/or request headers.
3079    *     Valid types for this operation include `UserProject`.
3080    *
3081    * @par Idempotency
3082    * This operation is always idempotent because it only acts on a specific
3083    * `notification_id`, the state after calling this function multiple times is
3084    * to delete that notification.  New notifications get different ids.
3085    *
3086    * @par Example
3087    * @snippet storage_notification_samples.cc delete notification
3088    *
3089    * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3090    *     information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3091    *
3092    * @see https://cloud.google.com/pubsub/ for general information on Google
3093    *     Cloud Pub/Sub service.
3094    */
3095   template <typename... Options>
DeleteNotification(std::string const & bucket_name,std::string const & notification_id,Options &&...options)3096   Status DeleteNotification(std::string const& bucket_name,
3097                             std::string const& notification_id,
3098                             Options&&... options) {
3099     internal::DeleteNotificationRequest request(bucket_name, notification_id);
3100     request.set_multiple_options(std::forward<Options>(options)...);
3101     return std::move(raw_client_->DeleteNotification(request)).status();
3102   }
3103   //@}
3104 
3105  private:
3106   Client() = default;
3107   static std::shared_ptr<internal::RawClient> CreateDefaultInternalClient(
3108       ClientOptions options);
3109 
3110   template <typename... Policies>
Decorate(std::shared_ptr<internal::RawClient> client,Policies &&...policies)3111   std::shared_ptr<internal::RawClient> Decorate(
3112       std::shared_ptr<internal::RawClient> client, Policies&&... policies) {
3113     if (client->client_options().enable_raw_client_tracing()) {
3114       client = std::make_shared<internal::LoggingClient>(std::move(client));
3115     }
3116     auto retry = std::make_shared<internal::RetryClient>(
3117         std::move(client), std::forward<Policies>(policies)...);
3118     return retry;
3119   }
3120 
3121   ObjectReadStream ReadObjectImpl(
3122       internal::ReadObjectRangeRequest const& request);
3123 
3124   ObjectWriteStream WriteObjectImpl(
3125       internal::ResumableUploadRequest const& request);
3126 
3127   // The version of UploadFile() where UseResumableUploadSession is one of the
3128   // options. Note how this does not use InsertObjectMedia at all.
3129   template <typename... Options>
UploadFileImpl(std::string const & file_name,std::string const & bucket_name,std::string const & object_name,std::true_type,Options &&...options)3130   StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3131                                           std::string const& bucket_name,
3132                                           std::string const& object_name,
3133                                           std::true_type,
3134                                           Options&&... options) {
3135     internal::ResumableUploadRequest request(bucket_name, object_name);
3136     request.set_multiple_options(std::forward<Options>(options)...);
3137     return UploadFileResumable(file_name, std::move(request));
3138   }
3139 
3140   // The version of UploadFile() where UseResumableUploadSession is *not* one of
3141   // the options. In this case we can use InsertObjectMediaRequest because it
3142   // is safe.
3143   template <typename... Options>
UploadFileImpl(std::string const & file_name,std::string const & bucket_name,std::string const & object_name,std::false_type,Options &&...options)3144   StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3145                                           std::string const& bucket_name,
3146                                           std::string const& object_name,
3147                                           std::false_type,
3148                                           Options&&... options) {
3149     std::size_t file_size = 0;
3150     if (UseSimpleUpload(file_name, file_size)) {
3151       internal::InsertObjectMediaRequest request(bucket_name, object_name,
3152                                                  std::string{});
3153       request.set_multiple_options(std::forward<Options>(options)...);
3154       return UploadFileSimple(file_name, file_size, request);
3155     }
3156     internal::ResumableUploadRequest request(bucket_name, object_name);
3157     request.set_multiple_options(std::forward<Options>(options)...);
3158     return UploadFileResumable(file_name, std::move(request));
3159   }
3160 
3161   bool UseSimpleUpload(std::string const& file_name, std::size_t& size) const;
3162 
3163   StatusOr<ObjectMetadata> UploadFileSimple(
3164       std::string const& file_name, std::size_t file_size,
3165       internal::InsertObjectMediaRequest request);
3166 
3167   StatusOr<ObjectMetadata> UploadFileResumable(
3168       std::string const& file_name, internal::ResumableUploadRequest request);
3169 
3170   StatusOr<ObjectMetadata> UploadStreamResumable(
3171       std::istream& source, internal::ResumableUploadRequest const& request);
3172 
3173   Status DownloadFileImpl(internal::ReadObjectRangeRequest const& request,
3174                           std::string const& file_name);
3175 
3176   /// Determine the email used to sign a blob.
3177   std::string SigningEmail(SigningAccount const& signing_account);
3178 
3179   /// Represents the result of signing a blob, including the key used in the
3180   /// signature.
3181   struct SignBlobResponseRaw {
3182     std::string key_id;
3183     std::vector<std::uint8_t> signed_blob;
3184   };
3185 
3186   /// Sign a blob.
3187   StatusOr<SignBlobResponseRaw> SignBlobImpl(
3188       SigningAccount const& signing_account, std::string const& string_to_sign);
3189 
3190   StatusOr<std::string> SignUrlV2(internal::V2SignUrlRequest const& request);
3191   StatusOr<std::string> SignUrlV4(internal::V4SignUrlRequest request);
3192 
3193   StatusOr<PolicyDocumentResult> SignPolicyDocument(
3194       internal::PolicyDocumentRequest const& request);
3195   StatusOr<PolicyDocumentV4Result> SignPolicyDocumentV4(
3196       internal::PolicyDocumentV4Request request);
3197 
3198   std::shared_ptr<internal::RawClient> raw_client_;
3199 
3200   friend class internal::NonResumableParallelUploadState;
3201   friend class internal::ResumableParallelUploadState;
3202   friend class testing::ClientTester;
3203 };
3204 
3205 /**
3206  * Create a random prefix for object names.
3207  *
3208  * This is useful for operations which require a unique prefix for temporary
3209  * files.
3210  *
3211  * This is a helper function and it doesn't communicate with GCS, so there is a
3212  * very small chance that names generated this way aren't unique. The chance
3213  * should be small enough to fit any error budget.
3214  *
3215  * Given the same `prefix`, the randomly generated names will have the same
3216  * length.
3217  *
3218  * @param prefix the prefix of the prefix to be created.
3219  * @return the random prefix name
3220  */
3221 std::string CreateRandomPrefixName(std::string const& prefix = "");
3222 
3223 namespace internal {
3224 
3225 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3226 struct DeleteApplyHelper {
3227   template <typename... Options>
operatorDeleteApplyHelper3228   Status operator()(Options... options) const {
3229     return client.DeleteObject(bucket_name, object_name, std::move(options)...);
3230   }
3231 
3232   Client& client;
3233   std::string bucket_name;
3234   std::string object_name;
3235 };
3236 
3237 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3238 struct InsertObjectApplyHelper {
3239   template <typename... Options>
operatorInsertObjectApplyHelper3240   StatusOr<ObjectMetadata> operator()(Options... options) const {
3241     return client.InsertObject(bucket_name, object_name, std::move(contents),
3242                                std::move(options)...);
3243   }
3244 
3245   Client& client;
3246   std::string const& bucket_name;
3247   std::string const& object_name;
3248   std::string contents;
3249 };
3250 
3251 /**
3252  * Create a "marker" object to ensure that two tasks cannot share a prefix.
3253  *
3254  * @param client the client on which to perform the operation.
3255  * @param bucket_name the name of the bucket that will contain the object.
3256  * @param prefix the prefix of the objects to be deleted.
3257  * @param options a list of optional query parameters and/or request headers.
3258  *      Valid types for this operation include `EncryptionKey` `KmsKeyName`,
3259  *     `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
3260  *     Contrary to the public API, invalid options will be silently ignored
3261  *     for ease of use.
3262  * @return the metadata of the marker
3263  */
3264 template <typename... Options>
LockPrefix(Client & client,std::string const & bucket_name,std::string const & prefix,Options &&...options)3265 StatusOr<ObjectMetadata> LockPrefix(Client& client,
3266                                     std::string const& bucket_name,
3267                                     std::string const& prefix,
3268                                     Options&&... options) {
3269   return google::cloud::internal::apply(
3270       internal::InsertObjectApplyHelper{client, bucket_name, prefix, ""},
3271       std::tuple_cat(
3272           std::make_tuple(IfGenerationMatch(0)),
3273           internal::StaticTupleFilter<
3274               internal::Among<EncryptionKey, KmsKeyName, PredefinedAcl,
3275                               Projection, UserProject>::TPred>(
3276               std::forward_as_tuple(std::forward<Options>(options)...))));
3277 }
3278 
3279 }  // namespace internal
3280 
3281 /**
3282  * Delete objects whose names match a given prefix
3283  *
3284  * @param client the client on which to perform the operation.
3285  * @param bucket_name the name of the bucket that will contain the object.
3286  * @param prefix the prefix of the objects to be deleted.
3287  * @param options a list of optional query parameters and/or request headers.
3288  *     Valid types for this operation include `QuotaUser`, `UserIp`,
3289  *     `UserProject` and `Versions`.
3290  */
3291 template <typename... Options>
DeleteByPrefix(Client & client,std::string const & bucket_name,std::string const & prefix,Options &&...options)3292 Status DeleteByPrefix(Client& client, std::string const& bucket_name,
3293                       std::string const& prefix, Options&&... options) {
3294   using internal::NotAmong;
3295   using internal::StaticTupleFilter;
3296 
3297   auto all_options = std::tie(options...);
3298 
3299   static_assert(
3300       std::tuple_size<decltype(
3301               StaticTupleFilter<
3302                   NotAmong<QuotaUser, UserIp, UserProject, Versions>::TPred>(
3303                   all_options))>::value == 0,
3304       "This functions accepts only options of type QuotaUser, UserIp, "
3305       "UserProject or Versions.");
3306   for (auto const& object :
3307        client.ListObjects(bucket_name, Projection::NoAcl(), Prefix(prefix),
3308                           std::forward<Options>(options)...)) {
3309     if (!object) {
3310       return object.status();
3311     }
3312 
3313     auto deletion_status = google::cloud::internal::apply(
3314         internal::DeleteApplyHelper{client, bucket_name, object->name()},
3315         std::tuple_cat(
3316             std::make_tuple(IfGenerationMatch(object->generation())),
3317             StaticTupleFilter<NotAmong<Versions>::TPred>(all_options)));
3318 
3319     if (!deletion_status.ok()) {
3320       return deletion_status;
3321     }
3322   }
3323   return Status();
3324 }
3325 
3326 namespace internal {
3327 
3328 // Just a wrapper to allow for use in `google::cloud::internal::apply`.
3329 struct ComposeApplyHelper {
3330   template <typename... Options>
operatorComposeApplyHelper3331   StatusOr<ObjectMetadata> operator()(Options... options) const {
3332     return client.ComposeObject(
3333         std::move(bucket_name), std::move(source_objects),
3334         std::move(destination_object_name), std::move(options)...);
3335   }
3336 
3337   Client& client;
3338   std::string bucket_name;
3339   std::vector<ComposeSourceObject> source_objects;
3340   std::string destination_object_name;
3341 };
3342 
3343 // A helper to defer deletion of temporary GCS objects.
3344 class ScopedDeleter {
3345  public:
3346   // The actual deletion depends on local's types in a very non-trivial way,
3347   // so we abstract this away by providing the function to delete one object.
3348   // NOLINTNEXTLINE(google-explicit-constructor)
3349   ScopedDeleter(std::function<Status(std::string, std::int64_t)> delete_fun);
3350   ScopedDeleter(ScopedDeleter const&) = delete;
3351   ScopedDeleter& operator=(ScopedDeleter const&) = delete;
3352   ~ScopedDeleter();
3353 
3354   /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3355   void Add(ObjectMetadata const& object);
3356 
3357   /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3358   void Add(std::string object_name, std::int64_t generation);
3359 
3360   /// Execute all the deferred deletions now.
3361   Status ExecuteDelete();
3362 
Enable(bool enable)3363   void Enable(bool enable) { enabled_ = enable; }
3364 
3365  private:
3366   bool enabled_;
3367   std::function<Status(std::string, std::int64_t)> delete_fun_;
3368   std::vector<std::pair<std::string, std::int64_t>> object_list_;
3369 };
3370 
3371 }  // namespace internal
3372 
3373 /**
3374  * Compose existing objects into a new object in the same bucket.
3375  *
3376  * Contrary to `Client::ComposeObject`, this function doesn't have a limit on
3377  * the number of source objects.
3378  *
3379  * The implementation may need to perform multiple Client::ComposeObject calls
3380  * to create intermediate, temporary objects which are then further composed.
3381  * Due to the lack of atomicity of this series of operations, stray temporary
3382  * objects might be left over if there are transient failures. In order to allow
3383  * the user to easily control for such situations, the user is expected to
3384  * provide a unique @p prefix parameter, which will become the prefix of all the
3385  * temporary objects created by this function. Once this function finishes, the
3386  * user may safely remove all objects with the provided prefix (e.g. via
3387  * DeleteByPrefix()). We recommend using CreateRandomPrefixName() for selecting
3388  * a random prefix within a bucket.
3389  *
3390  * @param client the client on which to perform the operations needed by this
3391  *     function
3392  * @param bucket_name the name of the bucket used for source object and
3393  *     destination object.
3394  * @param source_objects objects used to compose `destination_object_name`.
3395  * @param destination_object_name the composed object name.
3396  * @param prefix prefix for temporary objects created by this function; there
3397  *     should not be any objects with this prefix; in order to avoid race
3398  *     conditions, this function will create an object with this name
3399  * @param ignore_cleanup_failures if the composition succeeds but cleanup of
3400  *     temporary objects fails, depending on this parameter either a success
3401  *     will be returned (`true`) or the relevant cleanup error (`false`)
3402  * @param options a list of optional query parameters and/or request headers.
3403  *     Valid types for this operation include `DestinationPredefinedAcl`,
3404  *     `EncryptionKey`, `IfGenerationMatch`, `IfMetagenerationMatch`
3405  *     `KmsKeyName`, `QuotaUser`, `UserIp`, `UserProject` and
3406  *     `WithObjectMetadata`.
3407  *
3408  * @par Idempotency
3409  * This operation is not idempotent. While each request performed by this
3410  * function is retried based on the client policies, the operation itself stops
3411  * on the first request that fails.
3412  *
3413  * @par Example
3414  * @snippet storage_object_samples.cc compose object from many
3415  */
3416 template <typename... Options>
ComposeMany(Client & client,std::string const & bucket_name,std::vector<ComposeSourceObject> source_objects,std::string const & prefix,std::string destination_object_name,bool ignore_cleanup_failures,Options &&...options)3417 StatusOr<ObjectMetadata> ComposeMany(
3418     Client& client, std::string const& bucket_name,
3419     std::vector<ComposeSourceObject> source_objects, std::string const& prefix,
3420     std::string destination_object_name, bool ignore_cleanup_failures,
3421     Options&&... options) {
3422   using internal::Among;
3423   using internal::NotAmong;
3424   using internal::StaticTupleFilter;
3425   std::size_t const max_num_objects = 32;
3426 
3427   if (source_objects.empty()) {
3428     return Status(StatusCode::kInvalidArgument,
3429                   "ComposeMany requires at least one source object.");
3430   }
3431 
3432   auto all_options = std::make_tuple(options...);
3433 
3434   // TODO(#3247): this list of type should somehow be generated
3435   static_assert(
3436       std::tuple_size<decltype(
3437               StaticTupleFilter<NotAmong<
3438                   DestinationPredefinedAcl, EncryptionKey, IfGenerationMatch,
3439                   IfMetagenerationMatch, KmsKeyName, QuotaUser, UserIp,
3440                   UserProject, WithObjectMetadata>::TPred>(
3441                   all_options))>::value == 0,
3442       "This functions accepts only options of type DestinationPredefinedAcl, "
3443       "EncryptionKey, IfGenerationMatch, IfMetagenerationMatch, KmsKeyName, "
3444       "QuotaUser, UserIp, UserProject or WithObjectMetadata.");
3445 
3446   internal::ScopedDeleter deleter(
3447       [&](std::string const& object_name, std::int64_t generation) {
3448         return google::cloud::internal::apply(
3449             internal::DeleteApplyHelper{client, bucket_name, object_name},
3450             std::tuple_cat(
3451                 std::make_tuple(IfGenerationMatch(generation)),
3452                 StaticTupleFilter<Among<QuotaUser, UserProject, UserIp>::TPred>(
3453                     all_options)));
3454       });
3455 
3456   auto lock = internal::LockPrefix(client, bucket_name, prefix, "",
3457                                    std::make_tuple(options...));
3458   if (!lock) {
3459     return Status(
3460         lock.status().code(),
3461         "Failed to lock prefix for ComposeMany: " + lock.status().message());
3462   }
3463   deleter.Add(*lock);
3464 
3465   std::size_t num_tmp_objects = 0;
3466   auto tmpobject_name_gen = [&num_tmp_objects, &prefix] {
3467     return prefix + ".compose-tmp-" + std::to_string(num_tmp_objects++);
3468   };
3469 
3470   auto to_source_objects = [](std::vector<ObjectMetadata> objects) {
3471     std::vector<ComposeSourceObject> sources(objects.size());
3472     std::transform(objects.begin(), objects.end(), sources.begin(),
3473                    [](ObjectMetadata const& m) {
3474                      return ComposeSourceObject{m.name(), m.generation(), {}};
3475                    });
3476     return sources;
3477   };
3478 
3479   auto composer = [&](std::vector<ComposeSourceObject> compose_range,
3480                       bool is_final) -> StatusOr<ObjectMetadata> {
3481     if (is_final) {
3482       return google::cloud::internal::apply(
3483           internal::ComposeApplyHelper{client, bucket_name,
3484                                        std::move(compose_range),
3485                                        std::move(destination_object_name)},
3486           std::tuple_cat(std::make_tuple(IfGenerationMatch(0)), all_options));
3487     }
3488     return google::cloud::internal::apply(
3489         internal::ComposeApplyHelper{client, bucket_name,
3490                                      std::move(compose_range),
3491                                      tmpobject_name_gen()},
3492         StaticTupleFilter<
3493             NotAmong<IfGenerationMatch, IfMetagenerationMatch>::TPred>(
3494             all_options));
3495   };
3496 
3497   auto reduce = [&](std::vector<ComposeSourceObject> source_objects)
3498       -> StatusOr<std::vector<ObjectMetadata>> {
3499     std::vector<ObjectMetadata> objects;
3500     for (auto range_begin = source_objects.begin();
3501          range_begin != source_objects.end();) {
3502       std::size_t range_size = std::min<std::size_t>(
3503           std::distance(range_begin, source_objects.end()), max_num_objects);
3504       auto range_end = std::next(range_begin, range_size);
3505       std::vector<ComposeSourceObject> compose_range(range_size);
3506       std::move(range_begin, range_end, compose_range.begin());
3507 
3508       bool const is_final_composition =
3509           source_objects.size() <= max_num_objects;
3510       auto object = composer(std::move(compose_range), is_final_composition);
3511       if (!object) {
3512         return std::move(object).status();
3513       }
3514       objects.push_back(*std::move(object));
3515       if (!is_final_composition) {
3516         deleter.Add(objects.back());
3517       }
3518       range_begin = range_end;
3519     }
3520     return objects;
3521   };
3522 
3523   StatusOr<ObjectMetadata> result;
3524   do {
3525     StatusOr<std::vector<ObjectMetadata>> objects = reduce(source_objects);
3526     if (!objects) {
3527       return objects.status();
3528     }
3529     if (objects->size() == 1) {
3530       if (!ignore_cleanup_failures) {
3531         auto delete_status = deleter.ExecuteDelete();
3532         if (!delete_status.ok()) {
3533           return delete_status;
3534         }
3535       }
3536       result = std::move((*objects)[0]);
3537       break;
3538     }
3539     source_objects = to_source_objects(*std::move(objects));
3540   } while (source_objects.size() > 1);
3541   return result;
3542 }
3543 
3544 }  // namespace STORAGE_CLIENT_NS
3545 }  // namespace storage
3546 }  // namespace cloud
3547 }  // namespace google
3548 
3549 #endif  // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
3550