// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H #define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H #include #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include // Helpers for dealing with absl::Status/StatusOr generically namespace grpc_core { namespace promise_detail { // Convert with a move the input status to an absl::Status. template absl::Status IntoStatus(absl::StatusOr* status) { return std::move(status->status()); } // Convert with a move the input status to an absl::Status. inline absl::Status IntoStatus(absl::Status* status) { return std::move(*status); } } // namespace promise_detail // Return true if the status represented by the argument is ok, false if not. // By implementing this function for other, non-absl::Status types, those types // can participate in TrySeq as result types that affect control flow. inline bool IsStatusOk(const absl::Status& status) { return status.ok(); } template inline bool IsStatusOk(const absl::StatusOr& status) { return status.ok(); } template struct StatusCastImpl; template struct StatusCastImpl { static To Cast(To&& t) { return std::move(t); } }; template struct StatusCastImpl { static To Cast(const To& t) { return t; } }; template struct StatusCastImpl> { static absl::Status Cast(absl::StatusOr&& t) { return std::move(t.status()); } }; template struct StatusCastImpl&> { static absl::Status Cast(const absl::StatusOr& t) { return t.status(); } }; template struct StatusCastImpl&> { static absl::Status Cast(const absl::StatusOr& t) { return t.status(); } }; // StatusCast<> allows casting from one status-bearing type to another, // regardless of whether the status indicates success or failure. // This means that we can go from StatusOr to Status safely, but not in the // opposite direction. // For cases where the status is guaranteed to be a failure (and hence not // needing to preserve values) see FailureStatusCast<> below. template To StatusCast(From&& from) { return StatusCastImpl::Cast(std::forward(from)); } template struct FailureStatusCastImpl : public StatusCastImpl {}; template struct FailureStatusCastImpl, absl::Status> { static absl::StatusOr Cast(absl::Status&& t) { return std::move(t); } }; template struct FailureStatusCastImpl, const absl::Status&> { static absl::StatusOr Cast(const absl::Status& t) { return t; } }; template To FailureStatusCast(From&& from) { DCHECK(!IsStatusOk(from)); return FailureStatusCastImpl::Cast(std::forward(from)); } } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H