#pragma once #include #include #include "fs/Error.h" #include "fs/Api.h" namespace fs { class FS_API IStreamSink { public: IStreamSink() = default; virtual ~IStreamSink() = default; IStreamSink(IStreamSink&&) = default; IStreamSink& operator=(IStreamSink&&) = default; //This will return the last generated error AND CLEAR IT AFTERWARDS. virtual tl::optional getLastError() const = 0; //writes size bytes from the buffer to the sink at the current cursor position. //the sink size is increased if the sinks reaches the end virtual size_t write(tl::span data) = 0; //returns the size of the sink. Always >= tell virtual uint64_t getSize() const = 0; // The preferred buffer size for writes. Use this buffer size for optimal performance // If zero, use whatever you want virtual size_t getPreferredBufferSize() const = 0; }; template struct StreamSinkSerializationHelperWrite_Internal; template struct StreamSinkSerializationHelperWrite_Internal { static IStreamSink& write(IStreamSink& s, const T& val) { static_assert(std::is_standard_layout_v && !std::is_pointer_v && !std::is_array_v, "You need a specialized write for T"); s.write({ reinterpret_cast(&val), sizeof(T) }); return s; } static IStreamSink& write(IStreamSink& s, tl::span val) { const uint32_t count = static_cast(val.size()); s.write({ reinterpret_cast(&count), sizeof(count) }); for(const T& v : val) s.write( { reinterpret_cast(&v), sizeof(T) }); return s; } }; // specialization to read enums template struct StreamSinkSerializationHelperWrite_Internal { static IStreamSink& write(IStreamSink& s, const EnumType& val) { // first read into the temporary of the underlying type using underlying_t = std::underlying_type_t; underlying_t underlyingValue = static_cast(val); IStreamSink& ret = StreamSinkSerializationHelperWrite_Internal::write(s, underlyingValue); return ret; } }; template struct SimpleStreamSerializationHelperWrite : StreamSinkSerializationHelperWrite_Internal>> { }; template IStreamSink& operator<<(IStreamSink& s, const T& val) { return SimpleStreamSerializationHelperWrite::write(s, val); } template IStreamSink& operator<<(IStreamSink& s, tl::span val) { return SimpleStreamSerializationHelperWrite::write(s, val); } }