Google Cloud C++ Client  2.1.0
C++ Client Library for Google Cloud Platform
status.h
Go to the documentation of this file.
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 // https://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_STATUS_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STATUS_H
17 
18 #include "google/cloud/version.h"
19 #include "absl/types/optional.h"
20 #include <iostream>
21 #include <memory>
22 #include <string>
23 #include <unordered_map>
24 
25 namespace google {
26 namespace cloud {
28 
29 /**
30  * Well-known status codes with `grpc::StatusCode`-compatible values.
31  *
32  * The semantics of these values are documented in:
33  * https://grpc.io/grpc/cpp/classgrpc_1_1_status.html
34  */
35 enum class StatusCode {
36  /// Not an error; returned on success.
37  kOk = 0,
38 
39  kCancelled = 1,
40  kUnknown = 2,
41  kInvalidArgument = 3,
43  kNotFound = 5,
44  kAlreadyExists = 6,
46  kUnauthenticated = 16,
49  kAborted = 10,
50  kOutOfRange = 11,
51  kUnimplemented = 12,
52  kInternal = 13,
53  kUnavailable = 14,
54  kDataLoss = 15,
55 };
56 
57 std::string StatusCodeToString(StatusCode code);
58 std::ostream& operator<<(std::ostream& os, StatusCode code);
59 
60 class Status;
61 namespace internal {
62 void SetPayload(Status&, std::string key, std::string payload);
63 absl::optional<std::string> GetPayload(Status const&, std::string const& key);
64 } // namespace internal
65 
66 /**
67  * Describes the cause of the error with structured details.
68  *
69  * @see https://cloud.google.com/apis/design/errors#error_info
70  */
71 class ErrorInfo {
72  public:
73  ErrorInfo() = default;
74  explicit ErrorInfo(std::string reason, std::string domain,
75  std::unordered_map<std::string, std::string> metadata)
76  : reason_(std::move(reason)),
77  domain_(std::move(domain)),
78  metadata_(std::move(metadata)) {}
79 
80  std::string const& reason() const { return reason_; }
81  std::string const& domain() const { return domain_; }
82  std::unordered_map<std::string, std::string> const& metadata() const {
83  return metadata_;
84  }
85 
86  friend bool operator==(ErrorInfo const&, ErrorInfo const&);
87  friend bool operator!=(ErrorInfo const&, ErrorInfo const&);
88 
89  private:
90  std::string reason_;
91  std::string domain_;
92  std::unordered_map<std::string, std::string> metadata_;
93 };
94 
95 /**
96  * Represents success or an error with info about the error.
97  *
98  * This class is typically used to indicate whether or not a function or other
99  * operation completed successfully. Success is indicated by an "OK" status. OK
100  * statuses will have `.code() == StatusCode::kOk` and `.ok() == true`, with
101  * all other properties having empty values. All OK statuses are equal. Any
102  * non-OK `Status` is considered an error. Users can inspect the error using
103  * the member functions, or they can simply stream the `Status` object, and it
104  * will print itself in some human readable way (the streamed format may change
105  * over time and you should *not* depend on the specific format of a streamed
106  * `Status` object remaining unchanged).
107  *
108  * This is a regular value type that can be copied, moved, compared for
109  * equality, and streamed.
110  */
111 class Status {
112  public:
114  ~Status();
115  Status(Status const&);
116  Status& operator=(Status const&);
117  Status(Status&&) noexcept;
118  Status& operator=(Status&&) noexcept;
119 
120  /**
121  * Constructs a Status with the given @p code and @p message.
122  *
123  * Ignores @p message if @p code is `StatusCode::kOk`.
124  */
125  explicit Status(StatusCode code, std::string message, ErrorInfo info = {});
126 
127  bool ok() const { return !impl_; }
128  StatusCode code() const;
129  std::string const& message() const;
130  ErrorInfo const& error_info() const;
131 
132  friend inline bool operator==(Status const& a, Status const& b) {
133  return (a.ok() && b.ok()) || Equals(a, b);
134  }
135  friend inline bool operator!=(Status const& a, Status const& b) {
136  return !(a == b);
137  }
138  friend std::ostream& operator<<(std::ostream& os, Status const& s);
139 
140  private:
141  static bool Equals(Status const& a, Status const& b);
142  friend void internal::SetPayload(Status&, std::string, std::string);
143  friend absl::optional<std::string> internal::GetPayload(Status const&,
144  std::string const&);
145 
146  class Impl;
147  // A null `impl_` is an OK status. Only non-OK Statuses allocate an Impl.
148  std::unique_ptr<Impl> impl_;
149 };
150 
151 /**
152  * A runtime error that wraps a `google::cloud::Status`.
153  */
154 class RuntimeStatusError : public std::runtime_error {
155  public:
156  explicit RuntimeStatusError(Status status);
157 
158  Status const& status() const { return status_; }
159 
160  private:
161  Status status_;
162 };
163 
165 } // namespace cloud
166 } // namespace google
167 
168 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STATUS_H