template <typename T>
concept C_IsIntType = C_IsAnyOf<T, int16, uint16, int32, uint32, int64, uint64>;
template <typename T>
concept C_IsFloatType = std::is_same_v<T, float32>;
template <typename T>
concept C_IsSerializable = C_IsIntType<T> || C_IsFloatType<T>;
struct FxSerializerValue
{
public:
enum Type
{
eInt,
eFloat,
};
public:
FxSerializerValue() = delete;
template <typename T>
requires C_IsIntType<T>
explicit FxSerializerValue(T value) : Type(eInt), IntValue(value)
{
}
template <typename T>
requires C_IsFloatType<T>
explicit FxSerializerValue(T value) : Type(eFloat), FloatValue(value)
{
}
public:
Type Type;
union
{
int64 IntValue;
float32 FloatValue;
};
};
class FxSerializer
{
public:
FxSerializer() { Values.Create(16); }
FxSerializer(const FxSerializer& other) = delete;
template <typename T>
requires C_IsSerializable<T>
FxSerializer& operator<<(T value)
{
Values.Insert(FxSerializerValue { value });
return *this;
}
template <typename T>
requires C_IsSerializable<T>
FxSerializer& Add(T& member)
{
if (bInWriteMode) {
(*this) << member;
}
else {
(*this) >> member;
}
return *this;
}
void SetWriteMode() { bInWriteMode = true; }
void SetReadMode() { bInWriteMode = false; }
template <typename T>
requires C_IsSerializable<T>
FxSerializer& operator>>(T& value)
{
if (WriteIndex > Values.Size()) {
return *this;
}
FxSerializerValue& stored_value = Values[WriteIndex++];
if constexpr (C_IsIntType<T>) {
value = stored_value.IntValue;
}
else if constexpr (C_IsFloatType<T>) {
value = stored_value.FloatValue;
}
return *this;
}
void Rewind() { WriteIndex = 0; }
public:
int WriteIndex = 0;
FxPagedArray<FxSerializerValue> Values;
bool bInWriteMode = true;
};
#define FX_SERIALIZABLE_MEMBERS(...) \
template <typename... TMemberTypes> \
void SerializerDefineRecursive(FxSerializer& s, TMemberTypes&... types) \
{ \
(s.Add(types), ...); \
} \
void SerializeNow(FxSerializer& s) { SerializerDefineRecursive(s, __VA_ARGS__); } \
void Serialize(FxSerializer& s) \
{ \
s.SetWriteMode(); \
SerializeNow(s); \
} \
void Deserialize(FxSerializer& s) \
{ \
s.SetReadMode(); \
SerializeNow(s); \
}
struct SerializeTest
{
FX_SERIALIZABLE_MEMBERS(X, Y);
void Print() { FxLogInfo("Object: [{}, {}]", X, Y); }
float X = 0;
int Y = 0;
};