1 /* 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 17 // 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. 20 // 21 // Passing a success value or an error value: 22 // 23 // 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 29 // } 30 // } 31 // 32 // 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 // 44 // 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_) { 64 // MyError::A: return "A"; 65 // MyError::B: return "B"; 66 // } 67 // } 68 // }; 69 // 70 // #define NewMyError(e) Error<MyErrorWrapper>(MyError::e) 71 // 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 // 91 92 #pragma once 93 94 #include <assert.h> 95 #include <errno.h> 96 97 #include <sstream> 98 #include <string> 99 #include <type_traits> 100 101 #include "android-base/errors.h" 102 #include "android-base/expected.h" 103 #include "android-base/format.h" 104 105 namespace android { 106 namespace base { 107 108 // Errno is a wrapper class for errno(3). Use this type instead of `int` when instantiating 109 // `Result<T, E>` and `Error<E>` template classes. This is required to distinguish errno from other 110 // integer-based error code types like `status_t`. 111 struct Errno { ErrnoErrno112 Errno() : val_(0) {} ErrnoErrno113 Errno(int e) : val_(e) {} valueErrno114 int value() const { return val_; } 115 operator int() const { return value(); } printErrno116 std::string print() const { return strerror(value()); } 117 118 int val_; 119 120 // TODO(b/209929099): remove this conversion operator. This currently is needed to not break 121 // existing places where error().code() is used to construct enum values. 122 template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>> EErrno123 operator E() const { 124 return E(val_); 125 } 126 }; 127 128 template <typename E = Errno, bool include_message = true> 129 struct ResultError { 130 template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>> ResultErrorResultError131 ResultError(T&& message, P&& code) 132 : message_(std::forward<T>(message)), code_(E(std::forward<P>(code))) {} 133 134 template <typename T> 135 // NOLINTNEXTLINE(google-explicit-constructor) 136 operator android::base::expected<T, ResultError<E>>() const { 137 return android::base::unexpected(ResultError<E>(message_, code_)); 138 } 139 messageResultError140 std::string message() const { return message_; } codeResultError141 const E& code() const { return code_; } 142 143 private: 144 std::string message_; 145 E code_; 146 }; 147 148 template <typename E> 149 struct ResultError<E, /* include_message */ false> { 150 template <typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>> 151 ResultError(P&& code) : code_(E(std::forward<P>(code))) {} 152 153 template <typename T> 154 operator android::base::expected<T, ResultError<E, false>>() const { 155 return android::base::unexpected(ResultError<E, false>(code_)); 156 } 157 158 const E& code() const { return code_; } 159 160 private: 161 E code_; 162 }; 163 164 template <typename E> 165 inline bool operator==(const ResultError<E>& lhs, const ResultError<E>& rhs) { 166 return lhs.message() == rhs.message() && lhs.code() == rhs.code(); 167 } 168 169 template <typename E> 170 inline bool operator!=(const ResultError<E>& lhs, const ResultError<E>& rhs) { 171 return !(lhs == rhs); 172 } 173 174 template <typename E> 175 inline std::ostream& operator<<(std::ostream& os, const ResultError<E>& t) { 176 os << t.message(); 177 return os; 178 } 179 180 namespace internal { 181 // Stream class that does nothing and is has zero (actually 1) size. It is used instead of 182 // std::stringstream when include_message is false so that we use less on stack. 183 // sizeof(std::stringstream) is 280 on arm64. 184 struct DoNothingStream { 185 template <typename T> 186 DoNothingStream& operator<<(T&&) { 187 return *this; 188 } 189 190 std::string str() const { return ""; } 191 }; 192 } // namespace internal 193 194 template <typename E = Errno, bool include_message = true, 195 typename = std::enable_if_t<!std::is_same_v<E, int>>> 196 class Error { 197 public: 198 Error() : code_(0), has_code_(false) {} 199 template <typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>> 200 // NOLINTNEXTLINE(google-explicit-constructor) 201 Error(P&& code) : code_(std::forward<P>(code)), has_code_(true) {} 202 203 template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<E, P>>> 204 // NOLINTNEXTLINE(google-explicit-constructor) 205 operator android::base::expected<T, ResultError<P>>() const { 206 return android::base::unexpected(ResultError<P>(str(), static_cast<P>(code_))); 207 } 208 209 template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<E, P>>> 210 // NOLINTNEXTLINE(google-explicit-constructor) 211 operator android::base::expected<T, ResultError<P, false>>() const { 212 return android::base::unexpected(ResultError<P, false>(static_cast<P>(code_))); 213 } 214 215 template <typename T> 216 Error& operator<<(T&& t) { 217 static_assert(include_message, "<< not supported when include_message = false"); 218 // NOLINTNEXTLINE(bugprone-suspicious-semicolon) 219 if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) { 220 if (!has_code_) { 221 code_ = t.code(); 222 } 223 return (*this) << t.message(); 224 } 225 int saved = errno; 226 ss_ << t; 227 errno = saved; 228 return *this; 229 } 230 231 const std::string str() const { 232 static_assert(include_message, "str() not supported when include_message = false"); 233 std::string str = ss_.str(); 234 if (has_code_) { 235 if (str.empty()) { 236 return code_.print(); 237 } 238 return std::move(str) + ": " + code_.print(); 239 } 240 return str; 241 } 242 243 Error(const Error&) = delete; 244 Error(Error&&) = delete; 245 Error& operator=(const Error&) = delete; 246 Error& operator=(Error&&) = delete; 247 248 template <typename T, typename... Args> 249 friend Error ErrorfImpl(const T&& fmt, const Args&... args); 250 251 template <typename T, typename... Args> 252 friend Error ErrnoErrorfImpl(const T&& fmt, const Args&... args); 253 254 private: 255 Error(bool has_code, E code, const std::string& message) : code_(code), has_code_(has_code) { 256 (*this) << message; 257 } 258 259 std::conditional_t<include_message, std::stringstream, internal::DoNothingStream> ss_; 260 E code_; 261 const bool has_code_; 262 }; 263 264 inline Error<Errno> ErrnoError() { 265 return Error<Errno>(Errno{errno}); 266 } 267 268 template <typename E> 269 inline E ErrorCode(E code) { 270 return code; 271 } 272 273 // Return the error code of the last ResultError object, if any. 274 // Otherwise, return `code` as it is. 275 template <typename T, typename E, typename... Args> 276 inline E ErrorCode(E code, T&& t, const Args&... args) { 277 if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) { 278 return ErrorCode(t.code(), args...); 279 } 280 return ErrorCode(code, args...); 281 } 282 283 template <typename T, typename... Args> 284 inline Error<Errno> ErrorfImpl(const T&& fmt, const Args&... args) { 285 return Error(false, ErrorCode(Errno{}, args...), fmt::format(fmt, args...)); 286 } 287 288 template <typename T, typename... Args> 289 inline Error<Errno> ErrnoErrorfImpl(const T&& fmt, const Args&... args) { 290 return Error<Errno>(true, Errno{errno}, fmt::format(fmt, args...)); 291 } 292 293 #define Errorf(fmt, ...) android::base::ErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__) 294 #define ErrnoErrorf(fmt, ...) android::base::ErrnoErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__) 295 296 template <typename T, typename E = Errno, bool include_message = true> 297 using Result = android::base::expected<T, ResultError<E, include_message>>; 298 299 // Specialization of android::base::OkOrFail<V> for V = Result<T, E>. See android-base/errors.h 300 // for the contract. 301 302 namespace impl { 303 template <typename U> 304 using Code = std::decay_t<decltype(std::declval<U>().error().code())>; 305 306 template <typename U> 307 using ErrorType = std::decay_t<decltype(std::declval<U>().error())>; 308 309 template <typename U> 310 constexpr bool IsNumeric = std::is_integral_v<U> || std::is_floating_point_v<U> || 311 (std::is_enum_v<U> && std::is_convertible_v<U, size_t>); 312 313 // This base class exists to take advantage of shadowing 314 // We include the conversion in this base class so that if the conversion in NumericConversions 315 // overlaps, we (arbitrarily) choose the implementation in NumericConversions due to shadowing. 316 template <typename T> 317 struct ConversionBase { 318 ErrorType<T> error_; 319 // T is a expected<U, ErrorType<T>>. 320 operator const T() const && { 321 return unexpected(std::move(error_)); 322 } 323 324 operator const Code<T>() const && { 325 return error_.code(); 326 } 327 328 }; 329 330 // User defined conversions can be followed by numeric conversions 331 // Although we template specialize for the exact code type, we need 332 // specializations for conversions to all numeric types to avoid an 333 // ambiguous conversion sequence. 334 template <typename T, typename = void> 335 struct NumericConversions : public ConversionBase<T> {}; 336 template <typename T> 337 struct NumericConversions<T, 338 std::enable_if_t<impl::IsNumeric<impl::Code<T>>> 339 > : public ConversionBase<T> 340 { 341 #pragma push_macro("SPECIALIZED_CONVERSION") 342 #define SPECIALIZED_CONVERSION(type)\ 343 operator const expected<type, ErrorType<T>>() const &&\ 344 { return unexpected(std::move(this->error_));} 345 346 SPECIALIZED_CONVERSION(int) 347 SPECIALIZED_CONVERSION(short int) 348 SPECIALIZED_CONVERSION(unsigned short int) 349 SPECIALIZED_CONVERSION(unsigned int) 350 SPECIALIZED_CONVERSION(long int) 351 SPECIALIZED_CONVERSION(unsigned long int) 352 SPECIALIZED_CONVERSION(long long int) 353 SPECIALIZED_CONVERSION(unsigned long long int) 354 SPECIALIZED_CONVERSION(bool) 355 SPECIALIZED_CONVERSION(char) 356 SPECIALIZED_CONVERSION(unsigned char) 357 SPECIALIZED_CONVERSION(signed char) 358 SPECIALIZED_CONVERSION(wchar_t) 359 SPECIALIZED_CONVERSION(char16_t) 360 SPECIALIZED_CONVERSION(char32_t) 361 SPECIALIZED_CONVERSION(float) 362 SPECIALIZED_CONVERSION(double) 363 SPECIALIZED_CONVERSION(long double) 364 365 #undef SPECIALIZED_CONVERSION 366 #pragma pop_macro("SPECIALIZED_CONVERSION") 367 // For debugging purposes 368 using IsNumericT = std::true_type; 369 }; 370 371 #ifdef __cpp_concepts 372 template<class U> 373 concept Trivial = std::is_same_v<U, U>; 374 #endif 375 } // namespace impl 376 377 template <typename T, typename E, bool include_message> 378 struct OkOrFail<Result<T, E, include_message>> 379 : public impl::NumericConversions<Result<T, E, include_message>> { 380 using V = Result<T, E, include_message>; 381 using Err = impl::ErrorType<V>; 382 using C = impl::Code<V>; 383 private: 384 OkOrFail(Err&& v): impl::NumericConversions<V>{std::move(v)} {} 385 OkOrFail(const OkOrFail& other) = delete; 386 OkOrFail(const OkOrFail&& other) = delete; 387 public: 388 // Checks if V is ok or fail 389 static bool IsOk(const V& val) { return val.ok(); } 390 391 // Turns V into a success value 392 static T Unwrap(V&& val) { return std::move(val.value()); } 393 394 // Consumes V when it's a fail value 395 static const OkOrFail<V> Fail(V&& v) { 396 assert(!IsOk(v)); 397 return OkOrFail<V>{std::move(v.error())}; 398 } 399 400 // We specialize as much as possible to avoid ambiguous conversion with 401 // templated expected ctor 402 operator const Result<C, E, include_message>() const && { 403 return unexpected(std::move(this->error_)); 404 } 405 #ifdef __cpp_concepts 406 template <impl::Trivial U> 407 #else 408 template <typename U> 409 #endif 410 operator const Result<U, E, include_message>() const && { 411 return unexpected(std::move(this->error_)); 412 } 413 414 static std::string ErrorMessage(const V& val) { return val.error().message(); } 415 }; 416 417 // Macros for testing the results of functions that return android::base::Result. 418 // These also work with base::android::expected. 419 // For advanced matchers and customized error messages, see result-gtest.h. 420 421 #define ASSERT_RESULT_OK(stmt) \ 422 if (const auto& tmp = (stmt); !tmp.ok()) \ 423 FAIL() << "Value of: " << #stmt << "\n" \ 424 << " Actual: " << tmp.error().message() << "\n" \ 425 << "Expected: is ok\n" 426 427 #define EXPECT_RESULT_OK(stmt) \ 428 if (const auto& tmp = (stmt); !tmp.ok()) \ 429 ADD_FAILURE() << "Value of: " << #stmt << "\n" \ 430 << " Actual: " << tmp.error().message() << "\n" \ 431 << "Expected: is ok\n" 432 433 } // namespace base 434 } // namespace android 435