#pragma once #include "cplt_fwd.hpp" #include #include #include #include #include class BaseDataStream { private: std::endian mEndian = std::endian::big; public: std::endian GetEndianness() const; void SetEndianness(std::endian endianness); }; class InputDataStream : public BaseDataStream { private: std::fstream mBackend; public: static constexpr bool IsSerializer() { return false; } InputDataStream(std::fstream stream); 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 Read(int8_t& n); void Read(int16_t& n); void Read(int32_t& n); void Read(int64_t& n); void Read(uint8_t& n); void Read(uint16_t& n); void Read(uint32_t& n); void Read(uint64_t& n); void Read(float& n); void Read(double& n); template void ReadObject(TObject& obj) { if constexpr (requires(TObject t) { t.ReadFromDataStream(std::declval()); }) { obj.ReadFromDataStream(*this); } else if constexpr (requires(TObject t) { t.OperateIOProxy(std::declval()); }) { obj.OperateIOProxy(*this); } else { static_assert(false && sizeof(TObject), "This type does not have integration with InputDataStream."); } } template void ReadObjectAdapted(TObject& obj, TAdapter&& adapter) { adapter.ReadFromDataStream(*this, obj); } public: // Proxy functions for OperateIOProxy template void Bytes(size_t byteCount, T* buffer) const { ReadBytes(byteCount, buffer); } template void Value(T& t) const { Read(t); } template void Object(T& obj) const { ReadObject(obj); } template void ObjectAdapted(TObject& obj, TAdapter&& adapter) const { ReadObjectAdapted(obj, adapter); } }; class OutputDataStream : public BaseDataStream { private: std::fstream mBackend; public: static constexpr bool IsSerializer() { return true; } OutputDataStream(std::fstream stream); 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 Write(uint8_t n); void Write(uint16_t n); void Write(uint32_t n); void Write(uint64_t n); void Write(float n); void Write(double n); template void WriteObject(TObject& obj) { if constexpr (requires(TObject t) { t.WriteToDataStream(std::declval()); }) { obj.WriteToDataStream(*this); } else if constexpr (requires(TObject t) { t.OperateIOProxy(std::declval()); }) { obj.OperateIOProxy(*this); } else { static_assert(false && sizeof(TObject), "This type does not have integration with OutputDataStream."); } } template void WriteObjectAdapted(TObject& obj, TAdapter&& adapter) { adapter.WriteToDataStream(*this, obj); } public: // Proxy functions for OperateIOProxy template void Bytes(size_t byteCount, T* buffer) const { WriteBytes(byteCount, buffer); } template void Value(T t) const { Write(t); } template void Object(T& obj) const { WriteObject(obj); } template void ObjectAdapted(TObject& obj, TAdapter&& adapter) const { WriteObjectAdapted(obj, adapter); } };