97 lines
3.4 KiB
C++
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
|