// This file is part of Desktop App Toolkit, // a set of libraries for developing nice desktop applications. // // For license and copyright information please follow this link: // https://github.com/desktop-app/legal/blob/master/LEGAL // #pragma once namespace rpl { namespace details { class take_helper { public: take_helper(int count) : _count(count) { } template < typename Value, typename Error, typename Generator> auto operator()(producer &&initial) { return make_producer([ initial = std::move(initial), limit = _count ](const auto &consumer) mutable { auto count = consumer.template make_state(limit); auto initial_consumer = make_consumer( [consumer, count](auto &&value) { auto left = (*count)--; if (left) { consumer.put_next_forward( std::forward(value)); --left; } if (!left) { consumer.put_done(); } }, [consumer](auto &&error) { consumer.put_error_forward( std::forward(error)); }, [consumer] { consumer.put_done(); }); consumer.add_lifetime(initial_consumer.terminator()); return std::move(initial).start_existing(initial_consumer); }); } private: int _count = 0; }; } // namespace details inline auto take(int count) -> details::take_helper { Expects(count >= 0); return details::take_helper(count); } namespace details { template class take_while_helper { public: template take_while_helper(OtherPredicate &&predicate) : _predicate(std::forward(predicate)) { } template < typename Value, typename Error, typename Generator, typename = std::enable_if_t< details::is_callable_v>> auto operator()(producer &&initial) { return make_producer([ initial = std::move(initial), predicate = std::move(_predicate) ](const auto &consumer) mutable { return std::move(initial).start( [ consumer, predicate = std::move(predicate) ](auto &&value) { const auto &immutable = value; if (details::callable_invoke( predicate, immutable) ) { consumer.put_next_forward( std::forward(value)); } else { consumer.put_done(); } }, [consumer](auto &&error) { consumer.put_error_forward( std::forward(error)); }, [consumer] { consumer.put_done(); }); }); } private: Predicate _predicate; }; } // namespace details template inline auto take_while(Predicate &&predicate) -> details::take_while_helper> { return details::take_while_helper>( std::forward(predicate)); } } // namespace rpl