#pragma once #include "../types.hpp" #include "../utils.hpp" #include #include namespace sibs { class DeserializeException : public std::runtime_error { public: DeserializeException(const std::string &errMsg) : std::runtime_error(errMsg) {} }; /** * Endian independent deserializer */ class SafeDeserializer { DISABLE_COPY(SafeDeserializer); public: SafeDeserializer(const u8 *_data, usize _size) : data(_data), size(_size) { } /* * Throws DeserializeException on failure */ template T&& extract() { constexpr usize typeSize = sizeof(T); verifyExtractSize(typeSize); size -= typeSize; T result; memcpy(&result, data, typeSize); data += typeSize; return std::move(result); } /* * Throws DeserializeException on failure */ void extract(u8 *destination, usize destinationSize) { if(destinationSize > 0) { verifyExtractSize(destinationSize); size -= destinationSize; memcpy(destination, data, destinationSize); data += destinationSize; } } bool empty() const { return size == 0; } const u8* getBuffer() { return data; } usize getSize() const { return size; } private: void verifyExtractSize(usize typeSize) const { if(typeSize > size) { std::string errMsg = "Unable to extract "; errMsg += std::to_string(typeSize); errMsg += " bytes, only "; errMsg += std::to_string(size); errMsg += " bytes left in buffer"; throw DeserializeException(errMsg); } } private: const u8 *data; usize size; }; }