#pragma once #include #include #include #include namespace rsx { template concept SpanLike = requires(T t) { { t.data() } -> std::convertible_to; { t.size_bytes() } -> std::convertible_to; }; template concept Integral = std::is_integral_v || std::is_same_v; class io_buffer { void* m_ptr = nullptr; usz m_size = 0; std::function ()> m_allocator = nullptr; public: io_buffer() = default; template io_buffer(T& container) { m_ptr = reinterpret_cast(container.data()); m_size = container.size_bytes(); } io_buffer(std::function ()> allocator) { ensure(allocator); m_allocator = allocator; } template T* data() { if (!m_ptr && m_allocator) { std::tie(m_ptr, m_size) = m_allocator(); } return static_cast(m_ptr); } usz size() const { return m_size; } template std::span as_span() { const auto bytes = data(); return { bytes, m_size / sizeof(T) }; } }; }