| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMECAST_CAST_CORE_GRPC_GRPC_STATUS_OR_H_ |
| #define CHROMECAST_CAST_CORE_GRPC_GRPC_STATUS_OR_H_ |
| |
| #include <grpcpp/support/status.h> |
| |
| #include <string> |
| #include <type_traits> |
| |
| #include <optional> |
| #include "base/check.h" |
| |
| namespace cast { |
| namespace utils { |
| |
| // Converts grpc::Status to a string message. |
| std::string GrpcStatusToString(const grpc::Status& status); |
| |
| // Holds a value of type T with grpc::Status::OK or an error grpc::Status. |
| template <typename T, |
| typename std::enable_if<!std::is_reference<T>::value, T*>::type = |
| nullptr> |
| class GrpcStatusOr { |
| public: |
| GrpcStatusOr() : status_(grpc::StatusCode::UNKNOWN, "") {} |
| |
| // Constructs GrpcStatusOr from an error |status_code|. |
| GrpcStatusOr(grpc::StatusCode status_code) // NOLINT |
| : GrpcStatusOr(status_code, "") {} |
| |
| // Constructs GrpcStatusOr from an error |status_code| and |error_message|. |
| GrpcStatusOr(grpc::StatusCode status_code, const std::string& error_message) |
| : status_(status_code, error_message) { |
| DCHECK(!status_.ok()); |
| } |
| |
| // Constructs GrpcStatusOr from an error |status|. |
| GrpcStatusOr(grpc::Status status) // NOLINT |
| : status_(std::move(status)) { |
| DCHECK(!status_.ok()); |
| } |
| |
| // Constructs GrpcStatusOr from the |data|. Status code is set to OK. |
| GrpcStatusOr(const T& data) // NOLINT |
| : status_(grpc::Status::OK), data_(data) {} |
| |
| // Constructs GrpcStatusOr from the |data|. Status code is set to OK. |
| GrpcStatusOr(T&& data) // NOLINT |
| : status_(grpc::Status::OK), data_(std::move(data)) {} |
| |
| // Constructs GrpcStatusOr from the |data| of type U that is possible to |
| // convert to type |T|. For example, std::unique_ptr<MockClass> converted to |
| // std::unique_ptr<Class>. Status code is set to OK. |
| template <typename U, |
| typename std::enable_if<std::is_constructible<T, U>::value, |
| U>::type* = nullptr> |
| GrpcStatusOr(U&& data) // NOLINT |
| : status_(grpc::Status::OK), data_(std::forward<U>(data)) {} |
| |
| GrpcStatusOr(GrpcStatusOr&&) = default; |
| GrpcStatusOr& operator=(GrpcStatusOr&&) = default; |
| GrpcStatusOr(const GrpcStatusOr&) = default; |
| GrpcStatusOr& operator=(const GrpcStatusOr&) = default; |
| ~GrpcStatusOr() = default; |
| |
| // Returns if status is OK. |
| bool ok() const { return status_.ok(); } |
| |
| // Returns const reference to gRPC status. |
| const grpc::Status& status() const& { return status_; } |
| |
| // Returns r-value to gRPC status. |
| grpc::Status&& status() && { return std::move(status_); } |
| |
| // Returns the pointer to the stored data. Checks if status is not OK. |
| T* operator->() { |
| DCHECK(status_.ok()); |
| return &*data_; |
| } |
| |
| // Returns the const pointer to the stored data. Checks if status is not OK. |
| const T* operator->() const { |
| DCHECK(status_.ok()); |
| return &*data_; |
| } |
| |
| // Returns the const reference to the stored data. Checks if status is not OK. |
| const T& operator*() const& { |
| DCHECK(status_.ok()); |
| return *data_; |
| } |
| |
| // Returns the lvalue-ref to the underlying value. Checks if status is not OK. |
| const T& value() const& { |
| DCHECK(status_.ok()); |
| return *data_; |
| } |
| |
| // Returns the rvalue-ref to the underlying value. To trigger this accessor, |
| // the status object needs to be moved first: std::move(status_).value(). |
| // Checks if status is not OK. |
| T&& value() && { |
| DCHECK(status_.ok()); |
| status_ = grpc::Status(grpc::StatusCode::UNKNOWN, ""); |
| return std::move(data_).value(); |
| } |
| |
| // Sets the data. |
| void emplace(T&& data) { |
| status_ = grpc::Status::OK; |
| data_.emplace(std::move(data)); |
| } |
| |
| std::string ToString() const { return GrpcStatusToString(status()); } |
| |
| private: |
| grpc::Status status_; |
| std::optional<T> data_; |
| }; |
| |
| } // namespace utils |
| } // namespace cast |
| |
| #endif // CHROMECAST_CAST_CORE_GRPC_GRPC_STATUS_OR_H_ |