/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include #include "base/optional.h" namespace rpl { namespace details { class combine_previous_helper { public: template auto operator()( producer &&initial) const { return make_producer, Error>([ initial = std::move(initial) ](const auto &consumer) mutable { auto previous = consumer.template make_state< base::optional >(); return std::move(initial).start( [consumer, previous](auto &&value) { if (auto exists = *previous) { auto &existing = *exists; auto next = std::make_tuple( std::move(existing), value); consumer.put_next(std::move(next)); existing = std::forward( value); } else { *previous = std::forward( value); } }, [consumer](auto &&error) { consumer.put_error_forward(std::forward(error)); }, [consumer] { consumer.put_done(); }); }); } }; template class combine_previous_with_default_helper { public: template combine_previous_with_default_helper(OtherValue &&value) : _value(std::forward(value)) { } template auto operator()(producer &&initial) { return make_producer, Error>([ initial = std::move(initial), value = Value(std::move(_value)) ](const auto &consumer) mutable { auto previous = consumer.template make_state( std::move(value)); return std::move(initial).start( [consumer, previous](auto &&value) { auto &existing = *previous; auto next = std::make_tuple( std::move(existing), value); consumer.put_next(std::move(next)); existing = std::forward(value); }, [consumer](auto &&error) { consumer.put_error_forward(std::forward(error)); }, [consumer] { consumer.put_done(); }); }); } private: DefaultValue _value; }; template combine_previous_with_default_helper> combine_previous_with_default(DefaultValue &&value) { return { std::forward(value) }; } } // namespace details inline auto combine_previous() -> details::combine_previous_helper { return details::combine_previous_helper(); } template inline auto combine_previous(DefaultValue &&value) { return details::combine_previous_with_default( std::forward(value)); } } // namespace rpl