Files
clio/src/rpc/common/AnyHandler.hpp
2026-09-08 14:45:42 +01:00

109 lines
2.8 KiB
C++

#pragma once
#include "rpc/common/Concepts.hpp"
#include "rpc/common/Types.hpp"
#include "rpc/common/impl/Processors.hpp"
#include <boost/json/value.hpp>
#include <memory>
namespace rpc {
/**
* @brief A type-erased Handler that can contain any (NextGen) RPC handler class
*
* This allows to store different handlers in one map/vector etc.
* Support for copying was added in order to allow storing in a
* map/unordered_map using the initializer_list constructor.
*/
class AnyHandler final {
public:
/**
* @brief Type-erases any handler class.
*
* @tparam HandlerType The real type of wrapped handler class
* @tparam ProcessingStrategy A strategy that implements how processing of JSON is to be done
* @param handler The handler to wrap. Required to fulfil the @ref rpc::SomeHandler concept.
*/
template <
SomeHandler HandlerType,
typename ProcessingStrategy = impl::DefaultProcessor<HandlerType>>
/* implicit */ AnyHandler(HandlerType&& handler)
: pimpl_{std::make_unique<Model<HandlerType, ProcessingStrategy>>(
std::forward<HandlerType>(handler)
)}
{
}
/** @cond */
~AnyHandler() = default;
AnyHandler(AnyHandler const& other) : pimpl_{other.pimpl_->clone()}
{
}
AnyHandler&
operator=(AnyHandler const& rhs)
{
AnyHandler copy{rhs};
pimpl_.swap(copy.pimpl_);
return *this;
}
AnyHandler(AnyHandler&&) = default;
AnyHandler&
operator=(AnyHandler&&) = default;
/** @endcond */
/**
* @brief Process incoming JSON by the stored handler
*
* @param value The JSON to process
* @param ctx Request context
* @return JSON result or Status on error
*/
[[nodiscard]] ReturnType
process(boost::json::value const& value, Context const& ctx) const
{
return pimpl_->process(value, ctx);
}
private:
struct Concept {
virtual ~Concept() = default;
[[nodiscard]] virtual ReturnType
process(boost::json::value const& value, Context const& ctx) const = 0;
[[nodiscard]] virtual std::unique_ptr<Concept>
clone() const = 0;
};
template <typename HandlerType, typename ProcessorType>
struct Model : Concept {
HandlerType handler;
ProcessorType processor;
Model(HandlerType&& handler) : handler{std::move(handler)}
{
}
[[nodiscard]] ReturnType
process(boost::json::value const& value, Context const& ctx) const override
{
return processor(handler, value, ctx);
}
[[nodiscard]] std::unique_ptr<Concept>
clone() const override
{
return std::make_unique<Model>(*this);
}
};
private:
std::unique_ptr<Concept> pimpl_;
};
} // namespace rpc