xref: /aosp_15_r20/system/libbase/include/android-base/result.h (revision 8f0ba417480079999ba552f1087ae592091b9d02)
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 #include <string.h>
97 
98 #include <sstream>
99 #include <string>
100 #include <type_traits>
101 
102 #include "android-base/errors.h"
103 #include "android-base/expected.h"
104 #include "android-base/format.h"
105 
106 namespace android {
107 namespace base {
108 
109 // Errno is a wrapper class for errno(3). Use this type instead of `int` when instantiating
110 // `Result<T, E>` and `Error<E>` template classes. This is required to distinguish errno from other
111 // integer-based error code types like `status_t`.
112 struct Errno {
ErrnoErrno113   Errno() : val_(0) {}
ErrnoErrno114   Errno(int e) : val_(e) {}
valueErrno115   int value() const { return val_; }
116   operator int() const { return value(); }
printErrno117   const char* print() const { return strerror(value()); }
118 
119   int val_;
120 
121   // TODO(b/209929099): remove this conversion operator. This currently is needed to not break
122   // existing places where error().code() is used to construct enum values.
123   template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>>
EErrno124   operator E() const {
125     return E(val_);
126   }
127 };
128 
129 static_assert(std::is_trivially_copyable_v<Errno> == true);
130 
131 template <typename E = Errno, bool include_message = true>
132 struct ResultError {
133   template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>>
ResultErrorResultError134   ResultError(T&& message, P&& code)
135       : message_(std::forward<T>(message)), code_(E(std::forward<P>(code))) {}
136 
137   ResultError(const ResultError& other) = default;
138   ResultError(ResultError&& other) = default;
139   ResultError& operator=(const ResultError& other) = default;
140   ResultError& operator=(ResultError&& other) = default;
141 
142   template <typename T>
143   // NOLINTNEXTLINE(google-explicit-constructor)
144   operator android::base::expected<T, ResultError<E>>() && {
145     return android::base::unexpected(std::move(*this));
146   }
147 
148   template <typename T>
149   // NOLINTNEXTLINE(google-explicit-constructor)
150   operator android::base::expected<T, ResultError<E>>() const& {
151     return android::base::unexpected(*this);
152   }
153 
messageResultError154   const std::string& message() const { return message_; }
codeResultError155   const E& code() const { return code_; }
156 
157  private:
158   std::string message_;
159   E code_;
160 };
161 
162 template <typename E>
format_as(ResultError<E,true> error)163 auto format_as(ResultError<E, true> error) {
164   return error.message();
165 }
166 
167 template <typename E>
168 struct ResultError<E, /* include_message */ false> {
169   template <typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>>
170   ResultError(P&& code) : code_(E(std::forward<P>(code))) {}
171 
172   template <typename T>
173   operator android::base::expected<T, ResultError<E, false>>() const {
174     return android::base::unexpected(ResultError<E, false>(code_));
175   }
176 
177   const E& code() const { return code_; }
178 
179  private:
180   E code_;
181 };
182 
183 template <typename E>
184 inline bool operator==(const ResultError<E>& lhs, const ResultError<E>& rhs) {
185   return lhs.message() == rhs.message() && lhs.code() == rhs.code();
186 }
187 
188 template <typename E>
189 inline bool operator!=(const ResultError<E>& lhs, const ResultError<E>& rhs) {
190   return !(lhs == rhs);
191 }
192 
193 template <typename E>
194 inline std::ostream& operator<<(std::ostream& os, const ResultError<E>& t) {
195   os << t.message();
196   return os;
197 }
198 
199 namespace internal {
200 // Stream class that does nothing and is has zero (actually 1) size. It is used instead of
201 // std::stringstream when include_message is false so that we use less on stack.
202 // sizeof(std::stringstream) is 280 on arm64.
203 struct DoNothingStream {
204   template <typename T>
205   DoNothingStream& operator<<(T&&) {
206     return *this;
207   }
208 
209   std::string str() const { return ""; }
210 };
211 }  // namespace internal
212 
213 template <typename E = Errno, bool include_message = true,
214           typename = std::enable_if_t<!std::is_same_v<E, int>>>
215 class Error {
216  public:
217   Error() : code_(0), has_code_(false) {}
218   template <typename P, typename = std::enable_if_t<std::is_convertible_v<P, E>>>
219   // NOLINTNEXTLINE(google-explicit-constructor)
220   Error(P&& code) : code_(std::forward<P>(code)), has_code_(true) {}
221 
222   template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<E, P>>>
223   // NOLINTNEXTLINE(google-explicit-constructor)
224   operator android::base::expected<T, ResultError<P>>() const {
225     return android::base::unexpected(ResultError<P>(str(), static_cast<P>(code_)));
226   }
227 
228   template <typename T, typename P, typename = std::enable_if_t<std::is_convertible_v<E, P>>>
229   // NOLINTNEXTLINE(google-explicit-constructor)
230   operator android::base::expected<T, ResultError<P, false>>() const {
231     return android::base::unexpected(ResultError<P, false>(static_cast<P>(code_)));
232   }
233 
234   template <typename T>
235   Error& operator<<(T&& t) {
236     static_assert(include_message, "<< not supported when include_message = false");
237     // NOLINTNEXTLINE(bugprone-suspicious-semicolon)
238     if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) {
239       if (!has_code_) {
240         code_ = t.code();
241       }
242       return (*this) << t.message();
243     }
244     int saved = errno;
245     ss_ << t;
246     errno = saved;
247     return *this;
248   }
249 
250   const std::string str() const {
251     static_assert(include_message, "str() not supported when include_message = false");
252     std::string str = ss_.str();
253     if (has_code_) {
254       if (str.empty()) {
255         return code_.print();
256       }
257       return std::move(str) + ": " + code_.print();
258     }
259     return str;
260   }
261 
262   Error(const Error&) = delete;
263   Error(Error&&) = delete;
264   Error& operator=(const Error&) = delete;
265   Error& operator=(Error&&) = delete;
266 
267   template <typename... Args>
268   friend Error ErrorfImpl(fmt::format_string<Args...> fmt, const Args&... args);
269 
270   template <typename... Args>
271   friend Error ErrnoErrorfImpl(fmt::format_string<Args...> fmt, const Args&... args);
272 
273  private:
274   Error(bool has_code, E code, const std::string& message) : code_(code), has_code_(has_code) {
275     (*this) << message;
276   }
277 
278   std::conditional_t<include_message, std::stringstream, internal::DoNothingStream> ss_;
279   E code_;
280   const bool has_code_;
281 };
282 
283 inline Error<Errno> ErrnoError() {
284   return Error<Errno>(Errno{errno});
285 }
286 
287 template <typename E>
288 inline E ErrorCode(E code) {
289   return code;
290 }
291 
292 // Return the error code of the last ResultError object, if any.
293 // Otherwise, return `code` as it is.
294 template <typename T, typename E, typename... Args>
295 inline E ErrorCode(E code, T&& t, const Args&... args) {
296   if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError<E>>) {
297     return ErrorCode(t.code(), args...);
298   }
299   return ErrorCode(code, args...);
300 }
301 
302 __attribute__((noinline)) ResultError<Errno> MakeResultErrorWithCode(std::string&& message,
303                                                                      Errno code);
304 
305 template <typename... Args>
306 inline ResultError<Errno> ErrorfImpl(fmt::format_string<Args...> fmt, const Args&... args) {
307   return ResultError(fmt::vformat(fmt.get(), fmt::make_format_args(args...)),
308                      ErrorCode(Errno{}, args...));
309 }
310 
311 template <typename... Args>
312 inline ResultError<Errno> ErrnoErrorfImpl(fmt::format_string<Args...> fmt, const Args&... args) {
313   Errno code{errno};
314   return MakeResultErrorWithCode(fmt::vformat(fmt.get(), fmt::make_format_args(args...)), code);
315 }
316 
317 #define Errorf(fmt, ...) android::base::ErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
318 #define ErrnoErrorf(fmt, ...) android::base::ErrnoErrorfImpl(FMT_STRING(fmt), ##__VA_ARGS__)
319 
320 template <typename T, typename E = Errno, bool include_message = true>
321 using Result = android::base::expected<T, ResultError<E, include_message>>;
322 
323 // Specialization of android::base::OkOrFail<V> for V = Result<T, E>. See android-base/errors.h
324 // for the contract.
325 
326 namespace impl {
327 template <typename U>
328 using Code = std::decay_t<decltype(std::declval<U>().error().code())>;
329 
330 template <typename U>
331 using ErrorType = std::decay_t<decltype(std::declval<U>().error())>;
332 
333 template <typename U>
334 constexpr bool IsNumeric = std::is_integral_v<U> || std::is_floating_point_v<U> ||
335                            (std::is_enum_v<U> && std::is_convertible_v<U, size_t>);
336 
337 // This base class exists to take advantage of shadowing
338 // We include the conversion in this base class so that if the conversion in NumericConversions
339 // overlaps, we (arbitrarily) choose the implementation in NumericConversions due to shadowing.
340 template <typename T>
341 struct ConversionBase {
342   ErrorType<T> error_;
343   // T is a expected<U, ErrorType<T>>.
344   operator T() const& { return unexpected(error_); }
345   operator T() && { return unexpected(std::move(error_)); }
346 
347   operator Code<T>() const { return error_.code(); }
348 };
349 
350 // User defined conversions can be followed by numeric conversions
351 // Although we template specialize for the exact code type, we need
352 // specializations for conversions to all numeric types to avoid an
353 // ambiguous conversion sequence.
354 template <typename T, typename = void>
355 struct NumericConversions : public ConversionBase<T> {};
356 template <typename T>
357 struct NumericConversions<T,
358     std::enable_if_t<impl::IsNumeric<impl::Code<T>>>
359     > : public ConversionBase<T>
360 {
361 #pragma push_macro("SPECIALIZED_CONVERSION")
362 #define SPECIALIZED_CONVERSION(type)                                                  \
363   operator expected<type, ErrorType<T>>() const& { return unexpected(this->error_); } \
364   operator expected<type, ErrorType<T>>()&& { return unexpected(std::move(this->error_)); }
365 
366   SPECIALIZED_CONVERSION(int)
367   SPECIALIZED_CONVERSION(short int)
368   SPECIALIZED_CONVERSION(unsigned short int)
369   SPECIALIZED_CONVERSION(unsigned int)
370   SPECIALIZED_CONVERSION(long int)
371   SPECIALIZED_CONVERSION(unsigned long int)
372   SPECIALIZED_CONVERSION(long long int)
373   SPECIALIZED_CONVERSION(unsigned long long int)
374   SPECIALIZED_CONVERSION(bool)
375   SPECIALIZED_CONVERSION(char)
376   SPECIALIZED_CONVERSION(unsigned char)
377   SPECIALIZED_CONVERSION(signed char)
378   SPECIALIZED_CONVERSION(wchar_t)
379   SPECIALIZED_CONVERSION(char16_t)
380   SPECIALIZED_CONVERSION(char32_t)
381   SPECIALIZED_CONVERSION(float)
382   SPECIALIZED_CONVERSION(double)
383   SPECIALIZED_CONVERSION(long double)
384 
385 #undef SPECIALIZED_CONVERSION
386 #pragma pop_macro("SPECIALIZED_CONVERSION")
387   // For debugging purposes
388   using IsNumericT = std::true_type;
389 };
390 
391 #ifdef __cpp_concepts
392 template <class U>
393 // Define a concept which **any** type matches to
394 concept Universal = std::is_same_v<U, U>;
395 #endif
396 
397 // A type that is never used.
398 struct Never {};
399 } // namespace impl
400 
401 template <typename T, typename E, bool include_message>
402 struct OkOrFail<Result<T, E, include_message>>
403     : public impl::NumericConversions<Result<T, E, include_message>> {
404   using V = Result<T, E, include_message>;
405   using Err = impl::ErrorType<V>;
406   using C = impl::Code<V>;
407 private:
408    OkOrFail(Err&& v): impl::NumericConversions<V>{std::move(v)} {}
409    OkOrFail(const OkOrFail& other) = delete;
410    OkOrFail(const OkOrFail&& other) = delete;
411 public:
412   // Checks if V is ok or fail
413   static bool IsOk(const V& val) { return val.ok(); }
414 
415   // Turns V into a success value
416   static T Unwrap(V&& val) {
417     if constexpr (std::is_same_v<T, void>) {
418       assert(IsOk(val));
419       return;
420     } else {
421       return std::move(val.value());
422     }
423   }
424 
425   // Consumes V when it's a fail value
426   static OkOrFail<V> Fail(V&& v) {
427     assert(!IsOk(v));
428     return OkOrFail<V>{std::move(v.error())};
429   }
430 
431   // We specialize as much as possible to avoid ambiguous conversion with templated expected ctor.
432   // We don't need this specialization if `C` is numeric because that case is already covered by
433   // `NumericConversions`.
434   operator Result<std::conditional_t<impl::IsNumeric<C>, impl::Never, C>, E, include_message>()
435       const& {
436     return unexpected(this->error_);
437   }
438   operator Result<std::conditional_t<impl::IsNumeric<C>, impl::Never, C>, E, include_message>() && {
439     return unexpected(std::move(this->error_));
440   }
441 
442 #ifdef __cpp_concepts
443   // The idea here is to match this template method to any type (not simply trivial types).
444   // The reason for including a constraint is to take advantage of the fact that a constrained
445   // method always has strictly lower precedence than a non-constrained method in template
446   // specialization rules (thus avoiding ambiguity). So we use a universally matching constraint to
447   // mark this function as less preferable (but still accepting of all types).
448   template <impl::Universal U>
449   operator Result<U, E, include_message>() const& {
450     return unexpected(this->error_);
451   }
452   template <impl::Universal U>
453   operator Result<U, E, include_message>() && {
454     return unexpected(std::move(this->error_));
455   }
456 #else
457   template <typename U>
458   operator Result<U, E, include_message>() const& {
459     return unexpected(this->error_);
460   }
461   template <typename U>
462   operator Result<U, E, include_message>() && {
463     return unexpected(std::move(this->error_));
464   }
465 #endif
466 
467   static const std::string& ErrorMessage(const V& val) { return val.error().message(); }
468 };
469 
470 // Macros for testing the results of functions that return android::base::Result. These also work
471 // with base::android::expected. They assume the user depends on libgmock and includes
472 // gtest/gtest.h. For advanced matchers and customized error messages, see result-gmock.h.
473 
474 #define ASSERT_RESULT_OK(stmt)                            \
475   if (const auto& tmp = (stmt); !tmp.ok())                \
476   FAIL() << "Value of: " << #stmt << "\n"                 \
477          << "  Actual: " << tmp.error().message() << "\n" \
478          << "Expected: is ok\n"
479 
480 #define EXPECT_RESULT_OK(stmt)                                   \
481   if (const auto& tmp = (stmt); !tmp.ok())                       \
482   ADD_FAILURE() << "Value of: " << #stmt << "\n"                 \
483                 << "  Actual: " << tmp.error().message() << "\n" \
484                 << "Expected: is ok\n"
485 
486 }  // namespace base
487 }  // namespace android
488