aboutsummaryrefslogtreecommitdiff
path: root/sibs/SafeDeserializer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'sibs/SafeDeserializer.hpp')
-rw-r--r--sibs/SafeDeserializer.hpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/sibs/SafeDeserializer.hpp b/sibs/SafeDeserializer.hpp
new file mode 100644
index 0000000..3d83042
--- /dev/null
+++ b/sibs/SafeDeserializer.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include "../types.hpp"
+#include "../utils.hpp"
+#include <cstring>
+#include <stdexcept>
+
+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 <typename T>
+ 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;
+ };
+}