#pragma once #include #include #include template struct ring_buffer { std::array data = {}; uint16_t head = 0; uint16_t tail = 0; uint16_t used() const { return tail - head; } uint16_t free() const { return N - used(); } bool empty() const { return head == tail; } void push(std::span src) { if (src.size() > free()) return; for (auto b : src) data[(tail++) % N] = b; } uint16_t peek(std::span dst) const { uint16_t len = dst.size() < used() ? dst.size() : used(); for (uint16_t i = 0; i < len; i++) dst[i] = data[(head + i) % N]; return len; } void consume(uint16_t len) { head += len; if (head >= N) { head -= N; tail -= N; } } std::span read_contiguous() const { uint16_t offset = head % N; uint16_t contig = N - offset; uint16_t pending = used(); uint16_t len = pending < contig ? pending : contig; return {data.data() + offset, len}; } };