Crunch
A Message Definition Language for Getting Things Right
Loading...
Searching...
No Matches
crunch_varint.hpp
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <optional>
6#include <span>
7#include <utility>
8
9namespace Crunch::serdes {
10
16struct Varint {
25 static constexpr std::size_t encode(uint64_t value,
26 std::span<std::byte> output,
27 std::size_t offset) noexcept {
28 std::size_t start_offset = offset;
29 while (value >= 0x80) {
30 output[offset++] = static_cast<std::byte>((value & 0x7F) | 0x80);
31 value >>= 7;
32 }
33 output[offset++] = static_cast<std::byte>(value);
34 return offset - start_offset;
35 }
36
45 static constexpr std::optional<std::pair<uint64_t, std::size_t>> decode(
46 std::span<const std::byte> input, std::size_t offset) noexcept {
47 uint64_t value = 0;
48 std::size_t shift = 0;
49 std::size_t bytes_read = 0;
50
51 while (offset + bytes_read < input.size()) {
52 uint8_t byte = static_cast<uint8_t>(input[offset + bytes_read]);
53 bytes_read++;
54
55 if (shift >= 64) {
56 // Overflow (more than 10 bytes or too many bits for 64-bit int)
57 return std::nullopt;
58 }
59
60 value |= static_cast<uint64_t>(byte & 0x7F) << shift;
61 shift += 7;
62
63 if ((byte & 0x80) == 0) {
64 return std::make_pair(value, bytes_read);
65 }
66 }
67 // Buffer ended before Varint terminated
68 return std::nullopt;
69 }
70
77 static constexpr std::size_t size(uint64_t value) noexcept {
78 if (value == 0) {
79 return 1;
80 }
81 std::size_t bytes = 0;
82 while (value > 0) {
83 bytes++;
84 value >>= 7;
85 }
86 return bytes;
87 }
88
93 // cppcheck-suppress unusedStructMember
94 static constexpr std::size_t max_size = 10;
95
101 static consteval std::size_t max_varint_size(std::size_t value_bits) {
102 return (value_bits + 6) / 7;
103 }
104};
105
106} // namespace Crunch::serdes
Utility for Varint encoding/decoding.
Definition: crunch_varint.hpp:16
static constexpr std::optional< std::pair< uint64_t, std::size_t > > decode(std::span< const std::byte > input, std::size_t offset) noexcept
Decodes a Varint from a buffer.
Definition: crunch_varint.hpp:45
static constexpr std::size_t size(uint64_t value) noexcept
Calculates the size requirement for a value encoded as Varint.
Definition: crunch_varint.hpp:77
static consteval std::size_t max_varint_size(std::size_t value_bits)
Calculates the maximum varint size for a given number of bits.
Definition: crunch_varint.hpp:101
static constexpr std::size_t max_size
The maximum size required for a 64-bit integer encoded as Varint. ceil(64 / 7) = 10.
Definition: crunch_varint.hpp:94
static constexpr std::size_t encode(uint64_t value, std::span< std::byte > output, std::size_t offset) noexcept
Encodes a value as a Varint.
Definition: crunch_varint.hpp:25