#pragma once namespace sp { /** * \brief Append a pointer to the buffer * \param data The data to append */ template >> DataBuffer& operator<<(DataBuffer& buffer, const std::shared_ptr& data) { return buffer << *data; } /** * \brief Append a pointer to the buffer * \param data The data to append */ template >> DataBuffer& operator<<(DataBuffer& buffer, const std::unique_ptr& data) { return buffer << *data; } /** * \brief Append a vector to the buffer by first writing the size * \param data The vector to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::vector& data) { buffer << VarInt{data.size()}; for (const auto& element : data) { buffer << element; } return buffer; } /** * \brief Append a list to the buffer by first writing the size * \param data The list to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::list& data) { buffer << VarInt{data.size()}; for (const auto& element : data) { buffer << element; } return buffer; } /** * \brief Append a map to the buffer by first writing the size * \param data The map to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::map& data) { buffer << VarInt{data.size()}; for (const auto& [key, value] : data) { buffer << key << value; } return buffer; } /** * \brief Append a map to the buffer by first writing the size * \param data The map to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::unordered_map& data) { buffer << VarInt{data.size()}; for (const auto& [key, value] : data) { buffer << key << value; } return buffer; } /** * \brief Append a pair to the buffer * \param data The pair to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::pair& data) { return buffer << data.first << data.second; } /** * \brief Append an array to the buffer by first writing the size * \param data The buffer to append */ template DataBuffer& operator<<(DataBuffer& buffer, const std::array& data) { for (const auto& element : data) { buffer << element; } return buffer; } /** * \brief Read a pointer */ template >> DataBuffer& operator>>(DataBuffer& buffer, std::shared_ptr& data) { data = std::make_shared(); return buffer >> *data; } /** * \brief Read a pointer */ template >> DataBuffer& operator>>(DataBuffer& buffer, std::unique_ptr& data) { data = std::make_unique(); return buffer >> *data; } /** * \brief Read a vector (size + data) from the buffer * \pre The vector is assumed to be empty */ template DataBuffer& operator>>(DataBuffer& buffer, std::vector& data) { VarInt arraySize; buffer >> arraySize; for (std::size_t i = 0; i < arraySize.GetValue(); i++) { T newElement; buffer >> newElement; data.push_back(newElement); } return buffer; } /** * \brief Read a list (size + data) from the buffer * \pre The list is assumed to be empty */ template DataBuffer& operator>>(DataBuffer& buffer, std::list& data) { VarInt arraySize; buffer >> arraySize; for (std::size_t i = 0; i < arraySize.GetValue(); i++) { T newElement; buffer >> newElement; data.push_back(newElement); } return buffer; } /** * \brief Read a map (size + data) from the buffer * \pre The map is assumed to be empty */ template DataBuffer& operator>>(DataBuffer& buffer, std::map& data) { VarInt mapSize; buffer >> mapSize; for (std::size_t i = 0; i < mapSize.GetValue(); i++) { K newKey; V newValue; buffer >> newKey >> newValue; data.emplace(newKey, newValue); } return buffer; } /** * \brief Read a map (size + data) from the buffer * \pre The map is assumed to be empty */ template DataBuffer& operator>>(DataBuffer& buffer, std::unordered_map& data) { VarInt mapSize; buffer >> mapSize; for (std::size_t i = 0; i < mapSize.GetValue(); i++) { K newKey; V newValue; buffer >> newKey >> newValue; data.emplace(newKey, newValue); } return buffer; } /** * \brief Read a pair */ template DataBuffer& operator>>(DataBuffer& buffer, std::pair& data) { return buffer >> data.first >> data.second; } /** * \brief Read an array from the buffer */ template DataBuffer& operator>>(DataBuffer& buffer, std::array& data) { for (std::size_t i = 0; i < Size; i++) { T newElement; buffer >> newElement; data[i] = newElement; } return buffer; } } // namespace sp