#pragma once #include "Utils/UUID.hpp" #include "cplt_fwd.hpp" #include #include #include #include #include #include namespace DataStreamIntegrations { template void ReadFromDataStream(DataStream& s, std::vector& vec); template void WriteToDataStream(DataStream& s, const std::vector& vec); void ReadFromDataStream(DataStream& s, std::string& str); void WriteToDataStream(DataStream& s, const std::string& str); void WriteToDataStream(DataStream& s, const std::string_view& str); void ReadFromDataStream(DataStream& s, uuids::uuid& uuid); void WriteToDataStream(DataStream& s, const uuids::uuid& uuid); template void OperateIOAdapter(T&, int); } // namespace DataStreamIntegrations class SerializationAdapter { public: static constexpr bool IsSerializer() { return true; } public: DataStream* Stream; template void Bytes(size_t byteCount, T* buffer) const { Stream->WriteBytes(byteCount, buffer); } template void Value(T t) const { Stream->Write(t); } template void Object(T& obj) const { Stream->WriteObject(obj); } }; class DeserializationAdapter { public: static constexpr bool IsSerializer() { return false; } public: DataStream* Stream; template void Bytes(size_t byteCount, T* buffer) const { Stream->WriteBytes(byteCount, buffer); } template void Value(T& t) const { Stream->Read(t); } template void Object(T& obj) const { Stream->ReadObject(obj); } }; namespace DataStreamTraits { template concept HasMember = requires(T t) { t.ReadFromDataStream(std::declval()); }; template concept HasIOAdapterMember = requires(T t) { t.OperateIOAdapter(std::declval()); t.OperateIOAdapter(std::declval()); }; template concept HasExtension = requires(T t) { DataStreamIntegrations::ReadFromDataStream(std::declval(), t); }; template concept HasIOAdapterExtension = requires(T t) { DataStreamIntegrations::OperateIOAdapter(std::declval(), t); DataStreamIntegrations::OperateIOAdapter(std::declval(), t); }; } // namespace DataStreamTraits class DataStream { public: enum Endianness { BigEndian, LittleEndian, }; private: Endianness mEndian; public: DataStream(); ~DataStream(); Endianness GetEndianness() const; void SetEndianness(Endianness endianness); void ReadBytes(size_t byteCount, std::byte* buffer); void ReadBytes(size_t byteCount, char* buffer); void ReadBytes(size_t byteCount, signed char* buffer); void ReadBytes(size_t byteCount, unsigned char* buffer); template void ReadBytes(size_t byteCount, TInserter&& inserter) { for (size_t i = 0; i < byteCount; ++i) { uint8_t byte; Read(byte); inserter = byte; } } void WriteBytes(size_t byteCount, const std::byte* buffer); void WriteBytes(size_t byteCount, const char* buffer); void WriteBytes(size_t byteCount, const signed char* buffer); void WriteBytes(size_t byteCount, const unsigned char* buffer); template void WriteBytes(TIterator&& begin, TIterator&& end) { for (; begin != end; ++begin) { uint8_t byte = *begin; Write(byte); } } void Write(int8_t n); void Write(int16_t n); void Write(int32_t n); void Write(int64_t n); void Read(int8_t& n); void Read(int16_t& n); void Read(int32_t& n); void Read(int64_t& n); void Write(uint8_t n); void Write(uint16_t n); void Write(uint32_t n); void Write(uint64_t n); void Read(uint8_t& n); void Read(uint16_t& n); void Read(uint32_t& n); void Read(uint64_t& n); void Write(float n); void Write(double n); void Read(float& n); void Read(double& n); template void ReadObject(TObject& obj) { using namespace DataStreamTraits; if constexpr (HasMember) { obj.ReadFromDataStream(*this); } else if constexpr (HasIOAdapterMember) { DeserializationAdapter adapter{ this }; obj.OperateIOAdapter(adapter); } else if constexpr (HasExtension) { DataStreamIntegrations::ReadFromDataStream(*this, obj); } else if constexpr (HasIOAdapterExtension) { DeserializationAdapter adapter{ this }; DataStreamIntegrations::OperateIOAdapter(adapter, obj); } else { static_assert(false && sizeof(TObject), "This type does not have integration with DataStream."); } } template void WriteObject(TObject& obj) { using namespace DataStreamTraits; if constexpr (HasMember) { obj.WriteToDataStream(*this); } else if constexpr (HasIOAdapterMember) { SerializationAdapter adapter{ this }; obj.OperateIOAdapter(adapter); } else if constexpr (HasExtension) { DataStreamIntegrations::WriteToDataStream(*this, obj); } else if constexpr (HasIOAdapterExtension) { SerializationAdapter adapter{ this }; DataStreamIntegrations::OperateIOAdapter(adapter, obj); } else { static_assert(false && sizeof(TObject), "This type does not have integration with DataStream."); } } };