• 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/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