1 // Copyright (C) 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include "base/Optional.h" 18 19 // Result<T, E> - a template class to store either a result or error, inspired 20 // by Rust. 21 // 22 // T is the successful result type, and may be void. 23 // E is the error result type. 24 // 25 // To return success, return Ok(value) or Ok(). 26 // To return error, return Err(value). 27 // 28 // Usage in APIs: 29 // 30 // class MyError1 { Error1, Error2 }; 31 // typedef Result<void, MyError> MyResult; 32 // 33 // MyResult function() { 34 // if (good()) return Ok(); 35 // else return Err(MyError::Error1); 36 // } 37 // 38 // Checking results: 39 // 40 // if (result.ok()) { auto value = *result.ok(); } // no error 41 // return result; // propagate result as-is 42 // RETURN_IF_ERR(result); // propagate error 43 // switch (*result.err()) { ... } // handle error 44 // 45 // auto result = function(); 46 // RETURN_IF_ERR(result); // propagate error 47 48 // Helper to propagate errors. 49 #define RETURN_IF_ERR(...) \ 50 do { \ 51 auto&& __result = __VA_ARGS__; \ 52 if (__result.err()) { \ 53 return ::android::base::Err(__result.unwrapErr()); \ 54 } \ 55 } while (false) 56 57 namespace android { 58 namespace base { 59 60 namespace detail { 61 62 template <typename T> 63 struct Ok { OkOk64 Ok(const T& value) : value(value) {} OkOk65 Ok(T&& value) : value(std::move(value)) {} 66 OkOk67 Ok(Ok&& other) : value(std::move(other.value)) {} 68 69 T value; 70 }; 71 72 template <> 73 struct Ok<void> { 74 Ok() = default; 75 }; 76 77 template <typename E> 78 struct Err { 79 public: 80 Err(const E& value) : value(value) {} 81 Err(E&& value) : value(std::move(value)) {} 82 83 Err(Err&& other) : value(std::move(other.value)) {} 84 85 E value; 86 }; 87 88 template <typename T, typename E> 89 struct ResultStorage { 90 template <typename U, 91 typename = typename std::enable_if< 92 std::is_convertible<T, U>::value>::type> 93 ResultStorage(Ok<U>&& ok) : ok(std::move(ok.value)) {} 94 95 ResultStorage(Err<E>&& err) : err(std::move(err.value)) {} 96 97 bool isOk() const { return ok.hasValue(); } 98 99 Optional<T> ok; 100 Optional<E> err; 101 }; 102 103 template <typename E> 104 struct ResultStorage<void, E> { 105 ResultStorage(Ok<void>&& ok) {} 106 ResultStorage(Err<E>&& err) : err(std::move(err.value)) {} 107 108 bool isOk() const { return !err.hasValue(); } 109 110 Optional<E> err; 111 }; 112 113 } // namespace detail 114 115 template <typename T, typename Value = typename std::decay<T>::type> 116 detail::Ok<Value> Ok(T&& value) { 117 return detail::Ok<Value>(std::forward<T>(value)); 118 } 119 120 static inline detail::Ok<void> Ok() { 121 return detail::Ok<void>(); 122 } 123 124 template <typename E, typename Value = typename std::decay<E>::type> 125 detail::Err<Value> Err(E&& value) { 126 return detail::Err<Value>(std::forward<E>(value)); 127 } 128 129 template <typename T, typename E> 130 class Result { 131 public: 132 template <typename U, 133 typename = typename std::enable_if< 134 std::is_convertible<U, T>::value>::type> 135 Result(detail::Ok<U>&& ok) : mStorage(std::move(ok)) {} 136 Result(detail::Err<E>&& err) : mStorage(std::move(err)) {} 137 138 Result(Result&& other) 139 : mStorage(std::move(other.mStorage)), mValid(other.mValid) { 140 other.mValid = false; 141 } 142 143 // Returns an Optional<T> representing the value, not defined is T is void. 144 template <typename U = T> 145 typename std::enable_if<!std::is_void<U>::value && 146 std::is_copy_constructible<U>::value, 147 Optional<U>>::type 148 ok() { 149 CHECK(mValid) << "Result invalid"; 150 return mStorage.ok; 151 } 152 template <typename U = T> 153 typename std::enable_if<!std::is_void<U>::value, const Optional<U>&>::type 154 ok() const { 155 CHECK(mValid) << "Result invalid"; 156 return mStorage.ok; 157 } 158 159 // For Result<void, E> types, returns true if the Result is ok. 160 template <typename U = T> 161 typename std::enable_if<std::is_void<U>::value, bool>::type ok() const { 162 CHECK(mValid) << "Result invalid"; 163 return mStorage.isOk(); 164 } 165 166 // Returns an Optional<E> representing the error, if it exists. 167 template <typename U = E> 168 typename std::enable_if<std::is_copy_constructible<U>::value, 169 Optional<U>>::type 170 err() { 171 CHECK(mValid) << "Result invalid"; 172 return mStorage.err; 173 } 174 const Optional<E>& err() const { 175 CHECK(mValid) << "Result invalid"; 176 return mStorage.err; 177 } 178 179 // Unwraps the value and returns it. After this call the Result is invalid. 180 template <typename U = T> 181 typename std::enable_if<!std::is_void<U>::value, U>::type unwrap() { 182 CHECK(mValid) << "Result invalid"; 183 mValid = false; 184 return std::move(*(mStorage.ok.ptr())); 185 } 186 187 // Unwraps the error and returns it. After this call the Result is invalid. 188 E unwrapErr() { 189 CHECK(mValid) << "Result invalid"; 190 mValid = false; 191 return std::move(*(mStorage.err.ptr())); 192 } 193 194 private: 195 detail::ResultStorage<T, E> mStorage; 196 bool mValid = true; 197 }; 198 199 } // namespace base 200 } // namespace android 201