1 // Copyright 2021 gRPC authors.
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 GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H
16 #define GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H
17
18 #include <grpc/support/port_platform.h>
19
20 #include <utility>
21
22 #include "absl/status/status.h"
23 #include "absl/status/statusor.h"
24
25 // Helpers for dealing with absl::Status/StatusOr generically
26
27 namespace grpc_core {
28 namespace promise_detail {
29
30 // Convert with a move the input status to an absl::Status.
31 template <typename T>
IntoStatus(absl::StatusOr<T> * status)32 absl::Status IntoStatus(absl::StatusOr<T>* status) {
33 return std::move(status->status());
34 }
35
36 // Convert with a move the input status to an absl::Status.
IntoStatus(absl::Status * status)37 inline absl::Status IntoStatus(absl::Status* status) {
38 return std::move(*status);
39 }
40
41 } // namespace promise_detail
42
43 // Return true if the status represented by the argument is ok, false if not.
44 // By implementing this function for other, non-absl::Status types, those types
45 // can participate in TrySeq as result types that affect control flow.
IsStatusOk(const absl::Status & status)46 inline bool IsStatusOk(const absl::Status& status) { return status.ok(); }
47
48 template <typename T>
IsStatusOk(const absl::StatusOr<T> & status)49 inline bool IsStatusOk(const absl::StatusOr<T>& status) {
50 return status.ok();
51 }
52
53 template <typename To, typename From, typename SfinaeVoid = void>
54 struct StatusCastImpl;
55
56 template <typename To>
57 struct StatusCastImpl<To, To> {
58 static To Cast(To&& t) { return std::move(t); }
59 };
60
61 template <typename To>
62 struct StatusCastImpl<To, const To&> {
63 static To Cast(const To& t) { return t; }
64 };
65
66 template <typename T>
67 struct StatusCastImpl<absl::Status, absl::StatusOr<T>> {
68 static absl::Status Cast(absl::StatusOr<T>&& t) {
69 return std::move(t.status());
70 }
71 };
72
73 template <typename T>
74 struct StatusCastImpl<absl::Status, absl::StatusOr<T>&> {
75 static absl::Status Cast(const absl::StatusOr<T>& t) { return t.status(); }
76 };
77
78 template <typename T>
79 struct StatusCastImpl<absl::Status, const absl::StatusOr<T>&> {
80 static absl::Status Cast(const absl::StatusOr<T>& t) { return t.status(); }
81 };
82
83 // StatusCast<> allows casting from one status-bearing type to another,
84 // regardless of whether the status indicates success or failure.
85 // This means that we can go from StatusOr to Status safely, but not in the
86 // opposite direction.
87 // For cases where the status is guaranteed to be a failure (and hence not
88 // needing to preserve values) see FailureStatusCast<> below.
89 template <typename To, typename From>
90 To StatusCast(From&& from) {
91 return StatusCastImpl<To, From>::Cast(std::forward<From>(from));
92 }
93
94 template <typename To, typename From, typename SfinaeVoid = void>
95 struct FailureStatusCastImpl : public StatusCastImpl<To, From> {};
96
97 template <typename T>
98 struct FailureStatusCastImpl<absl::StatusOr<T>, absl::Status> {
99 static absl::StatusOr<T> Cast(absl::Status&& t) { return std::move(t); }
100 };
101
102 template <typename T>
103 struct FailureStatusCastImpl<absl::StatusOr<T>, const absl::Status&> {
104 static absl::StatusOr<T> Cast(const absl::Status& t) { return t; }
105 };
106
107 template <typename To, typename From>
108 To FailureStatusCast(From&& from) {
109 GPR_DEBUG_ASSERT(!IsStatusOk(from));
110 return FailureStatusCastImpl<To, From>::Cast(std::forward<From>(from));
111 }
112
113 } // namespace grpc_core
114
115 #endif // GRPC_SRC_CORE_LIB_PROMISE_DETAIL_STATUS_H
116