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_INTERNAL_COMPLEX_OPTION_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_COMPLEX_OPTION_H
17 
18 #include "google/cloud/storage/version.h"
19 #include "absl/types/optional.h"
20 #include <iostream>
21 
22 namespace google {
23 namespace cloud {
24 namespace storage {
25 inline namespace STORAGE_CLIENT_NS {
26 namespace internal {
27 /**
28  * A complex option is a request optional parameter that is neither a header
29  * nor a query parameter.
30  *
31  * The majority of the request options either change a header (or group of
32  * headers) or they set a query parameter. They are modeled using
33  * `WellKnownParameter` or `WellKnownHeader`. A few options do neither, they
34  * affect how the query is performed. Notably, we provide options where the
35  * user can provide pre-computed values for the MD5 hash and CRC32C values of
36  * an upload or download.
37  *
38  * @tparam Derived the type we will use to represent the option.
39  * @tparam T the C++ type of the option value.
40  */
41 template <typename Derived, typename T>
42 class ComplexOption {
43  public:
ComplexOption()44   ComplexOption() : value_{} {}
ComplexOption(T value)45   explicit ComplexOption(T value) : value_(std::move(value)) {}
46 
option_name()47   char const* option_name() const { return Derived::name(); }
has_value()48   bool has_value() const { return value_.has_value(); }
value()49   T const& value() const { return value_.value(); }
50   template <typename U>
value_or(U && default_val)51   T value_or(U&& default_val) {
52     return value_.value_or(std::forward<U>(default_val));
53   }
54 
55  private:
56   absl::optional<T> value_;
57 };
58 
59 template <typename Derived, typename T>
60 std::ostream& operator<<(std::ostream& os,
61                          ComplexOption<Derived, T> const& rhs) {
62   if (rhs.has_value()) {
63     return os << rhs.option_name() << "=" << rhs.value();
64   }
65   return os << rhs.option_name() << "=<not set>";
66 }
67 
68 }  // namespace internal
69 }  // namespace STORAGE_CLIENT_NS
70 }  // namespace storage
71 }  // namespace cloud
72 }  // namespace google
73 
74 #endif  // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_INTERNAL_COMPLEX_OPTION_H
75