mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
AK: Define our own concept of "trivially serializable"
While at it, rename the `read_trivial_value` and `write_trivial_value` functions to `read_value` and `write_value` respectively, since we'll add compatibility for non-trivial types down the line.
This commit is contained in:
parent
6777cb0975
commit
d1711f1cef
Notes:
sideshowbarker
2024-07-17 01:38:22 +09:00
Author: https://github.com/timschumi Commit: https://github.com/SerenityOS/serenity/commit/d1711f1cef Pull-request: https://github.com/SerenityOS/serenity/pull/17029 Reviewed-by: https://github.com/trflynn89 ✅
5 changed files with 23 additions and 14 deletions
|
@ -20,6 +20,7 @@ struct GenericTraits {
|
||||||
using PeekType = T&;
|
using PeekType = T&;
|
||||||
using ConstPeekType = T const&;
|
using ConstPeekType = T const&;
|
||||||
static constexpr bool is_trivial() { return false; }
|
static constexpr bool is_trivial() { return false; }
|
||||||
|
static constexpr bool is_trivially_serializable() { return false; }
|
||||||
static constexpr bool equals(T const& a, T const& b) { return a == b; }
|
static constexpr bool equals(T const& a, T const& b) { return a == b; }
|
||||||
template<Concepts::HashCompatible<T> U>
|
template<Concepts::HashCompatible<T> U>
|
||||||
static bool equals(U const& a, T const& b) { return a == b; }
|
static bool equals(U const& a, T const& b) { return a == b; }
|
||||||
|
@ -32,6 +33,7 @@ struct Traits : public GenericTraits<T> {
|
||||||
template<Integral T>
|
template<Integral T>
|
||||||
struct Traits<T> : public GenericTraits<T> {
|
struct Traits<T> : public GenericTraits<T> {
|
||||||
static constexpr bool is_trivial() { return true; }
|
static constexpr bool is_trivial() { return true; }
|
||||||
|
static constexpr bool is_trivially_serializable() { return true; }
|
||||||
static constexpr unsigned hash(T value)
|
static constexpr unsigned hash(T value)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(T) < 8)
|
if constexpr (sizeof(T) < 8)
|
||||||
|
@ -45,6 +47,7 @@ struct Traits<T> : public GenericTraits<T> {
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
struct Traits<T> : public GenericTraits<T> {
|
struct Traits<T> : public GenericTraits<T> {
|
||||||
static constexpr bool is_trivial() { return true; }
|
static constexpr bool is_trivial() { return true; }
|
||||||
|
static constexpr bool is_trivially_serializable() { return true; }
|
||||||
static constexpr unsigned hash(T value)
|
static constexpr unsigned hash(T value)
|
||||||
{
|
{
|
||||||
if constexpr (sizeof(T) < 8)
|
if constexpr (sizeof(T) < 8)
|
||||||
|
@ -65,6 +68,7 @@ template<Enum T>
|
||||||
struct Traits<T> : public GenericTraits<T> {
|
struct Traits<T> : public GenericTraits<T> {
|
||||||
static unsigned hash(T value) { return Traits<UnderlyingType<T>>::hash(to_underlying(value)); }
|
static unsigned hash(T value) { return Traits<UnderlyingType<T>>::hash(to_underlying(value)); }
|
||||||
static constexpr bool is_trivial() { return Traits<UnderlyingType<T>>::is_trivial(); }
|
static constexpr bool is_trivial() { return Traits<UnderlyingType<T>>::is_trivial(); }
|
||||||
|
static constexpr bool is_trivially_serializable() { return Traits<UnderlyingType<T>>::is_trivially_serializable(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -109,8 +109,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires(IsTriviallyDestructible<T>)
|
requires(Traits<T>::is_trivially_serializable())
|
||||||
ErrorOr<T> read_trivial_value()
|
ErrorOr<T> read_value()
|
||||||
{
|
{
|
||||||
alignas(T) u8 buffer[sizeof(T)] = {};
|
alignas(T) u8 buffer[sizeof(T)] = {};
|
||||||
TRY(read_entire_buffer({ &buffer, sizeof(buffer) }));
|
TRY(read_entire_buffer({ &buffer, sizeof(buffer) }));
|
||||||
|
@ -118,8 +118,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
requires(IsTriviallyDestructible<T>)
|
requires(Traits<T>::is_trivially_serializable())
|
||||||
ErrorOr<void> write_trivial_value(T const& value)
|
ErrorOr<void> write_value(T const& value)
|
||||||
{
|
{
|
||||||
return write_entire_buffer({ &value, sizeof(value) });
|
return write_entire_buffer({ &value, sizeof(value) });
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,10 +79,10 @@ ErrorOr<void> Name::write_to_stream(Core::Stream::Stream& stream) const
|
||||||
{
|
{
|
||||||
auto parts = as_string().split_view('.');
|
auto parts = as_string().split_view('.');
|
||||||
for (auto& part : parts) {
|
for (auto& part : parts) {
|
||||||
TRY(stream.write_trivial_value<u8>(part.length()));
|
TRY(stream.write_value<u8>(part.length()));
|
||||||
TRY(stream.write_entire_buffer(part.bytes()));
|
TRY(stream.write_entire_buffer(part.bytes()));
|
||||||
}
|
}
|
||||||
TRY(stream.write_trivial_value('\0'));
|
TRY(stream.write_value('\0'));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,23 +51,23 @@ ErrorOr<ByteBuffer> Packet::to_byte_buffer() const
|
||||||
|
|
||||||
Core::Stream::AllocatingMemoryStream stream;
|
Core::Stream::AllocatingMemoryStream stream;
|
||||||
|
|
||||||
TRY(stream.write_trivial_value(header));
|
TRY(stream.write_value(header));
|
||||||
for (auto& question : m_questions) {
|
for (auto& question : m_questions) {
|
||||||
TRY(question.name().write_to_stream(stream));
|
TRY(question.name().write_to_stream(stream));
|
||||||
TRY(stream.write_trivial_value(htons((u16)question.record_type())));
|
TRY(stream.write_value(htons((u16)question.record_type())));
|
||||||
TRY(stream.write_trivial_value(htons(question.raw_class_code())));
|
TRY(stream.write_value(htons(question.raw_class_code())));
|
||||||
}
|
}
|
||||||
for (auto& answer : m_answers) {
|
for (auto& answer : m_answers) {
|
||||||
TRY(answer.name().write_to_stream(stream));
|
TRY(answer.name().write_to_stream(stream));
|
||||||
TRY(stream.write_trivial_value(htons((u16)answer.type())));
|
TRY(stream.write_value(htons((u16)answer.type())));
|
||||||
TRY(stream.write_trivial_value(htons(answer.raw_class_code())));
|
TRY(stream.write_value(htons(answer.raw_class_code())));
|
||||||
TRY(stream.write_trivial_value(htonl(answer.ttl())));
|
TRY(stream.write_value(htonl(answer.ttl())));
|
||||||
if (answer.type() == RecordType::PTR) {
|
if (answer.type() == RecordType::PTR) {
|
||||||
Name name { answer.record_data() };
|
Name name { answer.record_data() };
|
||||||
TRY(stream.write_trivial_value(htons(name.serialized_size())));
|
TRY(stream.write_value(htons(name.serialized_size())));
|
||||||
TRY(name.write_to_stream(stream));
|
TRY(name.write_to_stream(stream));
|
||||||
} else {
|
} else {
|
||||||
TRY(stream.write_trivial_value(htons(answer.record_data().length())));
|
TRY(stream.write_value(htons(answer.record_data().length())));
|
||||||
TRY(stream.write_entire_buffer(answer.record_data().bytes()));
|
TRY(stream.write_entire_buffer(answer.record_data().bytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,3 +97,8 @@ private:
|
||||||
static_assert(sizeof(PacketHeader) == 12);
|
static_assert(sizeof(PacketHeader) == 12);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct AK::Traits<DNS::PacketHeader> : public AK::GenericTraits<DNS::PacketHeader> {
|
||||||
|
static constexpr bool is_trivially_serializable() { return true; }
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue