Files
Renderive/web_server/app/Web_Event_Adapter.h
T
2026-08-12 01:44:13 +08:00

97 lines
3.4 KiB
C++

#pragma once
#include "Web_Event.h"
#include <json/json.h>
#include <concepts>
#include <optional>
#include <string_view>
#include <type_traits>
#include <utility>
#include <variant>
namespace renderive::web {
using Web_Transport_Events = std::variant<Frame_Request, Viewport_Resize, Gallery_Request>;
using Render_2D_Web_Events = std::variant<Event, Pointer_Event, Wheel_Event, Key_Event>;
using Web_Demo_Control_Events = std::variant<Set_Demo_Mode,
Set_Center_Frequency,
Set_Bandwidth,
Set_Gain,
Set_Max_Hold,
Set_Smoothing,
Clear_Selection>;
struct Web_Transport_Event_Decoder {
using event_type = Web_Transport_Events;
[[nodiscard]] static std::optional<event_type> decode(const Json::Value& root,
std::string_view source);
};
struct Render_2D_Web_Event_Decoder {
using event_type = Render_2D_Web_Events;
[[nodiscard]] static std::optional<event_type> decode(const Json::Value& root,
std::string_view source);
};
struct Web_Demo_Control_Decoder {
using event_type = Web_Demo_Control_Events;
[[nodiscard]] static std::optional<event_type> decode(const Json::Value& root,
std::string_view source);
};
template <class Decoder>
concept Web_Event_Decoder = requires(const Json::Value& root, std::string_view source) {
typename Decoder::event_type;
{ Decoder::decode(root, source) } ->
std::same_as<std::optional<typename Decoder::event_type>>;
};
[[nodiscard]] std::optional<Json::Value> parse_web_event(std::string_view message);
template <class T>
struct Is_Variant : std::false_type {};
template <class... Values>
struct Is_Variant<std::variant<Values...>> : std::true_type {};
template <class Event_Variant, Web_Event_Decoder... Decoders>
class Basic_Web_Event_Adapter final {
public:
[[nodiscard]] static std::optional<Event_Variant> decode(std::string_view message) {
const auto root = parse_web_event(message);
if (!root)
return std::nullopt;
std::optional<Event_Variant> result;
([&] {
if (result)
return;
auto decoded = Decoders::decode(*root, message);
if (decoded)
result = widen(std::move(*decoded));
}(), ...);
return result;
}
private:
template <class Decoded>
static Event_Variant widen(Decoded decoded) {
if constexpr (Is_Variant<std::remove_cvref_t<Decoded>>::value) {
return std::visit([](auto&& value) -> Event_Variant {
return Event_Variant(std::forward<decltype(value)>(value));
}, std::move(decoded));
} else {
return Event_Variant(std::move(decoded));
}
}
};
using Web_Event_Adapter = Basic_Web_Event_Adapter<Web_Event,
Web_Transport_Event_Decoder,
Render_2D_Web_Event_Decoder,
Web_Demo_Control_Decoder>;
} // namespace renderive::web