diff --git a/include/sp/common/DataBufferOperators.h b/include/sp/common/DataBufferOperators.h index e47d3a1..ef4f7a0 100644 --- a/include/sp/common/DataBufferOperators.h +++ b/include/sp/common/DataBufferOperators.h @@ -1,16 +1,84 @@ #pragma once -#include #include +#include namespace sp { -template +template using is_default_serializable = std::bool_constant<(std::is_class_v && std::is_aggregate_v) || !std::is_class_v>; -template +template static constexpr bool is_default_serializable_v = is_default_serializable::value; +namespace details { + +template +void WriteRaw(DataBuffer& a_Buffer, T a_Data); + +template +void WriteFields(DataBuffer& a_Buffer, const T& a_Data); + +template +void WriteSharedPtr(DataBuffer& a_Buffer, const std::shared_ptr& a_Data); + +template +void WriteUniquePtr(DataBuffer& a_Buffer, const std::unique_ptr& a_Data); + +template +void WriteVector(DataBuffer& a_Buffer, const std::vector& a_Data); + +template +void WriteList(DataBuffer& a_Buffer, const std::list& a_Data); + +template +void WriteMap(DataBuffer& a_Buffer, const std::map& a_Data); + +template +void WriteUnorderedMap(DataBuffer& a_Buffer, const std::unordered_map& a_Data); + +template +void WritePair(DataBuffer& a_Buffer, const std::pair& a_Data); + +template +void WriteArray(DataBuffer& a_Buffer, const std::array& a_Data); + + + +template +void ReadRaw(DataBuffer& a_Buffer, T& a_Data); + +template +void ReadFields(DataBuffer& a_Buffer, T& a_Data); + +template +void ReadSharedPtr(DataBuffer& a_Buffer, std::shared_ptr& a_Data); + +template +void ReadUniquePtr(DataBuffer& a_Buffer, std::unique_ptr& a_Data); + +template +void ReadVector(DataBuffer& a_Buffer, std::vector& a_Data); + +template +void ReadList(DataBuffer& a_Buffer, std::list& a_Data); + +template +void ReadMap(DataBuffer& a_Buffer, std::map& a_Data); + +template +void ReadUnorderedMap(DataBuffer& a_Buffer, std::unordered_map& a_Data); + +template +void ReadPair(DataBuffer& a_Buffer, std::pair& a_Data); + +template +void ReadArray(DataBuffer& a_Buffer, std::array& a_Data); + +} // namespace details + + + /** * \brief Append data to the buffer (converted to big endian) @@ -18,10 +86,9 @@ static constexpr bool is_default_serializable_v = is_default_serializable::va template >> DataBuffer& operator<<(DataBuffer& a_Buffer, const T& a_Data) { if constexpr (std::is_class_v) { - boost::pfr::for_each_field(a_Data, [&a_Buffer](const auto& a_Field) { a_Buffer << a_Field; }); + details::WriteFields(a_Buffer, a_Data); } else { - a_Buffer.Append(a_Data); - SwapBytes(a_Buffer.data() + a_Buffer.GetReadOffset() - sizeof(T), a_Buffer.data() + a_Buffer.GetReadOffset()); + details::WriteRaw(a_Buffer, a_Data); } return a_Buffer; } @@ -43,8 +110,9 @@ std::ostream& operator<<(std::ostream& os, const DataBuffer& buffer); * \param data The data to append */ template >> -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::shared_ptr& data) { - return a_Buffer << *data; +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::shared_ptr& a_Data) { + details::WriteSharedPtr(a_Buffer, a_Data); + return a_Buffer; } /** @@ -52,8 +120,9 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::shared_ptr& data) { * \param data The data to append */ template >> -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unique_ptr& data) { - return a_Buffer << *data; +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unique_ptr& a_Data) { + details::WriteUniquePtr(a_Buffer, a_Data); + return a_Buffer; } /** @@ -61,11 +130,8 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unique_ptr& data) { * \param data The vector to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::vector& data) { - a_Buffer << VarInt{data.size()}; - for (const auto& element : data) { - a_Buffer << element; - } +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::vector& a_Data) { + details::WriteVector(a_Buffer, a_Data); return a_Buffer; } @@ -74,11 +140,8 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::vector& data) { * \param data The list to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::list& data) { - a_Buffer << VarInt{data.size()}; - for (const auto& element : data) { - a_Buffer << element; - } +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::list& a_Data) { + details::WriteList(a_Buffer, a_Data); return a_Buffer; } @@ -87,11 +150,8 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::list& data) { * \param data The map to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::map& data) { - a_Buffer << VarInt{data.size()}; - for (const auto& [key, value] : data) { - a_Buffer << key << value; - } +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::map& a_Data) { + details::WriteMap(a_Buffer, a_Data); return a_Buffer; } @@ -100,11 +160,8 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::map& data) { * \param data The map to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unordered_map& data) { - a_Buffer << VarInt{data.size()}; - for (const auto& [key, value] : data) { - a_Buffer << key << value; - } +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unordered_map& a_Data) { + details::WriteUnorderedMap(a_Buffer, a_Data); return a_Buffer; } @@ -113,8 +170,9 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::unordered_map& dat * \param data The pair to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::pair& data) { - return a_Buffer << data.first << data.second; +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::pair& a_Data) { + details::WritePair(a_Buffer, a_Data); + return a_Buffer; } /** @@ -122,10 +180,8 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::pair& data) { * \param data The buffer to append */ template -DataBuffer& operator<<(DataBuffer& a_Buffer, const std::array& data) { - for (const auto& element : data) { - a_Buffer << element; - } +DataBuffer& operator<<(DataBuffer& a_Buffer, const std::array& a_Data) { + details::WriteArray(a_Buffer, a_Data); return a_Buffer; } @@ -139,10 +195,9 @@ DataBuffer& operator<<(DataBuffer& a_Buffer, const std::array& data) { template >> DataBuffer& operator>>(DataBuffer& a_Buffer, T& a_Data) { if constexpr (std::is_class_v) { - boost::pfr::for_each_field(a_Data, [&a_Buffer](auto& a_Field) { a_Buffer >> a_Field; }); + details::ReadFields(a_Buffer, a_Data); } else { - a_Buffer.Read(a_Data); - SwapBytes(a_Data); + details::ReadRaw(a_Buffer, a_Data); } return a_Buffer; } @@ -151,7 +206,7 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, T& a_Data) { * \brief Read some data from the buffer and assign to the new buffer * \param data The buffer to assign */ -DataBuffer& operator>>(DataBuffer& a_Buffer, DataBuffer& data); +DataBuffer& operator>>(DataBuffer& a_Buffer, DataBuffer& a_Data); /** * \brief Read a string from the buffer @@ -164,18 +219,18 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::string& str); * \brief Read a pointer */ template >> -DataBuffer& operator>>(DataBuffer& a_Buffer, std::shared_ptr& data) { - data = std::make_shared(); - return a_Buffer >> *data; +DataBuffer& operator>>(DataBuffer& a_Buffer, std::shared_ptr& a_Data) { + details::ReadSharedPtr(a_Buffer, a_Data); + return a_Buffer; } /** * \brief Read a pointer */ template >> -DataBuffer& operator>>(DataBuffer& a_Buffer, std::unique_ptr& data) { - data = std::make_unique(); - return a_Buffer >> *data; +DataBuffer& operator>>(DataBuffer& a_Buffer, std::unique_ptr& a_Data) { + details::ReadUniquePtr(a_Buffer, a_Data); + return a_Buffer; } /** @@ -183,14 +238,8 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::unique_ptr& data) { * \pre The vector is assumed to be empty */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::vector& data) { - VarInt arraySize; - a_Buffer >> arraySize; - for (std::size_t i = 0; i < arraySize.GetValue(); i++) { - T newElement; - a_Buffer >> newElement; - data.push_back(newElement); - } +DataBuffer& operator>>(DataBuffer& a_Buffer, std::vector& a_Data) { + details::ReadVector(a_Buffer, a_Data); return a_Buffer; } @@ -199,14 +248,8 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::vector& data) { * \pre The list is assumed to be empty */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::list& data) { - VarInt arraySize; - a_Buffer >> arraySize; - for (std::size_t i = 0; i < arraySize.GetValue(); i++) { - T newElement; - a_Buffer >> newElement; - data.push_back(newElement); - } +DataBuffer& operator>>(DataBuffer& a_Buffer, std::list& a_Data) { + details::ReadList(a_Buffer, a_Data); return a_Buffer; } @@ -215,15 +258,8 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::list& data) { * \pre The map is assumed to be empty */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::map& data) { - VarInt mapSize; - a_Buffer >> mapSize; - for (std::size_t i = 0; i < mapSize.GetValue(); i++) { - K newKey; - V newValue; - a_Buffer >> newKey >> newValue; - data.emplace(newKey, newValue); - } +DataBuffer& operator>>(DataBuffer& a_Buffer, std::map& a_Data) { + details::ReadMap(a_Buffer, a_Data); return a_Buffer; } @@ -232,15 +268,8 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::map& data) { * \pre The map is assumed to be empty */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::unordered_map& data) { - VarInt mapSize; - a_Buffer >> mapSize; - for (std::size_t i = 0; i < mapSize.GetValue(); i++) { - K newKey; - V newValue; - a_Buffer >> newKey >> newValue; - data.emplace(newKey, newValue); - } +DataBuffer& operator>>(DataBuffer& a_Buffer, std::unordered_map& a_Data) { + details::ReadUnorderedMap(a_Buffer, a_Data); return a_Buffer; } @@ -248,21 +277,179 @@ DataBuffer& operator>>(DataBuffer& a_Buffer, std::unordered_map& data) { * \brief Read a pair */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::pair& data) { - return a_Buffer >> data.first >> data.second; +DataBuffer& operator>>(DataBuffer& a_Buffer, std::pair& a_Data) { + details::ReadPair(a_Buffer, a_Data); + return a_Buffer; } /** * \brief Read an array from the buffer */ template -DataBuffer& operator>>(DataBuffer& a_Buffer, std::array& data) { - for (std::size_t i = 0; i < Size; i++) { - T newElement; - a_Buffer >> newElement; - data[i] = newElement; - } +DataBuffer& operator>>(DataBuffer& a_Buffer, std::array& a_Data) { + details::ReadArray(a_Buffer, a_Data); return a_Buffer; } + + + + +namespace details { + +template +void WriteRaw(DataBuffer& a_Buffer, T a_Data) { + a_Buffer.Append(a_Data); + SwapBytes(a_Buffer.data() + a_Buffer.GetReadOffset() - sizeof(T), a_Buffer.data() + a_Buffer.GetReadOffset()); +} + +template +void WriteFields(DataBuffer& a_Buffer, const T& a_Data) { + boost::pfr::for_each_field(a_Data, [&a_Buffer](const auto& a_Field) { a_Buffer << a_Field; }); +} + +template +void WriteSharedPtr(DataBuffer& a_Buffer, const std::shared_ptr& a_Data) { + a_Buffer << *a_Data; +} + +template +void WriteUniquePtr(DataBuffer& a_Buffer, const std::unique_ptr& a_Data) { + a_Buffer << *a_Data; +} + +template +void WriteVector(DataBuffer& a_Buffer, const std::vector& a_Data) { + a_Buffer << VarInt{a_Data.size()}; + for (const auto& element : a_Data) { + a_Buffer << element; + } +} + +template +void WriteList(DataBuffer& a_Buffer, const std::list& a_Data) { + a_Buffer << VarInt{a_Data.size()}; + for (const auto& element : a_Data) { + a_Buffer << element; + } +} + +template +void WriteMap(DataBuffer& a_Buffer, const std::map& a_Data) { + a_Buffer << VarInt{a_Data.size()}; + for (const auto& [key, value] : a_Data) { + a_Buffer << key << value; + } +} + +template +void WriteUnorderedMap(DataBuffer& a_Buffer, const std::unordered_map& a_Data) { + a_Buffer << VarInt{a_Data.size()}; + for (const auto& [key, value] : a_Data) { + a_Buffer << key << value; + } +} + +template +void WritePair(DataBuffer& a_Buffer, const std::pair& a_Data) { + a_Buffer << a_Data.first << a_Data.second; +} + +template +void WriteArray(DataBuffer& a_Buffer, const std::array& a_Data) { + for (const auto& element : a_Data) { + a_Buffer << element; + } +} + + + + + +template +void ReadRaw(DataBuffer& a_Buffer, T& a_Data) { + a_Buffer.Read(a_Data); + SwapBytes(a_Data); +} + +template +void ReadFields(DataBuffer& a_Buffer, T& a_Data) { + boost::pfr::for_each_field(a_Data, [&a_Buffer](auto& a_Field) { a_Buffer >> a_Field; }); +} + +template +void ReadSharedPtr(DataBuffer& a_Buffer, std::shared_ptr& a_Data) { + a_Data = std::make_shared(); + a_Buffer >> *a_Data; +} + +template +void ReadUniquePtr(DataBuffer& a_Buffer, std::unique_ptr& a_Data) { + a_Data = std::make_unique(); + a_Buffer >> *a_Data; +} + +template +void ReadVector(DataBuffer& a_Buffer, std::vector& a_Data) { + VarInt arraySize; + a_Buffer >> arraySize; + for (std::size_t i = 0; i < arraySize.GetValue(); i++) { + T newElement; + a_Buffer >> newElement; + a_Data.push_back(newElement); + } +} + +template +void ReadList(DataBuffer& a_Buffer, std::list& a_Data) { + VarInt arraySize; + a_Buffer >> arraySize; + for (std::size_t i = 0; i < arraySize.GetValue(); i++) { + T newElement; + a_Buffer >> newElement; + a_Data.push_back(newElement); + } +} + +template +void ReadMap(DataBuffer& a_Buffer, std::map& a_Data) { + VarInt mapSize; + a_Buffer >> mapSize; + for (std::size_t i = 0; i < mapSize.GetValue(); i++) { + K newKey; + V newValue; + a_Buffer >> newKey >> newValue; + a_Data.emplace(newKey, newValue); + } +} + +template +void ReadUnorderedMap(DataBuffer& a_Buffer, std::unordered_map& a_Data) { + VarInt mapSize; + a_Buffer >> mapSize; + for (std::size_t i = 0; i < mapSize.GetValue(); i++) { + K newKey; + V newValue; + a_Buffer >> newKey >> newValue; + a_Data.emplace(newKey, newValue); + } +} + +template +void ReadPair(DataBuffer& a_Buffer, std::pair& a_Data) { + a_Buffer >> a_Data.first >> a_Data.a_Data; +} + +template +void ReadArray(DataBuffer& a_Buffer, std::array& a_Data) { + for (std::size_t i = 0; i < S; i++) { + T newElement; + a_Buffer >> newElement; + a_Data[i] = newElement; + } +} + + +} // namespace details + } // namespace sp \ No newline at end of file