1 /* 2 * Copyright (C) 2023 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 #pragma once 17 18 #include <functional> 19 #include <type_traits> 20 #include <variant> 21 22 namespace gfxstream { 23 24 template <typename E> 25 class unexpected; 26 27 template<class E> 28 unexpected(E) -> unexpected<E>; 29 30 #define ENABLE_IF(...) typename std::enable_if<__VA_ARGS__>::type* = nullptr 31 32 template <typename T, typename E> 33 class expected { 34 public: 35 constexpr expected() = default; 36 constexpr expected(const expected& rhs) = default; 37 constexpr expected(expected&& rhs) = default; 38 39 template <typename CopyT = T, ENABLE_IF(!std::is_void<CopyT>::value)> expected(T && v)40 constexpr expected(T&& v) 41 : mVariant(std::in_place_index<0>, std::forward<T>(v)) {} 42 43 template<class... Args, ENABLE_IF(std::is_constructible<T, Args&&...>::value)> expected(std::in_place_t,Args &&...args)44 constexpr expected(std::in_place_t, Args&&... args) 45 : mVariant(std::in_place_index<0>, std::forward<Args>(args)...) {} 46 expected(const unexpected<E> & u)47 constexpr expected(const unexpected<E>& u) 48 : mVariant(std::in_place_index<1>, u.value()) {} 49 50 template<class OtherE = E, ENABLE_IF(std::is_constructible<E, const OtherE&>::value)> expected(const unexpected<OtherE> & e)51 constexpr expected(const unexpected<OtherE>& e) 52 : mVariant(std::in_place_index<1>, e.value()) {} 53 54 constexpr const T* operator->() const { return std::addressof(value()); } 55 constexpr T* operator->() { return std::addressof(value()); } 56 constexpr const T& operator*() const& { return value(); } 57 constexpr T& operator*() & { return value(); } 58 constexpr const T&& operator*() const&& { return std::move(std::get<T>(mVariant)); } 59 constexpr T&& operator*() && { return std::move(std::get<T>(mVariant)); } 60 has_value()61 constexpr bool has_value() const { return mVariant.index() == 0; } ok()62 constexpr bool ok() const { return has_value(); } 63 64 template <typename T2 = T, ENABLE_IF(!std::is_void<T>::value)> value()65 constexpr const T& value() const& { return std::get<T>(mVariant); } 66 template <typename T2 = T, ENABLE_IF(!std::is_void<T>::value)> value()67 constexpr T& value() & { return std::get<T>(mVariant); } 68 value()69 constexpr const T&& value() const&& { return std::move(std::get<T>(mVariant)); } value()70 constexpr T&& value() && { return std::move(std::get<T>(mVariant)); } 71 error()72 constexpr const E& error() const& { return std::get<E>(mVariant); } error()73 constexpr E& error() & { return std::get<E>(mVariant); } error()74 constexpr const E&& error() const&& { return std::move(std::get<E>(mVariant)); } error()75 constexpr E&& error() && { return std::move(std::get<E>(mVariant)); } 76 77 template <typename F, 78 typename NewE = std::remove_cv_t<std::invoke_result_t<F, E>>> transform_error(F && function)79 constexpr expected<T, NewE> transform_error(F&& function) { 80 if (ok()) { 81 if constexpr (std::is_void_v<T>) { 82 return expected<T, NewE>(); 83 } else { 84 return expected<T, NewE>(std::in_place, value()); 85 } 86 } else { 87 return unexpected(std::invoke(std::forward<F>(function), error())); 88 } 89 } 90 91 private: 92 std::variant<T, E> mVariant; 93 }; 94 95 template <typename E> 96 class unexpected { 97 public: 98 constexpr unexpected(const unexpected&) = default; 99 100 template <typename T> unexpected(T && e)101 constexpr explicit unexpected(T&& e) 102 : mError(std::forward<T>(e)) {} 103 104 template<class... Args, ENABLE_IF(std::is_constructible<E, Args&&...>::value)> unexpected(std::in_place_t,Args &&...args)105 constexpr explicit unexpected(std::in_place_t, Args&&... args) 106 : mError(std::forward<Args>(args)...) {} 107 value()108 constexpr const E& value() const& noexcept { return mError; } value()109 constexpr E& value() & noexcept { return mError; } value()110 constexpr const E&& value() const&& noexcept { return std::move(mError); } value()111 constexpr E&& value() && noexcept { return std::move(mError); } 112 113 private: 114 E mError; 115 }; 116 117 #define GFXSTREAM_EXPECT(x) \ 118 ({ \ 119 auto local_expected = (x); \ 120 if (!local_expected.ok()) { \ 121 return gfxstream::unexpected(local_expected.error()); \ 122 }; \ 123 std::move(local_expected.value()); \ 124 }) 125 126 class Ok {}; 127 128 } // namespace gfxstream