#include "io_test_helper.hh" #include "io.hh" #include #include #include #include #include namespace { class BreakingReader : public io::Reader { public: BreakingReader(std::unique_ptr reader, size_t offset, io::ReadError error) : reader_(std::move(reader)), offset_(offset), error_(error) {} [[nodiscard]] std::expected read(void* dst, size_t max) override { if (offset_ == 0) return std::unexpected(error_); size_t avail = std::min(offset_, max); auto ret = reader_->read(dst, avail); if (ret.has_value()) { offset_ -= ret.value(); } return ret; } [[nodiscard]] std::expected skip(size_t max) override { if (offset_ == 0) return std::unexpected(error_); size_t avail = std::min(offset_, max); auto ret = reader_->skip(avail); if (ret.has_value()) { offset_ -= ret.value(); } return ret; } private: std::unique_ptr reader_; size_t offset_; io::ReadError const error_; }; class MaxBlockReader : public io::Reader { public: MaxBlockReader(std::unique_ptr reader, size_t max_block_size) : reader_(std::move(reader)), max_block_size_(max_block_size) {} [[nodiscard]] std::expected read(void* dst, size_t max) override { size_t avail = std::min(max_block_size_, max); return reader_->read(dst, avail); } [[nodiscard]] std::expected skip(size_t max) override { size_t avail = std::min(max_block_size_, max); return reader_->skip(avail); } private: std::unique_ptr reader_; size_t const max_block_size_; }; } // namespace std::unique_ptr io_make_breaking(std::unique_ptr reader, size_t offset, io::ReadError error) { return std::make_unique(std::move(reader), offset, error); } std::unique_ptr io_make_max_block( std::unique_ptr reader, size_t max_block_size) { return std::make_unique(std::move(reader), max_block_size); }