#pragma once /* * Copyright 2018-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include namespace pushmi { namespace detail { template struct transform_on; template struct transform_on> { F f_; transform_on() = default; constexpr explicit transform_on(F f) : f_(std::move(f)) {} struct value_fn { F f_; value_fn() = default; constexpr explicit value_fn(F f) : f_(std::move(f)) {} template auto operator()(Out& out, V0&& v0, VN&&... vn) { using Result = ::pushmi::invoke_result_t; static_assert( ::pushmi::SemiMovable, "none of the functions supplied to transform can convert this value"); static_assert( ::pushmi::ReceiveValue, "Result of value transform cannot be delivered to Out"); ::pushmi::set_value(out, f_((V0 &&) v0, (VN &&) vn...)); } }; template auto operator()(Out out) const { return ::pushmi::make_receiver(std::move(out), value_fn{f_}); } }; template struct transform_on, true> { F f_; transform_on() = default; constexpr explicit transform_on(F f) : f_(std::move(f)) {} template auto operator()(Out out) const { return make_flow_single(std::move(out), on_value(*this)); } template auto operator()(Out& out, V0&& v0, VN&&... vn) { using Result = ::pushmi::invoke_result_t; static_assert( ::pushmi::SemiMovable, "none of the functions supplied to transform can convert this value"); static_assert( ::pushmi::Flow && ::pushmi::ReceiveValue, "Result of value transform cannot be delivered to Out"); ::pushmi::set_value(out, f_((V0 &&) v0, (VN &&) vn...)); } }; template struct transform_on> { F f_; transform_on() = default; constexpr explicit transform_on(F f) : f_(std::move(f)) {} template auto operator()(Out out) const { return ::pushmi::make_receiver(std::move(out), on_value(*this)); } template auto operator()(Out& out, V0&& v0, VN&&... vn) { using Result = ::pushmi::invoke_result_t; static_assert( ::pushmi::SemiMovable, "none of the functions supplied to transform can convert this value"); static_assert( ::pushmi::ReceiveValue, "Result of value transform cannot be delivered to Out"); ::pushmi::set_value(out, f_((V0 &&) v0, (VN &&) vn...)); } }; template struct transform_on, true> { F f_; transform_on() = default; constexpr explicit transform_on(F f) : f_(std::move(f)) {} template auto operator()(Out out) const { return make_flow_receiver(std::move(out), on_value(*this)); } template auto operator()(Out& out, V0&& v0, VN&&... vn) { using Result = ::pushmi::invoke_result_t; static_assert( ::pushmi::SemiMovable, "none of the functions supplied to transform can convert this value"); static_assert( ::pushmi::Flow && ::pushmi::ReceiveValue, "Result of value transform cannot be delivered to Out"); ::pushmi::set_value(out, f_((V0 &&) v0, (VN &&) vn...)); } }; struct transform_fn { private: template struct impl { F f_; PUSHMI_TEMPLATE(class In) (requires Sender) auto operator()(In in) const { using Cardinality = property_set_index_t, is_single<>>; return ::pushmi::detail::sender_from( std::move(in), ::pushmi::detail::submit_transform_out( // copy 'f_' to allow multiple calls to connect to multiple 'in' transform_on< F, Cardinality, property_query_v, is_flow<>>>{f_})); } }; public: template auto operator()(FN... fn) const { auto f = ::pushmi::overload(std::move(fn)...); using F = decltype(f); return impl{std::move(f)}; } }; } // namespace detail namespace operators { PUSHMI_INLINE_VAR constexpr detail::transform_fn transform{}; } // namespace operators } // namespace pushmi