forked from scylladb/scylladb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vint-serialization.hh
65 lines (48 loc) · 2.61 KB
/
vint-serialization.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
* Copyright 2017-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
//
// For reference, see https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v5.spec.
//
// Relevant excerpt:
//
// [unsigned vint] An unsigned variable length integer. A vint is encoded with the most significant byte (MSB) first.
// The most significant byte will contains the information about how many extra bytes need to be read
// as well as the most significant bits of the integer.
// The number of extra bytes to read is encoded as 1 bits on the left side.
// For example, if we need to read 2 more bytes the first byte will start with 110
// (e.g. 256 000 will be encoded on 3 bytes as [110]00011 11101000 00000000)
// If the encoded integer is 8 bytes long the vint will be encoded on 9 bytes and the first
// byte will be: 11111111
//
// [vint] A signed variable length integer. This is encoded using zig-zag encoding and then sent
// like an [unsigned vint]. Zig-zag encoding converts numbers as follows:
// 0 = 0, -1 = 1, 1 = 2, -2 = 3, 2 = 4, -3 = 5, 3 = 6 and so forth.
// The purpose is to send small negative values as small unsigned values, so that we save bytes on the wire.
// To encode a value n use "(n >> 31) ^ (n << 1)" for 32 bit values, and "(n >> 63) ^ (n << 1)"
// for 64 bit values where "^" is the xor operation, "<<" is the left shift operation and ">>" is
// the arithmetic right shift operation (highest-order bit is replicated).
// Decode with "(n >> 1) ^ -(n & 1)".
//
#pragma once
#include "bytes.hh"
#include <cstdint>
using vint_size_type = bytes::size_type;
static constexpr size_t max_vint_length = 9;
struct unsigned_vint final {
using value_type = uint64_t;
static vint_size_type serialized_size(value_type) noexcept;
static vint_size_type serialize(value_type, bytes::iterator out);
static value_type deserialize(bytes_view v);
static vint_size_type serialized_size_from_first_byte(bytes::value_type first_byte);
};
struct signed_vint final {
using value_type = int64_t;
static vint_size_type serialized_size(value_type) noexcept;
static vint_size_type serialize(value_type, bytes::iterator out);
static value_type deserialize(bytes_view v);
static vint_size_type serialized_size_from_first_byte(bytes::value_type first_byte);
};