#pragma once #include "binary-reader.hpp" #include "compat/assert.hpp" namespace floormat::Serialize { template template constexpr binary_reader::binary_reader(const Seq& seq) noexcept : it{std::begin(seq)}, end{std::end(seq)} {} template constexpr binary_reader::binary_reader(It begin, It end) noexcept : it{begin}, end{end} {} template template constexpr value_u binary_reader::read_u() noexcept { value_u buf; static_assert(sizeof(T) <= sizeof(buf)); fm_assert(std::distance(it, end) >= sizeof(T)); num_bytes_read += sizeof(T); for (int i = 0; i < sizeof(T); i++) buf.bytes[i] = *it++; return buf; } template template T binary_reader::read() noexcept { value_u buf = read_u(); return *reinterpret_cast(buf.bytes); } template template constexpr std::array binary_reader::read() noexcept { std::array array; if (std::is_constant_evaluated()) array = {}; fm_assert(N <= (std::size_t)std::distance(it, end)); num_bytes_read += N; for (std::size_t i = 0; i < N; i++) array[i] = *it++; return array; } template constexpr void binary_reader::assert_end() noexcept { fm_assert(it == end); } template template constexpr value_u binary_reader::read_u() noexcept { value_u buf; if (std::is_constant_evaluated()) for (std::size_t i = 0; i < std::size(buf.bytes); i++) buf.bytes[i] = 0; static_assert(sizeof(T) <= sizeof(buf)); fm_assert((std::ptrdiff_t)sizeof(T) <= std::distance(it, end)); num_bytes_read += sizeof(T); if constexpr(std::endian::native == std::endian::big) for (int i = sizeof(T) - 1; i >= 0; i--) buf.bytes[i] = *it++; else for (std::size_t i = 0; i < sizeof(T); i++) buf.bytes[i] = *it++; return buf; } template binary_reader& operator>>(binary_reader& reader, T& x) noexcept { value_u u = reader.template read(); x = *reinterpret_cast(&u.bytes[0]); return reader; } } // namespace floormat::Serialize