| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- // 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>
- namespace rpl {
- namespace details {
- template <
- typename Transform,
- typename NewValue,
- typename Error,
- typename Handlers>
- class map_transform_helper {
- public:
- map_transform_helper(
- Transform &&transform,
- const consumer<NewValue, Error, Handlers> &consumer)
- : _consumer(consumer)
- , _transform(std::move(transform)) {
- }
- template <
- typename OtherValue,
- typename = std::enable_if_t<
- std::is_rvalue_reference_v<OtherValue&&>>>
- void operator()(OtherValue &&value) const {
- _consumer.put_next_forward(
- details::callable_invoke(_transform, std::move(value)));
- }
- template <
- typename OtherValue,
- typename = decltype(
- std::declval<Transform>()(const_ref_val<OtherValue>()))>
- void operator()(const OtherValue &value) const {
- _consumer.put_next_forward(
- details::callable_invoke(_transform, value));
- }
- private:
- consumer<NewValue, Error, Handlers> _consumer;
- Transform _transform;
- };
- template <
- typename Transform,
- typename NewValue,
- typename Error,
- typename Handlers,
- typename = std::enable_if_t<
- std::is_rvalue_reference_v<Transform&&>>>
- inline map_transform_helper<Transform, NewValue, Error, Handlers>
- map_transform(
- Transform &&transform,
- const consumer<NewValue, Error, Handlers> &consumer) {
- return { std::move(transform), consumer };
- }
- template <typename Transform>
- class map_helper {
- public:
- template <typename OtherTransform>
- map_helper(OtherTransform &&transform)
- : _transform(std::forward<OtherTransform>(transform)) {
- }
- template <
- typename Value,
- typename Error,
- typename Generator,
- typename NewValue = details::callable_result<
- Transform,
- Value>>
- auto operator()(producer<Value, Error, Generator> &&initial) {
- return make_producer<NewValue, Error>([
- initial = std::move(initial),
- transform = std::move(_transform)
- ](const auto &consumer) mutable {
- return std::move(initial).start(
- map_transform(
- std::move(transform),
- consumer
- ), [consumer](auto &&error) {
- consumer.put_error_forward(
- std::forward<decltype(error)>(error));
- }, [consumer] {
- consumer.put_done();
- });
- });
- }
- private:
- Transform _transform;
- };
- } // namespace details
- template <typename Transform>
- inline auto map(Transform &&transform)
- -> details::map_helper<std::decay_t<Transform>> {
- return details::map_helper<std::decay_t<Transform>>(
- std::forward<Transform>(transform));
- }
- template <typename Value>
- [[nodiscard]] inline auto map_to(Value &&value) {
- return map([value = std::forward<Value>(value)] {
- return value;
- });
- }
- inline auto to_empty = map_to(empty_value());
- namespace details {
- template <
- typename Transform,
- typename Value,
- typename NewError,
- typename Handlers>
- class map_error_transform_helper {
- public:
- map_error_transform_helper(
- Transform &&transform,
- const consumer<Value, NewError, Handlers> &consumer)
- : _transform(std::move(transform))
- , _consumer(consumer) {
- }
- template <
- typename OtherError,
- typename = std::enable_if_t<
- std::is_rvalue_reference_v<OtherError&&>>>
- void operator()(OtherError &&error) const {
- _consumer.put_error_forward(
- details::callable_invoke(_transform, std::move(error)));
- }
- template <
- typename OtherError,
- typename = decltype(
- std::declval<Transform>()(const_ref_val<OtherError>()))>
- void operator()(const OtherError &error) const {
- _consumer.put_error_forward(
- details::callable_invoke(_transform, error));
- }
- private:
- consumer<Value, NewError, Handlers> _consumer;
- Transform _transform;
- };
- template <
- typename Transform,
- typename Value,
- typename NewError,
- typename Handlers,
- typename = std::enable_if_t<
- std::is_rvalue_reference_v<Transform&&>>>
- inline map_error_transform_helper<Transform, Value, NewError, Handlers>
- map_error_transform(
- Transform &&transform,
- const consumer<Value, NewError, Handlers> &consumer) {
- return { std::move(transform), consumer };
- }
- template <typename Transform>
- class map_error_helper {
- public:
- template <typename OtherTransform>
- map_error_helper(OtherTransform &&transform)
- : _transform(std::forward<OtherTransform>(transform)) {
- }
- template <
- typename Value,
- typename Error,
- typename Generator,
- typename NewError = details::callable_result<
- Transform,
- Error>>
- auto operator()(producer<Value, Error, Generator> &&initial) {
- return make_producer<Value, NewError>([
- initial = std::move(initial),
- transform = std::move(_transform)
- ](const auto &consumer) mutable {
- return std::move(initial).start(
- [consumer](auto &&value) {
- consumer.put_next_forward(
- std::forward<decltype(value)>(value));
- }, map_error_transform(
- std::move(transform),
- consumer
- ), [consumer] {
- consumer.put_done();
- });
- });
- }
- private:
- Transform _transform;
- };
- class map_error_to_done_helper {
- public:
- map_error_to_done_helper() {
- }
- template <
- typename Value,
- typename Error,
- typename Generator>
- auto operator()(producer<Value, Error, Generator> &&initial) {
- return make_producer<Value, no_error>([
- initial = std::move(initial)
- ](const auto &consumer) mutable {
- return std::move(initial).start(
- [consumer](auto &&value) {
- consumer.put_next_forward(
- std::forward<decltype(value)>(value));
- }, [consumer] {
- consumer.put_done();
- }, [consumer] {
- consumer.put_done();
- });
- });
- }
- };
- } // namespace details
- template <typename Transform>
- inline auto map_error(Transform &&transform)
- -> details::map_error_helper<std::decay_t<Transform>> {
- return details::map_error_helper<std::decay_t<Transform>>(
- std::forward<Transform>(transform));
- }
- inline details::map_error_to_done_helper map_error_to_done() {
- return details::map_error_to_done_helper();
- }
- } // namespace rpl
|