#include "foundation/binary_stream.h" namespace pp::foundation { ByteReader::ByteReader(std::span bytes) noexcept : bytes_(bytes) { } std::size_t ByteReader::position() const noexcept { return position_; } std::size_t ByteReader::size() const noexcept { return bytes_.size(); } std::size_t ByteReader::remaining() const noexcept { return bytes_.size() - position_; } bool ByteReader::empty() const noexcept { return remaining() == 0; } Status ByteReader::seek(std::size_t position) noexcept { if (position > bytes_.size()) { return Status::out_of_range("seek position is outside the stream"); } position_ = position; return Status::success(); } Result ByteReader::read_u8() noexcept { const auto bytes = read_bytes(1); if (!bytes) { return Result::failure(bytes.status()); } return Result::success(static_cast(bytes.value()[0])); } Result ByteReader::read_u16_le() noexcept { const auto bytes = read_bytes(2); if (!bytes) { return Result::failure(bytes.status()); } const auto b0 = static_cast(bytes.value()[0]); const auto b1 = static_cast(bytes.value()[1]); return Result::success(static_cast(b0 | (b1 << 8U))); } Result ByteReader::read_u32_le() noexcept { const auto bytes = read_bytes(4); if (!bytes) { return Result::failure(bytes.status()); } const auto b0 = static_cast(bytes.value()[0]); const auto b1 = static_cast(bytes.value()[1]); const auto b2 = static_cast(bytes.value()[2]); const auto b3 = static_cast(bytes.value()[3]); return Result::success(b0 | (b1 << 8U) | (b2 << 16U) | (b3 << 24U)); } Result> ByteReader::read_bytes(std::size_t count) noexcept { if (count > remaining()) { return Result>::failure( Status::out_of_range("read would move beyond the end of the stream")); } const auto start = position_; position_ += count; return Result>::success(bytes_.subspan(start, count)); } ByteWriter::ByteWriter(std::vector& bytes) noexcept : bytes_(&bytes) { } std::size_t ByteWriter::size() const noexcept { return bytes_ == nullptr ? 0 : bytes_->size(); } Status ByteWriter::write_u8(std::uint8_t value) { if (bytes_ == nullptr) { return Status::invalid_argument("writer has no backing storage"); } bytes_->push_back(static_cast(value)); return Status::success(); } Status ByteWriter::write_u16_le(std::uint16_t value) { if (bytes_ == nullptr) { return Status::invalid_argument("writer has no backing storage"); } bytes_->push_back(static_cast(value & 0xffU)); bytes_->push_back(static_cast((value >> 8U) & 0xffU)); return Status::success(); } Status ByteWriter::write_u32_le(std::uint32_t value) { if (bytes_ == nullptr) { return Status::invalid_argument("writer has no backing storage"); } bytes_->push_back(static_cast(value & 0xffU)); bytes_->push_back(static_cast((value >> 8U) & 0xffU)); bytes_->push_back(static_cast((value >> 16U) & 0xffU)); bytes_->push_back(static_cast((value >> 24U) & 0xffU)); return Status::success(); } Status ByteWriter::write_bytes(std::span bytes) { if (bytes_ == nullptr) { return Status::invalid_argument("writer has no backing storage"); } bytes_->insert(bytes_->end(), bytes.begin(), bytes.end()); return Status::success(); } }