#pragma once #include #include #include static inline void add_buffer_bytes(std::vector& storage, void const* data, size_t size) { storage.insert(storage.end(), reinterpret_cast(data), reinterpret_cast(data) + size); } static inline void add_buffer_bytes(std::vector& storage, std::span data) { storage.insert(storage.end(), data.begin(), data.end()); } struct buffer_writer { buffer_writer(std::span fullData) : remaining(fullData) { } std::span remaining; void add(std::span content) { THROW_HR_IF(E_INVALIDARG, content.size() > remaining.size()); memcpy(remaining.data(), content.data(), content.size()); remaining = remaining.subspan(content.size()); } template T* reserve_space() { THROW_HR_IF(E_INVALIDARG, sizeof(T) > remaining.size()); auto result = reinterpret_cast(remaining.data()); remaining = remaining.subspan(sizeof(T)); return result; } }; struct buffer_reader { std::span data; size_t remaining() const { return data.size(); } std::span read(size_t size) { THROW_HR_IF(E_INVALIDARG, size > data.size()); auto result = data.first(size); data = data.subspan(size); return result; } std::span read_remaining() { return std::exchange(data, {}); } template T const* read() { return reinterpret_cast(read(sizeof(T)).data()); } };