blob: af531f3ebb638ac54b27199533c8c5e89091a148 [file] [log] [blame]
Jiyong Parkab7dc5a2019-05-31 03:43:34 +09001/*
2 * Copyright (C) 2017 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
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090017// Result<T, E> is the type that is used to pass a success value of type T or an error code of type
18// E, optionally together with an error message. T and E can be any type. If E is omitted it
19// defaults to int, which is useful when errno(3) is used as the error code.
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090020//
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090021// Passing a success value or an error value:
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090022//
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090023// Result<std::string> readFile() {
24// std::string content;
25// if (base::ReadFileToString("path", &content)) {
26// return content; // ok case
27// } else {
28// return ErrnoError() << "failed to read"; // error case
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090029// }
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090030// }
31//
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090032// Checking the result and then unwrapping the value or propagating the error:
33//
34// Result<bool> hasAWord() {
35// auto content = readFile();
36// if (!content.ok()) {
37// return Error() << "failed to process: " << content.error();
38// }
39// return (*content.find("happy") != std::string::npos);
40// }
41//
42// Using custom error code type:
43//
Jiyong Park7706f492021-12-14 22:33:38 +090044// enum class MyError { A, B }; // assume that this is the error code you already have
45//
46// // To use the error code with Result, define a wrapper class that provides the following
47// operations and use the wrapper class as the second type parameter (E) when instantiating
48// Result<T, E>
49//
50// 1. default constructor
51// 2. copy constructor / and move constructor if copying is expensive
52// 3. conversion operator to the error code type
53// 4. value() function that return the error code value
54// 5. print() function that gives a string representation of the error ode value
55//
56// struct MyErrorWrapper {
57// MyError val_;
58// MyErrorWrapper() : val_(/* reasonable default value */) {}
59// MyErrorWrapper(MyError&& e) : val_(std:forward<MyError>(e)) {}
60// operator const MyError&() const { return val_; }
61// MyError value() const { return val_; }
62// std::string print() const {
63// switch(val_) {
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090064// MyError::A: return "A";
65// MyError::B: return "B";
66// }
67// }
68// };
69//
Jiyong Park7706f492021-12-14 22:33:38 +090070// #define NewMyError(e) Error<MyErrorWrapper>(MyError::e)
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090071//
72// Result<T, MyError> val = NewMyError(A) << "some message";
73//
74// Formatting the error message using fmtlib:
75//
76// Errorf("{} errors", num); // equivalent to Error() << num << " errors";
77// ErrnoErrorf("{} errors", num); // equivalent to ErrnoError() << num << " errors";
78//
79// Returning success or failure, but not the value:
80//
81// Result<void> doSomething() {
82// if (success) return {};
83// else return Error() << "error occurred";
84// }
85//
86// Extracting error code:
87//
88// Result<T> val = Error(3) << "some error occurred";
89// assert(3 == val.error().code());
90//
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090091
92#pragma once
93
Jiyong Parkf7bb3e82021-12-10 22:46:25 +090094#include <assert.h>
Jiyong Parkab7dc5a2019-05-31 03:43:34 +090095#include <errno.h>
96
97#include <sstream>
98#include <string>
99
Jiyong Park7706f492021-12-14 22:33:38 +0900100#include "android-base/errors.h"
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900101#include "android-base/expected.h"
Tom Cherry377d1ad2019-06-14 14:34:54 -0700102#include "android-base/format.h"
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900103
104namespace android {
105namespace base {
106
Jiyong Park7706f492021-12-14 22:33:38 +0900107// Errno is a wrapper class for errno(3). Use this type instead of `int` when instantiating
108// `Result<T, E>` and `Error<E>` template classes. This is required to distinguish errno from other
109// integer-based error code types like `status_t`.
110struct Errno {
111 Errno() : val_(0) {}
112 Errno(int e) : val_(e) {}
113 int value() const { return val_; }
114 operator int() const { return value(); }
115 std::string print() const { return strerror(value()); }
116
117 int val_;
118
119 // TODO(b/209929099): remove this conversion operator. This currently is needed to not break
120 // existing places where error().code() is used to construct enum values.
121 template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>>
122 operator E() const {
123 return E(val_);
124 }
125};
126
127template <typename E = Errno>
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900128struct ResultError {
Jiyong Park7706f492021-12-14 22:33:38 +0900129 template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>>
130 ResultError(T&& message, P&& code)
131 : message_(std::forward<T>(message)), code_(E(std::forward<P>(code))) {}
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900132
133 template <typename T>
Maciej Żenczykowskib39ecb42020-01-26 20:12:30 -0800134 // NOLINTNEXTLINE(google-explicit-constructor)
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900135 operator android::base::expected<T, ResultError<E>>() const {
136 return android::base::unexpected(ResultError<E>(message_, code_));
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900137 }
138
139 std::string message() const { return message_; }
Jiyong Park7706f492021-12-14 22:33:38 +0900140 const E& code() const { return code_; }
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900141
142 private:
143 std::string message_;
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900144 E code_;
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900145};
146
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900147template <typename E>
148inline bool operator==(const ResultError<E>& lhs, const ResultError<E>& rhs) {
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900149 return lhs.message() == rhs.message() && lhs.code() == rhs.code();
150}
151
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900152template <typename E>
153inline bool operator!=(const ResultError<E>& lhs, const ResultError<E>& rhs) {
Jiyong Parkbdf42dc2019-06-05 18:33:01 +0900154 return !(lhs == rhs);
155}
156
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900157template <typename E>
158inline std::ostream& operator<<(std::ostream& os, const ResultError<E>& t) {
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900159 os << t.message();
160 return os;
161}
162
Jiyong Park7706f492021-12-14 22:33:38 +0900163template <typename E = Errno, typename = std::enable_if_t<!std::is_same_v<E, int>>>
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900164class Error {
165 public:
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900166 Error() : code_(0), has_code_(false) {}
Jiyong Park7706f492021-12-14 22:33:38 +0900167 template <typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>>
Maciej Żenczykowskib39ecb42020-01-26 20:12:30 -0800168 // NOLINTNEXTLINE(google-explicit-constructor)
Jiyong Park7706f492021-12-14 22:33:38 +0900169 Error(P&& code) : code_(std::forward<P>(code)), has_code_(true) {}
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900170
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900171 template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<E, P>>>
Maciej Żenczykowskib39ecb42020-01-26 20:12:30 -0800172 // NOLINTNEXTLINE(google-explicit-constructor)
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900173 operator android::base::expected<T, ResultError<P>>() const {
174 return android::base::unexpected(ResultError<P>(str(), static_cast<P>(code_)));
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900175 }
176
177 template <typename T>
178 Error& operator<<(T&& t) {
Maciej Żenczykowskice99a912020-04-24 11:21:21 -0700179 // NOLINTNEXTLINE(bugprone-suspicious-semicolon)
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900180 if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) {
181 if (!has_code_) {
182 code_ = t.code();
183 }
Jooyung Han072c7142019-06-11 13:38:01 +0900184 return (*this) << t.message();
185 }
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900186 int saved = errno;
187 ss_ << t;
188 errno = saved;
189 return *this;
190 }
191
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900192 const std::string str() const {
193 std::string str = ss_.str();
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900194 if (has_code_) {
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900195 if (str.empty()) {
Jiyong Park7706f492021-12-14 22:33:38 +0900196 return code_.print();
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900197 }
Jiyong Park7706f492021-12-14 22:33:38 +0900198 return std::move(str) + ": " + code_.print();
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900199 }
200 return str;
201 }
202
203 Error(const Error&) = delete;
204 Error(Error&&) = delete;
205 Error& operator=(const Error&) = delete;
206 Error& operator=(Error&&) = delete;
207
Tom Cherry81f5f502020-02-04 15:18:29 -0800208 template <typename T, typename... Args>
209 friend Error ErrorfImpl(const T&& fmt, const Args&... args);
Jiyong Park4e223e62019-06-12 16:25:04 +0900210
Tom Cherry81f5f502020-02-04 15:18:29 -0800211 template <typename T, typename... Args>
212 friend Error ErrnoErrorfImpl(const T&& fmt, const Args&... args);
Jiyong Park4e223e62019-06-12 16:25:04 +0900213
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900214 private:
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900215 Error(bool has_code, E code, const std::string& message) : code_(code), has_code_(has_code) {
Jiyong Park4e223e62019-06-12 16:25:04 +0900216 (*this) << message;
217 }
218
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900219 std::stringstream ss_;
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900220 E code_;
221 const bool has_code_;
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900222};
223
Jiyong Park7706f492021-12-14 22:33:38 +0900224inline Error<Errno> ErrnoError() {
225 return Error<Errno>(Errno{errno});
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900226}
227
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900228template <typename E>
229inline E ErrorCode(E code) {
Jiyong Park4e223e62019-06-12 16:25:04 +0900230 return code;
231}
232
233// Return the error code of the last ResultError object, if any.
234// Otherwise, return `code` as it is.
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900235template <typename T, typename E, typename... Args>
236inline E ErrorCode(E code, T&& t, const Args&... args) {
237 if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) {
Jiyong Park4e223e62019-06-12 16:25:04 +0900238 return ErrorCode(t.code(), args...);
239 }
240 return ErrorCode(code, args...);
241}
242
Tom Cherry81f5f502020-02-04 15:18:29 -0800243template <typename T, typename... Args>
Jiyong Park7706f492021-12-14 22:33:38 +0900244inline Error<Errno> ErrorfImpl(const T&& fmt, const Args&... args) {
245 return Error(false, ErrorCode(Errno{}, args...), fmt::format(fmt, args...));
Jiyong Park4e223e62019-06-12 16:25:04 +0900246}
247
Tom Cherry81f5f502020-02-04 15:18:29 -0800248template <typename T, typename... Args>
Jiyong Park7706f492021-12-14 22:33:38 +0900249inline Error<Errno> ErrnoErrorfImpl(const T&& fmt, const Args&... args) {
250 return Error<Errno>(true, Errno{errno}, fmt::format(fmt, args...));
Jiyong Park4e223e62019-06-12 16:25:04 +0900251}
252
Tom Cherry81f5f502020-02-04 15:18:29 -0800253#define Errorf(fmt, ...) android::base::ErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
254#define ErrnoErrorf(fmt, ...) android::base::ErrnoErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
255
Jiyong Park7706f492021-12-14 22:33:38 +0900256template <typename T, typename E = Errno>
Jiyong Parkf7bb3e82021-12-10 22:46:25 +0900257using Result = android::base::expected<T, ResultError<E>>;
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900258
Jiyong Park7706f492021-12-14 22:33:38 +0900259// Specialization of android::base::OkOrFail<V> for V = Result<T, E>. See android-base/errors.h
260// for the contract.
261template <typename T, typename E>
262struct OkOrFail<Result<T, E>> {
263 typedef Result<T, E> V;
264 // Checks if V is ok or fail
265 static bool IsOk(const V& val) { return val.ok(); }
266
267 // Turns V into a success value
268 static T Unwrap(V&& val) { return std::move(val.value()); }
269
270 // Consumes V when it's a fail value
271 static OkOrFail<V> Fail(V&& v) {
272 assert(!IsOk(v));
273 return OkOrFail<V>{std::move(v)};
274 }
275 V val_;
276
277 // Turns V into S (convertible from E) or Result<U, E>
278 template <typename S, typename = std::enable_if_t<std::is_convertible_v<E, S>>>
279 operator S() && {
280 return val_.error().code();
281 }
282 template <typename U>
283 operator Result<U, E>() && {
284 return val_.error();
285 }
286
287 static std::string ErrorMessage(const V& val) { return val.error().message(); }
288};
289
Bernie Innocenti9cc7edc2020-02-06 02:51:42 +0900290// Macros for testing the results of functions that return android::base::Result.
291// These also work with base::android::expected.
Yifan Hongf21c5462021-05-21 18:43:16 -0700292// For advanced matchers and customized error messages, see result-gtest.h.
Bernie Innocenti9cc7edc2020-02-06 02:51:42 +0900293
294#define CHECK_RESULT_OK(stmt) \
295 do { \
296 const auto& tmp = (stmt); \
297 CHECK(tmp.ok()) << tmp.error(); \
298 } while (0)
299
300#define ASSERT_RESULT_OK(stmt) \
301 do { \
302 const auto& tmp = (stmt); \
303 ASSERT_TRUE(tmp.ok()) << tmp.error(); \
304 } while (0)
305
306#define EXPECT_RESULT_OK(stmt) \
307 do { \
308 auto tmp = (stmt); \
309 EXPECT_TRUE(tmp.ok()) << tmp.error(); \
310 } while (0)
311
Jiyong Parkab7dc5a2019-05-31 03:43:34 +0900312} // namespace base
313} // namespace android