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 
27 namespace asylo {
28 namespace internal {
29 
30 // This template is chosen if the input object has a function called "status".
31 template <typename T>
32 inline constexpr bool HasStatus(decltype(std::declval<T>().status()) *) {
33  return true;
34 }
35 
36 // Default template, chosen when no prior templates match.
37 template <typename T>
38 inline constexpr bool HasStatus(...) {
39  return false;
40 }
41 
42 // `StatusOr`-like overload which returns a wrapped `Status`-like value.
43 template <typename T,
44  typename std::enable_if<HasStatus<T>(nullptr), int>::type = 0>
45 inline auto ToStatus(T&& status_or) -> decltype(status_or.status()) {
46  return status_or.status();
47 }
48 
49 // Identity function for all `Status`-like objects.
50 template <typename T,
51  typename std::enable_if<!HasStatus<T>(nullptr), int>::type = 0>
52 inline T ToStatus(T&& status_like) {
53  return status_like;
54 }
55 
56 } // namespace internal
57 } // namespace asylo
58 
59 /// Evaluates an expression that produces an `Status`-like object with
60 /// a `.ok()` method. If this method returns false, the object is
61 /// returned from the current function. If the expression evaluates to a
62 /// `StatusOr` object, then it is converted to a `Status` on return.
63 ///
64 /// Example:
65 /// ```
66 /// ::asylo::Status MultiStepFunction() {
67 /// ASYLO_RETURN_IF_ERROR(Function(args...));
68 /// ASYLO_RETURN_IF_ERROR(foo.Method(args...));
69 /// return ::asylo::Status::OkStatus();
70 /// }
71 /// ```
72 #define ASYLO_RETURN_IF_ERROR(expr) do
73  {
74  auto _asylo_status_to_verify = (expr);
75  if (ABSL_PREDICT_FALSE(!_asylo_status_to_verify.ok())) {
76  return ::asylo::internal::ToStatus(
77  std::forward<decltype(_asylo_status_to_verify)>(
78  _asylo_status_to_verify));
79  } \
80 }while (false)
81 
82 /// Evaluates an expression `rexpr` that returns a `StatusOr`-like
83 /// object with `.ok()`, `.status()`, and `.ValueOrDie()` methods. If
84 /// the result is OK, moves its value into the variable defined by
85 /// `lhs`, otherwise returns the result of the `.status()` from the
86 /// current function. The error result of `.status` is returned
87 /// unchanged. If there is an error, `lhs` is not evaluated: thus any
88 /// side effects of evaluating `lhs` will only occur if `rexpr.ok()`
89 /// is true.
90 ///
91 /// Interface:
92 /// ```
93 /// ASYLO_ASSIGN_OR_RETURN(lhs, rexpr)
94 /// ```
95 ///
96 /// Example: Assigning to an existing variable:
97 /// ```
98 /// ValueType value;
99 /// ASYLO_ASSIGN_OR_RETURN(value, MaybeGetValue(arg));
100 /// ```
101 ///
102 /// Example: Assigning to an expression with side effects:
103 /// ```
104 /// MyProto data;
105 /// ASYLO_ASSIGN_OR_RETURN(*data.mutable_str(), MaybeGetValue(arg));
106 /// // No field "str" is added on error.
107 /// ```
108 ///
109 /// Example: Assigning to a `std::unique_ptr`.
110 /// ```
111 /// std::unique_ptr<T> ptr;
112 /// ASYLO_ASSIGN_OR_RETURN(ptr, MaybeGetPtr(arg));
113 /// ```
114 #define ASYLO_ASSIGN_OR_RETURN(lhs, rexpr) do
115  {
116  auto _asylo_status_or_value = (rexpr);
117  if (ABSL_PREDICT_FALSE(!_asylo_status_or_value.ok())) {
118  return _asylo_status_or_value.status();
119  }
120  lhs = std::move(_asylo_status_or_value).ValueOrDie(); \
121 }while (false)
122 
123 #endif // ASYLO_UTIL_STATUS_MACROS_H_
constexpr bool HasStatus(...)
Definition: status_macros.h:38
auto ToStatus(T &&status_or) -> decltype(status_or.status())
Definition: status_macros.h:45
ABSL_CONST_INIT const char kStatusMoveAssignmentMsg[]
Definition: status_macros.h:28
constexpr bool HasStatus(decltype(std::declval< T >().status()) *)
Definition: status_macros.h:32
T ToStatus(T &&status_like)
Definition: status_macros.h:52