[*] Minor AuByteBuffer TypeReadWrite "improvements"

(more like, i cant be bothered to finish this in a clean way and we need a minimum viable product)
This commit is contained in:
Reece Wilson 2023-08-07 22:51:18 +01:00
parent fc08e8351d
commit 1cd56ab161
2 changed files with 143 additions and 7 deletions

View File

@ -506,10 +506,16 @@ namespace Aurora::Memory
inline bool Pad(AuUInt16 aPowOf2, AuUInt8 magicCharacter = '\x00');
inline bool Fill(AuUInt length, AuUInt8 magicCharacter = '\x00');
// Typed read/write
// Templated read/write for **PODs**
// (yes, there's some support for non-primitive classes this early into the abstraction.)
// (AuString and some other containers may work, but really, we need a typed bytebuffer.)
template<typename T>
T Read();
// Panics if flagReadError is true by the end of deserialization
template<typename T>
T ReadChecked();
template<typename T>
bool Write(const T &in);

View File

@ -9,14 +9,49 @@
namespace Aurora::Memory
{
static const auto kMaxSaneElementsForAuMemory = 0xFFFFF;
#if !defined(AURORA_RUNTIME_BUFFER_MAX_ELEMS)
#define AURORA_RUNTIME_BUFFER_MAX_ELEMS 0xFFFFFu
#endif
static const auto kMaxSaneElementsForAuMemory = AURORA_RUNTIME_BUFFER_MAX_ELEMS;
template<typename T>
bool ByteBuffer::Read(T &out)
{
if constexpr (AuIsClass_v<T>)
{
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, AuRemoveReference_t<T>>::value)
if constexpr (AuIsTuple_v<AuRemoveReference_t<T>>)
{
AuTupleForEach(out, [=](auto &tupleElement)
{
Read(tupleElement);
});
return !this->flagReadError;
}
else if constexpr (AuIsOptional_v<AuRemoveReference_t<T>>)
{
if (Read<bool>())
{
AuRemoveReference_t<decltype(out.value())> value;
Read(value);
if (this->flagReadError)
{
return false;
}
else
{
out = T { AuMove(value) };
return true;
}
}
else
{
return !this->flagReadError;
}
}
else if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, AuRemoveReference_t<T>>::value)
{
if (Read<AuUInt32>() != sizeof(typename T::value_type))
{
@ -31,11 +66,67 @@ namespace Aurora::Memory
return false;
}
out.resize(uLength);
if (!AuTryResize(out, uLength))
{
this->flagReadError = true;
SysPushErrorMemory();
return false;
}
for (auto i = 0u; i < uLength; i++)
{
Read<T::value_type>(out[i]);
Read(out[i]);
}
return !this->flagReadError;
}
else if constexpr (AuIsBST_v<AuRemoveReference_t<T>> ||
AuIsHashMap_v<AuRemoveReference_t<T>>)
{
if (Read<AuUInt32>() != sizeof(typename T::key_type))
{
this->flagReadError = true;
return false;
}
if (Read<AuUInt32>() != sizeof(typename T::mapped_type))
{
this->flagReadError = true;
return false;
}
auto uLength = Read<AuUInt32>();
if (uLength > kMaxSaneElementsForAuMemory)
{
this->flagReadError = true;
return false;
}
if (!AuTryReserve(out, uLength))
{
this->flagReadError = true;
SysPushErrorMemory();
return false;
}
for (auto i = 0u; i < uLength; i++)
{
typename T::key_type key;
typename T::mapped_type value;
Read(key);
if (this->flagReadError)
{
return false;
}
Read(value);
if (this->flagReadError)
{
return false;
}
out[key] = value;
}
return !this->flagReadError;
@ -71,19 +162,58 @@ namespace Aurora::Memory
return a;
}
template<typename T>
T ByteBuffer::ReadChecked()
{
T a {};
Read(a);
SysAssert(!this->flagReadError);
return a;
}
template<typename T>
bool ByteBuffer::Write(const T &in)
{
if constexpr (AuIsClass_v<T>)
{
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, AuRemoveReference_t<T>>::value)
if constexpr (AuIsTuple_v<AuRemoveReference_t<T>>)
{
AuTupleForEach(in, [=](auto &tupleElement)
{
Write(tupleElement);
});
return !this->flagWriteError;
}
else if constexpr (AuIsOptional_v<AuRemoveReference_t<T>>)
{
Write<bool>(AuStaticCast<bool>(in));
Write(in.value());
return !this->flagWriteError;
}
else if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, AuRemoveReference_t<T>>::value)
{
Write<AuUInt32>(sizeof(typename T::value_type));
Write<AuUInt32>(AuUInt32(in.size()));
for (const auto &item : in)
{
Write<T::value_type>(item);
Write(item);
}
return !this->flagWriteError;
}
else if constexpr (AuIsBST_v<AuRemoveReference_t<T>> ||
AuIsHashMap_v<AuRemoveReference_t<T>>)
{
Write<AuUInt32>(sizeof(typename T::key_type));
Write<AuUInt32>(sizeof(typename T::mapped_type));
Write<AuUInt32>(AuUInt32(in.size()));
for (const auto &[key, value]: in)
{
Write(key);
Write(value);
}
return !this->flagWriteError;