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