• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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