From 1cd56ab161c327bf3279314d7c33ab374190d636 Mon Sep 17 00:00:00 2001 From: Jamie Reece Wilson Date: Mon, 7 Aug 2023 22:51:18 +0100 Subject: [PATCH] [*] Minor AuByteBuffer TypeReadWrite "improvements" (more like, i cant be bothered to finish this in a clean way and we need a minimum viable product) --- Include/Aurora/Memory/ByteBuffer.hpp | 8 +- .../Memory/ByteBuffer_TypedReadWrite.inl | 142 +++++++++++++++++- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/Include/Aurora/Memory/ByteBuffer.hpp b/Include/Aurora/Memory/ByteBuffer.hpp index 4b0a22d1..a45f7408 100644 --- a/Include/Aurora/Memory/ByteBuffer.hpp +++ b/Include/Aurora/Memory/ByteBuffer.hpp @@ -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 T Read(); + // Panics if flagReadError is true by the end of deserialization + template + T ReadChecked(); + template bool Write(const T &in); diff --git a/Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl b/Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl index ebbb5ff9..3394d7ac 100644 --- a/Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl +++ b/Include/Aurora/Memory/ByteBuffer_TypedReadWrite.inl @@ -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 bool ByteBuffer::Read(T &out) { if constexpr (AuIsClass_v) { - if constexpr (AuIsBaseOfTemplate>::value) + if constexpr (AuIsTuple_v>) + { + AuTupleForEach(out, [=](auto &tupleElement) + { + Read(tupleElement); + }); + return !this->flagReadError; + } + else if constexpr (AuIsOptional_v>) + { + if (Read()) + { + AuRemoveReference_t value; + + Read(value); + + if (this->flagReadError) + { + return false; + } + else + { + out = T { AuMove(value) }; + return true; + } + } + else + { + return !this->flagReadError; + } + } + else if constexpr (AuIsBaseOfTemplate>::value) { if (Read() != 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(out[i]); + Read(out[i]); + } + + return !this->flagReadError; + } + else if constexpr (AuIsBST_v> || + AuIsHashMap_v>) + { + if (Read() != sizeof(typename T::key_type)) + { + this->flagReadError = true; + return false; + } + + if (Read() != sizeof(typename T::mapped_type)) + { + this->flagReadError = true; + return false; + } + + auto uLength = Read(); + 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 + T ByteBuffer::ReadChecked() + { + T a {}; + Read(a); + SysAssert(!this->flagReadError); + return a; + } + template bool ByteBuffer::Write(const T &in) { if constexpr (AuIsClass_v) { - if constexpr (AuIsBaseOfTemplate>::value) + if constexpr (AuIsTuple_v>) + { + AuTupleForEach(in, [=](auto &tupleElement) + { + Write(tupleElement); + }); + return !this->flagWriteError; + } + else if constexpr (AuIsOptional_v>) + { + Write(AuStaticCast(in)); + Write(in.value()); + return !this->flagWriteError; + } + else if constexpr (AuIsBaseOfTemplate>::value) { Write(sizeof(typename T::value_type)); Write(AuUInt32(in.size())); for (const auto &item : in) { - Write(item); + Write(item); + } + + return !this->flagWriteError; + } + else if constexpr (AuIsBST_v> || + AuIsHashMap_v>) + + { + Write(sizeof(typename T::key_type)); + Write(sizeof(typename T::mapped_type)); + Write(AuUInt32(in.size())); + + for (const auto &[key, value]: in) + { + Write(key); + Write(value); } return !this->flagWriteError;