pipeline/include/freepipe/freepipe.hpp
2025-08-10 17:30:51 +01:00

152 lines
4.6 KiB
C++

// Copyright 2025, Luís Murta
// SPDX-License-Identifier: MIT
#pragma once
#include <any>
#include <boost/asio.hpp>
#include <concepts>
// #include <expected>
#include <functional>
#include <optional>
#include <ostream>
#include <tuple>
#include <utility>
namespace freepipe {
template <typename... Args> struct Task {
explicit constexpr Task(std::shared_ptr<boost::asio::io_context> ioc, Args &&...args)
requires(sizeof...(Args) > 0)
: ioc_(std::move(ioc)), args_(std::forward<Args>(args)...) {}
explicit constexpr Task(std::shared_ptr<boost::asio::io_context> ioc)
requires(sizeof...(Args) == 0)
: ioc_(std::move(ioc)) {}
constexpr auto const &operator*() const & { return args_; }
constexpr auto &operator*() & { return args_; }
constexpr auto &&operator*() && { return std::move(args_); }
constexpr auto const &&operator*() const && { return std::move(args_); }
std::shared_ptr<boost::asio::io_context> ioc_;
private:
std::tuple<Args...> args_;
};
template <typename... Args, std::regular_invocable<Args...> F>
constexpr auto operator|(Task<Args...> const &task, F &&func) {
using R = std::invoke_result_t<F, Args...>;
if constexpr (std::is_void_v<R>) {
std::apply(std::forward<F>(func), *task);
return boost::asio::post(task.ioc_, Task<>{task.ioc_});
} else {
return Task<R>{task.ioc_, std::apply(std::forward<F>(func), *task)};
}
}
template <typename... Args, std::regular_invocable<Args...> F>
constexpr auto operator|(Task<Args...> &&task, F &&func) {
using R = std::invoke_result_t<F, Args...>;
if constexpr (std::is_void_v<R>) {
boost::asio::post(*task.ioc_, [&] { std::apply(std::forward<F>(func), std::move(*task)); });
return Task<>{task.ioc_};
} else {
return Task<R>{task.ioc_, std::apply(std::forward<F>(func), std::move(*task))};
}
}
template <typename... Args, std::regular_invocable<Args...>... F>
constexpr auto operator|(Task<Args...> const &task, std::tuple<F...> &&func) {
std::tuple<std::invoke_result_t<F, Args...>...> ret;
auto l = [&](auto &&f) {
using R = std::invoke_result_t<decltype(f), Args...>;
if constexpr (std::is_void_v<R>) {
std::apply(std::forward<decltype(f)>(f), *task);
return;
} else {
return std::apply(std::forward<decltype(f)>(f), *task);
}
};
std::apply(l, func);
return std::make_from_tuple<Task>(std::apply(
[&]<std::size_t... Is>(F &&...f) {
return Task<std::invoke_result_t<F, Args...>...>(
l(std::forward<F>(f), std::index_sequence<Is...>{})...);
},
std::move(func)));
// (
// [&] {
// using R = std::invoke_result_t<F, Args...>;
// if constexpr (std::is_void_v<R>) {
// std::apply(std::forward<F>(func), *task);
// } else {
// std::get<R>(ret) = std::apply(std::forward<F>(func), *task);
// }
// }(),
// ...);
// auto ans = std::apply(
// [](auto &&f) {
// return Task(
// if constexpr (std::is_void_v<decltype(f)>) { return Task<>{}; } else {
// return Task<decltype(f)>{f};
// },
// f...);
// },
// std::move(func));
// return std::make_from_tuple<Task>(std::move(ret));
}
template <typename... Args, std::regular_invocable<Args...>... F>
constexpr auto operator|(Task<Args...> &&task, std::tuple<F...> &&func) {
std::tuple<std::invoke_result_t<F, Args...>...> ret;
(
[&] {
using R = std::invoke_result_t<F, Args...>;
if constexpr (std::is_void_v<R>) {
std::apply(std::forward<F>(func), *std::move(task));
} else {
std::get<R>(ret) = std::apply(std::forward<F>(func), *std::move(task));
}
}(),
...);
return std::make_from_tuple<Task>(std::move(ret));
}
template <typename... Args, typename CharT, typename Traits = std::char_traits<CharT>>
constexpr auto operator|(Task<Args...> const &task, std::basic_ostream<CharT, Traits> &os) {
std::apply([&os](auto &&...args) { ((os << args << '\n'), ...); }, *task);
return Task<>{task.ioc_};
}
template <typename... Args, typename CharT, typename Traits = std::char_traits<CharT>>
constexpr auto operator|(Task<Args...> &&task, std::basic_ostream<CharT, Traits> &os) {
std::apply([&os](auto &&...args) { ((os << args << '\n'), ...); }, std::move(*task));
return Task<>{task.ioc_};
}
class Pipe : public Task<> {
// std::shared_ptr<boost::asio::io_context> io_context_;
public:
Pipe() : Task<>(std::make_shared<boost::asio::io_context>()) {}
explicit Pipe(std::shared_ptr<boost::asio::io_context> io_context) : Task<>{io_context} {}
};
} // namespace freepipe