#ifndef DESERIALIZATION_H_ #define DESERIALIZATION_H_ #include #include #include #include "basic_types.hpp" namespace mysql { // Utility void check_size(ReadIterator from, ReadIterator last, std::size_t sz); inline std::string_view get_string(ReadIterator from, std::size_t size) { return std::string_view {reinterpret_cast(from), size}; } // Fixed size template struct get_size { static constexpr std::size_t value = std::size_t(-1); }; template <> struct get_size { static constexpr std::size_t value = 1; }; template <> struct get_size { static constexpr std::size_t value = 2; }; template <> struct get_size { static constexpr std::size_t value = 3; }; template <> struct get_size { static constexpr std::size_t value = 4; }; template <> struct get_size { static constexpr std::size_t value = 6; }; template <> struct get_size { static constexpr std::size_t value = 8; }; template <> struct get_size { static constexpr std::size_t value = 1; }; template <> struct get_size { static constexpr std::size_t value = 2; }; template <> struct get_size { static constexpr std::size_t value = 4; }; template <> struct get_size { static constexpr std::size_t value = 8; }; template struct get_size> { static constexpr std::size_t value = size; }; template constexpr std::size_t get_size_v = get_size::value; template constexpr bool is_fixed_size_v = get_size_v != std::size_t(-1); template void little_to_native(T& value) { boost::endian::little_to_native_inplace(value); } template <> inline void little_to_native(int3& value) { boost::endian::little_to_native_inplace(value.value); } template <> inline void little_to_native(int6& value) { boost::endian::little_to_native_inplace(value.value); } template void little_to_native(string_fixed&) {} // Deserialization functions template std::enable_if_t, ReadIterator> deserialize(ReadIterator from, ReadIterator last, T& output) { check_size(from, last, get_size_v); memset(&output, 0, sizeof(T)); memcpy(&output, from, get_size_v); little_to_native(output); return from + get_size_v; } ReadIterator deserialize(ReadIterator from, ReadIterator last, int_lenenc& output); ReadIterator deserialize(ReadIterator from, ReadIterator last, string_null& output); inline ReadIterator deserialize(ReadIterator from, ReadIterator last, string_eof& output) { output.value = get_string(from, last-from); return last; } inline ReadIterator deserialize(ReadIterator from, ReadIterator last, std::string_view& output, std::size_t size) { check_size(from, last, size); output = get_string(from, size); return from + size; } inline ReadIterator deserialize(ReadIterator from, ReadIterator last, void* output, std::size_t size) { check_size(from, last, size); memcpy(output, from, size); return from + size; } inline ReadIterator deserialize(ReadIterator from, ReadIterator last, string_lenenc& output) { int_lenenc length; from = deserialize(from, last, length); from = deserialize(from, last, output.value, length.value); return from; } template std::enable_if_t, ReadIterator> deserialize(ReadIterator from, ReadIterator last, T& to) { std::underlying_type_t value; ReadIterator res = deserialize(from, last, value); to = static_cast(value); return res; } inline ReadIterator deserialize(ReadIterator from, ReadIterator last, nullptr_t&) { return from; } template ReadIterator deserialize(const std::vector& from, T& to) { return deserialize(from.data(), from.data() + from.size(), to); } // SERIALIZATION class DynamicBuffer { std::vector buffer_; public: DynamicBuffer() = default; void add(const void* data, std::size_t size) { auto current_size = buffer_.size(); buffer_.resize(current_size+size); memcpy(buffer_.data() + current_size, data, size); } void add(std::uint8_t value) { buffer_.push_back(value); } const void* data() const { return buffer_.data(); } void* data() { return buffer_.data(); } std::size_t size() const { return buffer_.size(); } const std::vector& get() const { return buffer_; } }; template void native_to_little(T& value) { boost::endian::native_to_little_inplace(value); } template <> inline void native_to_little(int3& value) { boost::endian::native_to_little_inplace(value.value); } template <> inline void native_to_little(int6& value) { boost::endian::native_to_little_inplace(value.value); } template std::enable_if_t> serialize(DynamicBuffer& buffer, T value) { native_to_little(value); buffer.add(&value, get_size_v); } template <> inline void serialize(DynamicBuffer& buffer, int1 value) { buffer.add(value); } template void serialize(DynamicBuffer& buffer, const string_fixed& value) { buffer.add(value, sizeof(value)); } void serialize(DynamicBuffer& buffer, int_lenenc value); inline void serialize(DynamicBuffer& buffer, const std::string_view& value) { buffer.add(value.data(), value.size()); } inline void serialize(DynamicBuffer& buffer, const string_null& value) { serialize(buffer, value.value); serialize(buffer, int1(0)); } inline void serialize(DynamicBuffer& buffer, const string_eof& value) { serialize(buffer, value.value); } inline void serialize(DynamicBuffer& buffer, const string_lenenc& value) { serialize(buffer, int_lenenc {value.value.size()}); serialize(buffer, value.value); } template std::enable_if_t> serialize(DynamicBuffer& buffer, T value) { serialize(buffer, static_cast>(value)); } inline void serialize(DynamicBuffer&, nullptr_t) {}; } #endif /* DESERIALIZATION_H_ */