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