xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__into_variant.hpp (revision 10d0b4b7d1498cfd5c3d37edea271a54d1984e41)
1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
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 "__execution_fwd.hpp"
19 
20 // include these after __execution_fwd.hpp
21 #include "__basic_sender.hpp"
22 #include "__concepts.hpp"
23 #include "__domain.hpp"
24 #include "__meta.hpp"
25 #include "__sender_adaptor_closure.hpp"
26 #include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender
27 #include "__transform_completion_signatures.hpp"
28 #include "__transform_sender.hpp"
29 #include "__utility.hpp"
30 
31 #include <exception>
32 #include <tuple>
33 #include <variant> // IWYU pragma: keep
34 
35 namespace stdexec {
36   /////////////////////////////////////////////////////////////////////////////
37   // [execution.senders.adaptors.into_variant]
38   namespace __into_variant {
39     template <class _Sender, class _Env>
40       requires sender_in<_Sender, _Env>
41     using __into_variant_result_t = value_types_of_t<_Sender, _Env>;
42 
43     template <class _Sender, class... _Env>
44     using __variant_t = __value_types_t<__completion_signatures_of_t<_Sender, _Env...>>;
45 
46     template <class _Variant>
47     using __variant_completions =
48       completion_signatures<set_value_t(_Variant), set_error_t(std::exception_ptr)>;
49 
50     template <class _Sender, class... _Env>
51     using __completions = transform_completion_signatures<
52       __completion_signatures_of_t<_Sender, _Env...>,
53       __meval<__variant_completions, __variant_t<_Sender, _Env...>>,
54       __mconst<completion_signatures<>>::__f
55     >;
56 
57     struct into_variant_t {
58       template <sender _Sender>
operator ()stdexec::__into_variant::into_variant_t59       auto operator()(_Sender&& __sndr) const -> __well_formed_sender auto {
60         auto __domain = __get_early_domain(__sndr);
61         return stdexec::transform_sender(
62           __domain, __make_sexpr<into_variant_t>(__(), static_cast<_Sender&&>(__sndr)));
63       }
64 
STDEXEC_ATTRIBUTEstdexec::__into_variant::into_variant_t65       STDEXEC_ATTRIBUTE(always_inline)
66       auto operator()() const noexcept -> __binder_back<into_variant_t> {
67         return {{}, {}, {}};
68       }
69     };
70 
71     struct __into_variant_impl : __sexpr_defaults {
72       static constexpr auto get_state =
73         []<class _Self, class _Receiver>(_Self&&, _Receiver&) noexcept {
74           using __variant_t = value_types_of_t<__child_of<_Self>, env_of_t<_Receiver>>;
75           return __mtype<__variant_t>();
76         };
77 
78       static constexpr auto complete =
79         []<class _State, class _Receiver, class _Tag, class... _Args>(
80           __ignore,
81           _State,
82           _Receiver& __rcvr,
83           _Tag,
84           _Args&&... __args) noexcept -> void {
85         if constexpr (__same_as<_Tag, set_value_t>) {
86           using __variant_t = __t<_State>;
87           STDEXEC_TRY {
88             set_value(
89               static_cast<_Receiver&&>(__rcvr),
90               __variant_t{std::tuple<_Args&&...>{static_cast<_Args&&>(__args)...}});
91           }
92           STDEXEC_CATCH_ALL {
93             stdexec::set_error(static_cast<_Receiver&&>(__rcvr), std::current_exception());
94           }
95         } else {
96           _Tag()(static_cast<_Receiver&&>(__rcvr), static_cast<_Args&&>(__args)...);
97         }
98       };
99 
100       static constexpr auto get_completion_signatures =
101         []<class _Self, class... _Env>(_Self&&, _Env&&...) noexcept
102         -> __completions<__child_of<_Self>, _Env...> {
103         static_assert(sender_expr_for<_Self, into_variant_t>);
104         return {};
105       };
106     };
107   } // namespace __into_variant
108 
109   using __into_variant::into_variant_t;
110   inline constexpr into_variant_t into_variant{};
111 
112   template <>
113   struct __sexpr_impl<into_variant_t> : __into_variant::__into_variant_impl { };
114 } // namespace stdexec
115