| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- // 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
- #include <rpl/producer.h>
- #include "base/optional.h"
- namespace rpl {
- namespace details {
- class combine_previous_helper {
- public:
- template <typename Value, typename Error, typename Generator>
- auto operator()(
- producer<Value, Error, Generator> &&initial) const {
- return make_producer<std::tuple<Value, Value>, Error>([
- initial = std::move(initial)
- ](const auto &consumer) mutable {
- auto previous = consumer.template make_state<
- std::optional<Value>
- >();
- 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<decltype(value)>(
- value);
- } else {
- *previous = std::forward<decltype(value)>(
- value);
- }
- }, [consumer](auto &&error) {
- consumer.put_error_forward(std::forward<decltype(error)>(error));
- }, [consumer] {
- consumer.put_done();
- });
- });
- }
- };
- template <typename DefaultValue>
- class combine_previous_with_default_helper {
- public:
- template <typename OtherValue>
- combine_previous_with_default_helper(OtherValue &&value)
- : _value(std::forward<OtherValue>(value)) {
- }
- template <typename Value, typename Error, typename Generator>
- auto operator()(producer<Value, Error, Generator> &&initial) {
- return make_producer<std::tuple<Value, Value>, Error>([
- initial = std::move(initial),
- value = Value(std::move(_value))
- ](const auto &consumer) mutable {
- auto previous = consumer.template make_state<Value>(
- 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<decltype(value)>(value);
- }, [consumer](auto &&error) {
- consumer.put_error_forward(std::forward<decltype(error)>(error));
- }, [consumer] {
- consumer.put_done();
- });
- });
- }
- private:
- DefaultValue _value;
- };
- template <typename DefaultValue>
- combine_previous_with_default_helper<std::decay_t<DefaultValue>>
- combine_previous_with_default(DefaultValue &&value) {
- return { std::forward<DefaultValue>(value) };
- }
- } // namespace details
- inline auto combine_previous()
- -> details::combine_previous_helper {
- return details::combine_previous_helper();
- }
- template <typename DefaultValue>
- inline auto combine_previous(DefaultValue &&value) {
- return details::combine_previous_with_default(
- std::forward<DefaultValue>(value));
- }
- } // namespace rpl
|