Asylo
status_macros.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2018 Asylo authors
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef ASYLO_UTIL_STATUS_MACROS_H_
20 #define ASYLO_UTIL_STATUS_MACROS_H_
21 
22 #include <type_traits>
23 #include <utility>
24 
25 #include "absl/base/optimization.h"
26 #include "absl/status/status.h"
27 
28 namespace asylo {
29 namespace internal {
30 
31 // This template is chosen if the input object has a function called "status".
32 template <typename T>
33 inline constexpr bool HasStatus(decltype(std::declval<T>().status()) *) {
34  return true;
35 }
36 
37 // Default template, chosen when no prior templates match.
38 template <typename T>
39 inline constexpr bool HasStatus(...) {
40  return false;
41 }
42 
43 // `StatusOr`-like overload which returns a wrapped `Status`-like value.
44 template <typename T,
45  typename std::enable_if<HasStatus<T>(nullptr), int>::type = 0>
46 inline auto ToStatus(T&& status_or) -> decltype(status_or.status()) {
47  return status_or.status();
48 }
49 
50 // Identity function for all `Status`-like objects.
51 template <typename T,
52  typename std::enable_if<!HasStatus<T>(nullptr), int>::type = 0>
53 inline T ToStatus(T&& status_like) {
54  return status_like;
55 }
56 
57 } // namespace internal
58 } // namespace asylo
59 
60 /// Evaluates an expression that produces an `Status`-like object with
61 /// a `.ok()` method. If this method returns false, the object is
62 /// returned from the current function. If the expression evaluates to a
63 /// `StatusOr` object, then it is converted to a `Status` on return.
64 ///
65 /// Example:
66 /// ```
67 /// ::asylo::Status MultiStepFunction() {
68 /// ASYLO_RETURN_IF_ERROR(Function(args...));
69 /// ASYLO_RETURN_IF_ERROR(foo.Method(args...));
70 /// return ::absl::OkStatus();
71 /// }
72 /// ```
73 #define ASYLO_RETURN_IF_ERROR(expr) do
74  {
75  auto _asylo_status_to_verify = (expr);
76  if (ABSL_PREDICT_FALSE(!_asylo_status_to_verify.ok())) {
77  return ::asylo::internal::ToStatus(
78  std::forward<decltype(_asylo_status_to_verify)>(
79  _asylo_status_to_verify));
80  } \
81 }while (false)
82 
83 /// Evaluates an expression `rexpr` that returns a `StatusOr`-like
84 /// object with `.ok()`, `.status()`, and `.value()` methods. If
85 /// the result is OK, moves its value into the variable defined by
86 /// `lhs`, otherwise returns the result of the `.status()` from the
87 /// current function. The error result of `.status` is returned
88 /// unchanged. If there is an error, `lhs` is not evaluated: thus any
89 /// side effects of evaluating `lhs` will only occur if `rexpr.ok()`
90 /// is true.
91 ///
92 /// Interface:
93 /// ```
94 /// ASYLO_ASSIGN_OR_RETURN(lhs, rexpr)
95 /// ```
96 ///
97 /// Example: Assigning to an existing variable:
98 /// ```
99 /// ValueType value;
100 /// ASYLO_ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
101 /// ```
102 ///
103 /// Example: Assigning to an expression with side effects:
104 /// ```
105 /// MyProto data;
106 /// ASYLO_ASSIGN_OR_RETURN(*data.mutable_str(), MaybeGetValue(arg));
107 /// // No field "str" is added on error.
108 /// ```
109 ///
110 /// Example: Assigning to a `std::unique_ptr`.
111 /// ```
112 /// std::unique_ptr<T> ptr;
113 /// ASYLO_ASSIGN_OR_RETURN(ptr, MaybeGetPtr(arg));
114 /// ```
115 #define ASYLO_ASSIGN_OR_RETURN(lhs, rexpr)
116  do {
117  auto _asylo_status_or_value = (rexpr);
118  if (ABSL_PREDICT_FALSE(!_asylo_status_or_value.ok())) {
119  return _asylo_status_or_value.status();
120  }
121  lhs = std::move(_asylo_status_or_value).value();
122  } while (false)
123 
124 #endif // ASYLO_UTIL_STATUS_MACROS_H_
constexpr bool HasStatus(...)
Definition: status_macros.h:39
auto ToStatus(T &&status_or) -> decltype(status_or.status())
Definition: status_macros.h:46
ABSL_CONST_INIT const char kStatusMoveAssignmentMsg[]
Definition: status_macros.h:29
constexpr bool HasStatus(decltype(std::declval< T >().status()) *)
Definition: status_macros.h:33
T ToStatus(T &&status_like)
Definition: status_macros.h:53