Android-cuttlefish cvd tool
expect.h
Go to the documentation of this file.
1//
2// Copyright (C) 2022 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#pragma once
17
18#include <optional>
19#include <type_traits>
20#include <utility>
21
22#include "fmt/format.h" // IWYU pragma: keep: preprocessor
23#include "tl/expected.hpp" // IWYU pragma: export
24
26#include "cuttlefish/result/result_type.h" // IWYU pragma: export
27
28namespace cuttlefish {
29
48#define CF_ERR(MSG) tl::unexpected(CF_STACK_TRACE_ENTRY("") << MSG)
49#define CF_ERRNO(MSG) tl::unexpected(CF_STACK_TRACE_ENTRY("") << MSG)
50#define CF_ERRF(MSG, ...) \
51 tl::unexpected(CF_STACK_TRACE_ENTRY("") \
52 << fmt::format(FMT_STRING(MSG), __VA_ARGS__))
53
54template <typename T>
55T OutcomeDereference(std::optional<T>&& value) {
56 return std::move(*value);
57}
58
60
61template <typename T>
63 return std::move(*result);
64}
65
66template <typename T>
67typename std::enable_if<std::is_convertible_v<T, bool>, T>::type
69 return std::forward<T>(value);
70}
71
72inline bool TypeIsSuccess(bool value) { return value; }
73
74template <typename T>
75bool TypeIsSuccess(std::optional<T>& value) {
76 return value.has_value();
77}
78
79template <typename T>
81 return value.has_value();
82}
83
84inline auto ErrorFromType(bool) { return StackTraceError(); }
85
86template <typename T>
87inline auto ErrorFromType(std::optional<T>) {
88 return StackTraceError();
89}
90
91template <typename T>
93 return value.error();
94}
95
96#define CF_EXPECT_OVERLOAD(_1, _2, NAME, ...) NAME
97
98#define CF_EXPECT2(RESULT, MSG) \
99 ({ \
100 decltype(RESULT)&& macro_intermediate_result = RESULT; \
101 if (!TypeIsSuccess(macro_intermediate_result)) { \
102 auto current_entry = CF_STACK_TRACE_ENTRY(#RESULT); \
103 current_entry << MSG; \
104 auto error = ErrorFromType(macro_intermediate_result); \
105 error.PushEntry(std::move(current_entry)); \
106 return tl::unexpected(std::move(error)); \
107 }; \
108 OutcomeDereference(std::move(macro_intermediate_result)); \
109 })
110
111#define CF_EXPECT1(RESULT) CF_EXPECT2(RESULT, "")
112
149#define CF_EXPECT(...) \
150 CF_EXPECT_OVERLOAD(__VA_ARGS__, CF_EXPECT2, CF_EXPECT1)(__VA_ARGS__)
151
152#define CF_EXPECTF(RESULT, MSG, ...) \
153 CF_EXPECT(RESULT, fmt::format(FMT_STRING(MSG), __VA_ARGS__))
154
155#define CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, MSG) \
156 ({ \
157 auto&& lhs_macro_intermediate_result = LHS_RESULT; \
158 auto&& rhs_macro_intermediate_result = RHS_RESULT; \
159 bool comparison_result = lhs_macro_intermediate_result COMPARE_OP \
160 rhs_macro_intermediate_result; \
161 if (!comparison_result) { \
162 auto current_entry = CF_STACK_TRACE_ENTRY(""); \
163 current_entry << "Expected \"" << #LHS_RESULT << "\" " << #COMPARE_OP \
164 << " \"" << #RHS_RESULT << "\" but was " \
165 << lhs_macro_intermediate_result << " vs " \
166 << rhs_macro_intermediate_result << ". "; \
167 current_entry << MSG; \
168 auto error = ErrorFromType(false); \
169 error.PushEntry(std::move(current_entry)); \
170 return tl::unexpected(std::move(error)); \
171 }; \
172 comparison_result; \
173 })
174
175#define CF_COMPARE_EXPECT3(COMPARE_OP, LHS_RESULT, RHS_RESULT) \
176 CF_COMPARE_EXPECT4(COMPARE_OP, LHS_RESULT, RHS_RESULT, "")
177
178#define CF_COMPARE_EXPECT_OVERLOAD(_1, _2, _3, _4, NAME, ...) NAME
179
180#define CF_COMPARE_EXPECT(...) \
181 CF_COMPARE_EXPECT_OVERLOAD(__VA_ARGS__, CF_COMPARE_EXPECT4, \
182 CF_COMPARE_EXPECT3) \
183 (__VA_ARGS__)
184
185#define CF_EXPECT_EQ(LHS_RESULT, RHS_RESULT, ...) \
186 CF_COMPARE_EXPECT(==, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
187#define CF_EXPECT_NE(LHS_RESULT, RHS_RESULT, ...) \
188 CF_COMPARE_EXPECT(!=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
189#define CF_EXPECT_LE(LHS_RESULT, RHS_RESULT, ...) \
190 CF_COMPARE_EXPECT(<=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
191#define CF_EXPECT_LT(LHS_RESULT, RHS_RESULT, ...) \
192 CF_COMPARE_EXPECT(<, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
193#define CF_EXPECT_GE(LHS_RESULT, RHS_RESULT, ...) \
194 CF_COMPARE_EXPECT(>=, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
195#define CF_EXPECT_GT(LHS_RESULT, RHS_RESULT, ...) \
196 CF_COMPARE_EXPECT(>, LHS_RESULT, RHS_RESULT, ##__VA_ARGS__)
197
198} // namespace cuttlefish
Definition: error_type.h:85
Definition: alloc_driver.h:20
T OutcomeDereference(std::optional< T > &&value)
Definition: expect.h:55
auto ErrorFromType(bool)
Definition: expect.h:84
tl::expected< T, StackTraceError > Result
Definition: result_type.h:30
bool TypeIsSuccess(bool value)
Definition: expect.h:72
uint8_t type
Definition: pairing_connection.h:0