Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
249 lines
5.9 KiB
C++
249 lines
5.9 KiB
C++
// 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 = std::remove_reference_t<
|
|
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 = std::remove_reference_t<
|
|
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
|