#include #include #include #include namespace sp { static constexpr int SEGMENT_BITS = (1 << 7) - 1; static constexpr int CONTINUE_BIT = 1 << 7; std::size_t VarInt::GetSerializedLength() const { DataBuffer buffer; buffer << *this; return buffer.GetSize(); } DataBuffer& operator<<(DataBuffer& out, const VarInt& var) { std::uint64_t value = var.m_Value; while (true) { if ((value & ~static_cast(SEGMENT_BITS)) == 0) { out << static_cast(value); return out; } out << static_cast((value & SEGMENT_BITS) | CONTINUE_BIT); value >>= 7; } } DataBuffer& operator>>(DataBuffer& in, VarInt& var) { var.Read([&in](std::uint8_t& data){ in.ReadSome(&data, 1); }); return in; } void VarInt::Read(const ReadFunc& read) { m_Value = 0; unsigned int position = 0; std::uint8_t currentByte; while (true) { read(currentByte); m_Value |= static_cast(currentByte & SEGMENT_BITS) << position; if ((currentByte & CONTINUE_BIT) == 0) break; position += 7; if (position >= 8 * sizeof(m_Value)) throw std::runtime_error("VarInt is too big"); } } } // namespace sp