Files
banan-os/userspace/libraries/LibGUI/include/LibGUI/Packet.h

386 lines
8.6 KiB
C++

#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/String.h>
#include <BAN/StringView.h>
#include <BAN/Vector.h>
#include <LibInput/KeyEvent.h>
#include <LibInput/MouseEvent.h>
#define FOR_EACH_0(macro)
#define FOR_EACH_2(macro, type, name) macro(type, name)
#define FOR_EACH_4(macro, type, name, ...) macro(type, name) FOR_EACH_2(macro, __VA_ARGS__)
#define FOR_EACH_6(macro, type, name, ...) macro(type, name) FOR_EACH_4(macro, __VA_ARGS__)
#define FOR_EACH_8(macro, type, name, ...) macro(type, name) FOR_EACH_6(macro, __VA_ARGS__)
#define FOR_EACH_10(macro, type, name, ...) macro(type, name) FOR_EACH_8(macro, __VA_ARGS__)
#define CONCATENATE_2(arg1, arg2) arg1 ## arg2
#define CONCATENATE_1(arg1, arg2) CONCATENATE_2(arg1, arg2)
#define CONCATENATE(arg1, arg2) CONCATENATE_1(arg1, arg2)
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__ __VA_OPT__(,) FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__)
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
#define FOR_EACH_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what __VA_OPT__(,) __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what __VA_OPT__(,) __VA_ARGS__)
#define FIELD_DECL(type, name) type name;
#define ADD_SERIALIZED_SIZE(type, name) serialized_size += Serialize::serialized_size_impl<type>(this->name);
#define SERIALIZE(type, name) Serialize::serialize_impl<type>(buffer, this->name);
#define DESERIALIZE(type, name) value.name = TRY(Serialize::deserialize_impl<type>(buffer));
#define DEFINE_PACKET_EXTRA(name, extra, ...) \
struct name \
{ \
extra; \
\
FOR_EACH(FIELD_DECL, __VA_ARGS__) \
\
size_t serialized_size() const \
{ \
size_t serialized_size = 0; \
serialized_size += Serialize::serialized_size_impl(PacketHeader {}); \
FOR_EACH(ADD_SERIALIZED_SIZE, __VA_ARGS__) \
return serialized_size; \
} \
\
void serialize(BAN::ByteSpan buffer) const \
{ \
const uint32_t serialized_size = this->serialized_size(); \
Serialize::serialize_impl(buffer, PacketHeader { \
.size = serialized_size, \
.type = PacketType::name, \
}); \
FOR_EACH(SERIALIZE, __VA_ARGS__); \
} \
\
static BAN::ErrorOr<name> deserialize(BAN::ConstByteSpan buffer) \
{ \
const auto header = TRY(Serialize::deserialize_impl<PacketHeader>(buffer)); \
if (header.type != PacketType::name || header.size != buffer.size() + sizeof(PacketHeader)) \
return BAN::Error::from_errno(EINVAL); \
name value; \
FOR_EACH(DESERIALIZE, __VA_ARGS__) \
return value; \
} \
}
#define DEFINE_PACKET(name, ...) DEFINE_PACKET_EXTRA(name, , __VA_ARGS__)
namespace LibGUI
{
namespace detail
{
template<typename T>
concept Vector = requires {
requires BAN::same_as<T, BAN::Vector<typename T::value_type>>;
};
}
static constexpr BAN::StringView s_window_server_socket = "/tmp/window-server.socket"_sv;
namespace Serialize
{
inline void append_raw_data(BAN::ByteSpan& buffer, BAN::ConstByteSpan data)
{
ASSERT(buffer.size() >= data.size());
memcpy(buffer.data(), data.data(), data.size());
buffer = buffer.slice(data.size());
}
template<typename T> requires BAN::is_pod_v<T>
inline size_t serialized_size_impl(const T&)
{
return sizeof(T);
}
template<typename T> requires BAN::is_pod_v<T>
inline void serialize_impl(BAN::ByteSpan& buffer, const T& value)
{
append_raw_data(buffer, BAN::ConstByteSpan::from(value));
}
template<typename T> requires BAN::is_pod_v<T>
inline BAN::ErrorOr<T> deserialize_impl(BAN::ConstByteSpan& buffer)
{
if (buffer.size() < sizeof(T))
return BAN::Error::from_errno(ENOBUFS);
const T value = buffer.as<const T>();
buffer = buffer.slice(sizeof(T));
return value;
}
template<typename T> requires BAN::is_same_v<T, BAN::String>
inline size_t serialized_size_impl(const T& value)
{
return sizeof(uint32_t) + value.size();
}
template<typename T> requires BAN::is_same_v<T, BAN::String>
inline void serialize_impl(BAN::ByteSpan& buffer, const T& value)
{
const uint32_t value_size = value.size();
append_raw_data(buffer, BAN::ConstByteSpan::from(value_size));
auto* u8_data = reinterpret_cast<const uint8_t*>(value.data());
append_raw_data(buffer, BAN::ConstByteSpan(u8_data, value.size()));
}
template<typename T> requires BAN::is_same_v<T, BAN::String>
inline BAN::ErrorOr<T> deserialize_impl(BAN::ConstByteSpan& buffer)
{
if (buffer.size() < sizeof(uint32_t))
return BAN::Error::from_errno(ENOBUFS);
const uint32_t string_len = buffer.as<const uint32_t>();
buffer = buffer.slice(sizeof(uint32_t));
if (buffer.size() < string_len)
return BAN::Error::from_errno(ENOBUFS);
BAN::String string;
TRY(string.resize(string_len));
memcpy(string.data(), buffer.data(), string_len);
buffer = buffer.slice(string_len);
return string;
}
template<detail::Vector T>
inline size_t serialized_size_impl(const T& vector)
{
size_t result = sizeof(uint32_t);
for (const auto& element : vector)
result += serialized_size_impl(element);
return result;
}
template<detail::Vector T>
inline void serialize_impl(BAN::ByteSpan& buffer, const T& vector)
{
const uint32_t value_size = vector.size();
append_raw_data(buffer, BAN::ConstByteSpan::from(value_size));
for (const auto& element : vector)
serialize_impl(buffer, element);
}
template<detail::Vector T>
inline BAN::ErrorOr<T> deserialize_impl(BAN::ConstByteSpan& buffer)
{
if (buffer.size() < sizeof(uint32_t))
return BAN::Error::from_errno(ENOBUFS);
const uint32_t vector_size = buffer.as<const uint32_t>();
buffer = buffer.slice(sizeof(uint32_t));
T vector;
TRY(vector.resize(vector_size));
for (auto& element : vector)
element = TRY(deserialize_impl<typename T::value_type>(buffer));
return vector;
}
}
enum class PacketType : uint32_t
{
WindowCreate,
WindowCreateResponse,
WindowInvalidate,
WindowSetPosition,
WindowSetAttributes,
WindowSetMouseRelative,
WindowSetSize,
WindowSetMinSize,
WindowSetMaxSize,
WindowSetFullscreen,
WindowSetTitle,
WindowSetCursor,
DestroyWindowEvent,
CloseWindowEvent,
ResizeWindowEvent,
WindowShownEvent,
WindowFocusEvent,
WindowFullscreenEvent,
KeyEvent,
MouseButtonEvent,
MouseMoveEvent,
MouseScrollEvent,
};
struct PacketHeader
{
uint32_t size;
PacketType type;
};
namespace WindowPacket
{
struct Attributes
{
bool title_bar;
bool movable;
bool focusable;
bool rounded_corners;
bool alpha_channel;
bool resizable;
bool shown;
bool cursor_visible;
};
DEFINE_PACKET(
WindowCreate,
uint32_t, width,
uint32_t, height,
Attributes, attributes,
BAN::String, title
);
DEFINE_PACKET(
WindowInvalidate,
uint32_t, x,
uint32_t, y,
uint32_t, width,
uint32_t, height
);
DEFINE_PACKET(
WindowSetPosition,
int32_t, x,
int32_t, y
);
DEFINE_PACKET(
WindowSetAttributes,
Attributes, attributes
);
DEFINE_PACKET(
WindowSetMouseRelative,
bool, enabled
);
DEFINE_PACKET(
WindowSetSize,
uint32_t, width,
uint32_t, height
);
DEFINE_PACKET(
WindowSetMinSize,
uint32_t, width,
uint32_t, height
);
DEFINE_PACKET(
WindowSetMaxSize,
uint32_t, width,
uint32_t, height
);
DEFINE_PACKET(
WindowSetFullscreen,
bool, fullscreen
);
DEFINE_PACKET(
WindowSetTitle,
BAN::String, title
);
DEFINE_PACKET(
WindowSetCursor,
uint32_t, width,
uint32_t, height,
int32_t, origin_x,
int32_t, origin_y,
BAN::Vector<uint32_t>, pixels
);
}
namespace EventPacket
{
DEFINE_PACKET(
DestroyWindowEvent
);
DEFINE_PACKET(
CloseWindowEvent
);
DEFINE_PACKET(
ResizeWindowEvent,
uint32_t, width,
uint32_t, height,
long, smo_key
);
DEFINE_PACKET_EXTRA(
WindowShownEvent,
struct event_t {
bool shown;
},
event_t, event
);
DEFINE_PACKET_EXTRA(
WindowFocusEvent,
struct event_t {
bool focused;
},
event_t, event
);
DEFINE_PACKET_EXTRA(
WindowFullscreenEvent,
struct event_t {
bool fullscreen;
},
event_t, event
);
DEFINE_PACKET_EXTRA(
KeyEvent,
using event_t = LibInput::KeyEvent,
event_t, event
);
DEFINE_PACKET_EXTRA(
MouseButtonEvent,
struct event_t {
LibInput::MouseButton button;
bool pressed;
int32_t x;
int32_t y;
},
event_t, event
);
DEFINE_PACKET_EXTRA(
MouseMoveEvent,
struct event_t {
int32_t x;
int32_t y;
},
event_t, event
);
DEFINE_PACKET_EXTRA(
MouseScrollEvent,
struct event_t {
int32_t scroll;
},
event_t, event
);
}
}