mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
rx/serializer: fixed compilation with gcc
This commit is contained in:
parent
37f423aec3
commit
be56f0745a
|
|
@ -75,7 +75,7 @@ T callDeserializeFunction(Deserializer &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept SerializableImpl = requires(Serializer &s, const T &value) {
|
constexpr auto SerializableImpl = requires(Serializer &s, const T &value) {
|
||||||
value.serialize(s);
|
value.serialize(s);
|
||||||
} || requires(Serializer &s, const T &value) {
|
} || requires(Serializer &s, const T &value) {
|
||||||
callSerializeFunction(s, value);
|
callSerializeFunction(s, value);
|
||||||
|
|
@ -84,7 +84,7 @@ concept SerializableImpl = requires(Serializer &s, const T &value) {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept DeserializableImpl = requires(Deserializer &d, T &value) {
|
constexpr auto DeserializableImpl = requires(Deserializer &d, T &value) {
|
||||||
value.deserialize(d);
|
value.deserialize(d);
|
||||||
} || requires(Deserializer &d, T &value) {
|
} || requires(Deserializer &d, T &value) {
|
||||||
value = std::remove_cvref_t<T>::deserialize(d);
|
value = std::remove_cvref_t<T>::deserialize(d);
|
||||||
|
|
@ -99,16 +99,20 @@ concept DeserializableImpl = requires(Deserializer &d, T &value) {
|
||||||
} || requires(Deserializer &d, T &value) {
|
} || requires(Deserializer &d, T &value) {
|
||||||
TypeSerializer<std::remove_cvref_t<T>>::deserialize(d, value);
|
TypeSerializer<std::remove_cvref_t<T>>::deserialize(d, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto IsSerializable = SerializableImpl<T> && DeserializableImpl<T>;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept Serializable =
|
concept Serializable = detail::IsSerializable<T>;
|
||||||
detail::SerializableImpl<T> && detail::DeserializableImpl<T>;
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct SerializableFieldTest {
|
template <typename ClassT> struct SerializableFieldTest {
|
||||||
template <Serializable FieldT>
|
template <typename FieldT>
|
||||||
requires(std::is_default_constructible_v<FieldT>)
|
requires(std::is_default_constructible_v<FieldT> &&
|
||||||
|
!std::is_same_v<FieldT, ClassT> && detail::IsSerializable<FieldT>)
|
||||||
constexpr operator FieldT();
|
constexpr operator FieldT();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -121,7 +125,7 @@ template <typename T, std::size_t I> constexpr bool isSerializableField() {
|
||||||
std::index_sequence<Before...>,
|
std::index_sequence<Before...>,
|
||||||
std::index_sequence<After...>) {
|
std::index_sequence<After...>) {
|
||||||
return requires {
|
return requires {
|
||||||
T{(Before, SerializableAnyFieldTest{})..., SerializableFieldTest{},
|
T{(Before, SerializableAnyFieldTest{})..., SerializableFieldTest<T>{},
|
||||||
(After, SerializableAnyFieldTest{})...};
|
(After, SerializableAnyFieldTest{})...};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -130,18 +134,27 @@ template <typename T, std::size_t I> constexpr bool isSerializableField() {
|
||||||
std::make_index_sequence<rx::fieldCount<T> - I - 1>{});
|
std::make_index_sequence<rx::fieldCount<T> - I - 1>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N = rx::fieldCount<T>>
|
template <typename T> constexpr bool isSerializableFields() {
|
||||||
constexpr bool isSerializableFields() {
|
|
||||||
auto impl = []<std::size_t... I>(std::index_sequence<I...>) {
|
auto impl = []<std::size_t... I>(std::index_sequence<I...>) {
|
||||||
return requires { T{(I, SerializableFieldTest{})...}; };
|
return requires { T{(I, SerializableFieldTest<T>{})...}; };
|
||||||
};
|
};
|
||||||
|
|
||||||
return impl(std::make_index_sequence<N>{});
|
if constexpr (!std::is_class_v<T>) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
constexpr auto fieldCount = rx::fieldCount<T>;
|
||||||
|
|
||||||
|
if constexpr (fieldCount == 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return impl(std::make_index_sequence<fieldCount>{});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept SerializableClass = !detail::IsRange<T> && std::is_class_v<T> &&
|
constexpr auto SerializableClass =
|
||||||
rx::fieldCount<T> > 0 && isSerializableFields<T>();
|
!detail::IsRange<T> && isSerializableFields<T>();
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
struct Serializer {
|
struct Serializer {
|
||||||
|
|
@ -259,7 +272,8 @@ template <detail::TriviallyRelocatable T> struct TypeSerializer<T> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <Serializable A, Serializable B>
|
template <typename A, typename B>
|
||||||
|
requires detail::IsSerializable<A> && detail::IsSerializable<B>
|
||||||
struct TypeSerializer<std::pair<A, B>> {
|
struct TypeSerializer<std::pair<A, B>> {
|
||||||
static void serialize(Serializer &s, const std::pair<A, B> &t) {
|
static void serialize(Serializer &s, const std::pair<A, B> &t) {
|
||||||
s.serialize(t.first);
|
s.serialize(t.first);
|
||||||
|
|
@ -276,7 +290,9 @@ struct TypeSerializer<std::pair<A, B>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <Serializable... T> struct TypeSerializer<std::tuple<T...>> {
|
template <typename... T>
|
||||||
|
requires(detail::IsSerializable<T> && ...)
|
||||||
|
struct TypeSerializer<std::tuple<T...>> {
|
||||||
static void serialize(Serializer &s, const std::tuple<T...> &t) {
|
static void serialize(Serializer &s, const std::tuple<T...> &t) {
|
||||||
std::apply([&s](auto &value) { s.serialize(value); }, t);
|
std::apply([&s](auto &value) { s.serialize(value); }, t);
|
||||||
}
|
}
|
||||||
|
|
@ -288,9 +304,9 @@ template <Serializable... T> struct TypeSerializer<std::tuple<T...>> {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::is_default_constructible_v<T> &&
|
requires std::is_default_constructible_v<T> &&
|
||||||
requires(Serializer &s, T &object) {
|
(!detail::TriviallyRelocatable<T>) && requires(T &object) {
|
||||||
s.serialize(object.size());
|
requires detail::IsSerializable<decltype(object.size())>;
|
||||||
s.serialize(*object.begin());
|
requires detail::IsSerializable<decltype(*object.begin())>;
|
||||||
object.resize(1);
|
object.resize(1);
|
||||||
object.begin() != object.end();
|
object.begin() != object.end();
|
||||||
}
|
}
|
||||||
|
|
@ -334,12 +350,13 @@ struct TypeSerializer<T> {
|
||||||
template <detail::IsRange T>
|
template <detail::IsRange T>
|
||||||
requires(
|
requires(
|
||||||
std::is_default_constructible_v<T> &&
|
std::is_default_constructible_v<T> &&
|
||||||
requires(Serializer &s, T &object) {
|
(!detail::TriviallyRelocatable<T>) &&
|
||||||
s.serialize(object.size());
|
requires(T &object) {
|
||||||
s.serialize(*object.begin());
|
requires detail::IsSerializable<decltype(object.size())>;
|
||||||
|
requires detail::IsSerializable<decltype(*object.begin())>;
|
||||||
object.insert(std::move(*object.begin()));
|
object.insert(std::move(*object.begin()));
|
||||||
object.begin() != object.end();
|
object.begin() != object.end();
|
||||||
} && !requires(Serializer &s, T &object) { object.resize(1); })
|
} && !requires(T &object) { object.resize(1); })
|
||||||
struct TypeSerializer<T> {
|
struct TypeSerializer<T> {
|
||||||
using item_type = std::remove_cvref_t<decltype(*std::declval<T>().begin())>;
|
using item_type = std::remove_cvref_t<decltype(*std::declval<T>().begin())>;
|
||||||
|
|
||||||
|
|
@ -373,7 +390,7 @@ struct TypeSerializer<T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <SerializableClass T> struct StructSerializerBuilder {
|
template <typename T> struct StructSerializerBuilder {
|
||||||
static constexpr std::array<StructSerializerField, rx::fieldCount<T>>
|
static constexpr std::array<StructSerializerField, rx::fieldCount<T>>
|
||||||
build() {
|
build() {
|
||||||
StructSerializerBuilder result;
|
StructSerializerBuilder result;
|
||||||
|
|
@ -425,10 +442,8 @@ private:
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <detail::SerializableClass T>
|
template <typename T>
|
||||||
requires(!requires {
|
requires detail::SerializableClass<T> && (!detail::TriviallyRelocatable<T>)
|
||||||
std::index_sequence<detail::StructSerializerBuilder<T>::build().size()>{};
|
|
||||||
})
|
|
||||||
struct TypeSerializer<T> {
|
struct TypeSerializer<T> {
|
||||||
static const auto &getFields() {
|
static const auto &getFields() {
|
||||||
static const auto fields = detail::StructSerializerBuilder<T>::build();
|
static const auto fields = detail::StructSerializerBuilder<T>::build();
|
||||||
|
|
@ -458,37 +473,4 @@ struct TypeSerializer<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// all fields are constructable at compile time overload
|
|
||||||
template <detail::SerializableClass T>
|
|
||||||
requires requires {
|
|
||||||
std::index_sequence<detail::StructSerializerBuilder<T>::build().size()>{};
|
|
||||||
}
|
|
||||||
struct TypeSerializer<T> {
|
|
||||||
static constexpr auto fields = detail::StructSerializerBuilder<T>::build();
|
|
||||||
|
|
||||||
static void serialize(Serializer &s, const T &object) {
|
|
||||||
s.serialize<std::uint32_t>(sizeof(object));
|
|
||||||
auto bytes = std::bit_cast<std::byte *>(&object);
|
|
||||||
for (auto field : fields) {
|
|
||||||
field.serialize(s, bytes + field.offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void deserialize(Deserializer &s, T &object) {
|
|
||||||
if (s.deserialize<std::uint32_t>() != sizeof(object)) {
|
|
||||||
s.setFailure();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bytes = std::bit_cast<std::byte *>(&object);
|
|
||||||
for (auto field : fields) {
|
|
||||||
field.deserialize(s, bytes + field.offset);
|
|
||||||
|
|
||||||
if (s.failure()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace rx
|
} // namespace rx
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue