#ifndef _VKSSERIALIZER_HPP #define _VKSSERIALIZER_HPP /*------------------------------------------------------------------------- * Vulkan CTS Framework * -------------------- * * Copyright (c) 2021 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *-------------------------------------------------------------------------*/ #include "vksCommon.hpp" #include "vksEndian.hpp" #include #include #include namespace vksc_server { struct ToWrite { typedef const void* VoidPointer; static void SerializeData (vector& buffer, msize& pos, VoidPointer data, msize size) { if (size == 0) return; if ((pos + size) > buffer.size()) buffer.resize(pos + size); memmove(buffer.data() + pos, data, size); pos += size; } }; struct ToRead { typedef void* VoidPointer; static void SerializeData (vector& buffer, msize& pos, VoidPointer data, msize size) { if (size == 0) return; if ( (pos + size) > buffer.size() ) throw std::runtime_error("SerializeData::ToRead unexpected end"); memmove(data, buffer.data() + pos, size); pos += size; } }; template class Serializer { vector& Data; msize Pos{}; public: Serializer (vector& data) : Data(data) {} void SerializeRawData (typename TYPE::VoidPointer data, msize size) { TYPE::SerializeData(Data, Pos, data, size); } template void SerializeObject (T& obj) { obj.Serialize(*this); } void Serialize () { } template void Serialize (ARG&& arg) { SerializeItem(*this, arg); } template void Serialize (ARG&& first, ARGs&&... args) { SerializeItem(*this, first); Serialize(args...); } }; template inline void SerializeItem (TYPE& serializer, u8& val) { serializer.SerializeRawData(&val, sizeof(u8)); } inline void SerializeItem (Serializer& serializer, u32& val) { u32 nval; serializer.SerializeRawData(&nval, sizeof(u32)); val = NetworkToHost32(nval); } inline void SerializeItem (Serializer& serializer, u32& val) { u32 nval = HostToNetwork32(val); serializer.SerializeRawData(&nval, sizeof(u32)); } inline void SerializeItem (Serializer& serializer, u64& val) { u64 nval; serializer.SerializeRawData(&nval, sizeof(u64)); val = NetworkToHost64(nval); } inline void SerializeItem (Serializer& serializer, u64& val) { u64 nval = HostToNetwork64(val); serializer.SerializeRawData(&nval, sizeof(u64)); } inline void SerializeItem (Serializer& serializer, s32& val) { u32 nval; serializer.SerializeRawData(&nval, sizeof(u32)); val = static_cast(NetworkToHost32(nval)); } inline void SerializeItem (Serializer& serializer, s32& val) { u32 nval = HostToNetwork32(static_cast(val)); serializer.SerializeRawData(&nval, sizeof(u32)); } inline void SerializeItem (Serializer& serializer, bool& v) { u8 byte; serializer.Serialize(byte); if (byte == 0) v = false; else if (byte == 1) v = true; else throw std::runtime_error("SerializeItem(Serializer, bool) invalid bool value"); } inline void SerializeItem (Serializer& serializer, bool& v) { u8 byte = v?1:0; serializer.Serialize(byte); } inline void SerializeSize (Serializer& serializer, msize size) { if (size > std::numeric_limits::max()) throw std::runtime_error("length of a container is too big"); u32 size32 = (u32)size; serializer.Serialize(size32); } inline void SerializeSize (Serializer& serializer, msize& size) { u32 size32; serializer.Serialize(size32); size = size32; } inline void SerializeItem (Serializer& serializer, string& str) { msize size; SerializeSize(serializer, size); vector v(size); serializer.SerializeRawData(v.data(), v.size()); str.assign(v.begin(), v.end()); } inline void SerializeItem (Serializer& serializer, const string& str) { SerializeSize(serializer, str.size()); serializer.SerializeRawData(str.data(), str.size()); } template inline void SerializeItem(Serializer& serializer, std::vector& v) { msize ms = v.size(); SerializeSize(serializer, ms); for (msize i{}; i < v.size(); ++i) { serializer.Serialize(v[i]); } } template inline void SerializeItem(Serializer& serializer, std::vector& v) { msize size; SerializeSize(serializer, size); v.clear(); for (msize i{}; i < size; ++i) { T item; SerializeItem(serializer, item); v.push_back(std::move(item)); } } template <> inline void SerializeItem (Serializer& serializer, std::vector& v) { SerializeSize(serializer, v.size()); serializer.SerializeRawData(v.data(), v.size()); } template <> inline void SerializeItem (Serializer& serializer, std::vector& v) { msize size; SerializeSize(serializer, size); v.clear(); v.resize(size); serializer.SerializeRawData(v.data(), v.size()); } template inline void SerializeItem (Serializer& serializer, std::map& v) { msize size; SerializeSize(serializer, size); v.clear(); for (msize i{}; i < size; ++i) { std::pair p; serializer.Serialize(p.first, p.second); v.insert(std::move(p)); } } template inline void SerializeItem (Serializer& serializer, std::map& v) { SerializeSize(serializer, v.size()); for (auto& p : v) { serializer.Serialize(p.first, p.second); } } template inline void SerializeItem (Serializer& serializer, std::set& v) { msize size; SerializeSize(serializer, size); v.clear(); for (msize i{}; i < size; ++i) { T item; SerializeItem(serializer, item); v.insert(std::move(item)); } } template inline void SerializeItem (Serializer& serializer, std::set& v) { SerializeSize(serializer, v.size()); for (auto& i : v) SerializeItem(serializer, i); } template inline vector Serialize(T& data) { vector result; Serializer{result}.SerializeObject(data); return result; } template inline T Deserialize(vector& buffer) { T result; Serializer{buffer}.SerializeObject(result); return result; } } #endif // _VKSSERIALIZER_HPP