-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVariantVector.cpp
109 lines (99 loc) · 3.3 KB
/
VariantVector.cpp
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "VariantVector.h"
#include "VarsizedInt.cpp/VarsizedInt.h"
static inline void varsizedIntPack(std::vector<uint8_t>& packed, uint64_t x) {
uint8_t bytes[CVarsizedInt::MaxSize] = {};
int bytesSize = CVarsizedInt::Encode(bytes, x);
packed.insert(packed.end(), bytes, bytes + bytesSize);
}
std::vector<uint8_t> CVariantVector::Pack(const CVariantVector::Type& variantVec) {
std::vector<uint8_t> packed = {};
varsizedIntPack(packed, variantVec.size());
for (const auto& variant : variantVec) {
uint64_t variantIndex = variant.index();
varsizedIntPack(packed, variantIndex);
switch (variantIndex) {
case GetTypeIndex<uint64_t>():
varsizedIntPack(packed, std::get<uint64_t>(variant));
break;
case GetTypeIndex<std::string>(): {
const std::string& value = std::get<std::string>(variant);
varsizedIntPack(packed, value.size());
packed.insert(packed.end(), value.begin(), value.end());
}
break;
case GetTypeIndex<std::vector<uint8_t>>(): {
const std::vector<uint8_t>& value = std::get<std::vector<uint8_t>>(variant);
varsizedIntPack(packed, value.size());
packed.insert(packed.end(), value.begin(), value.end());
}
break;
}
}
return packed;
}
static inline std::optional<uint64_t> varsizedIntUnpack(const std::vector<uint8_t>& data, uint64_t& offset) {
if (data.size() < offset + 1) {
return std::nullopt;
}
uint64_t bytesSize = CVarsizedInt::ParseSize((uint8_t*)&data[offset]);
if (bytesSize < 0 || data.size() < offset + bytesSize) {
return std::nullopt;
}
uint64_t x = CVarsizedInt::Decode((uint8_t*)&data[offset]);
offset += bytesSize;
return x;
}
std::optional<CVariantVector::Type> CVariantVector::Unpack(const std::vector<uint8_t>& data) {
uint64_t offset = 0;
std::optional<uint64_t> variantVecSize = varsizedIntUnpack(data, offset);
if (!variantVecSize.has_value()) {
return std::nullopt;
}
uint64_t variantVecSizeValue = *variantVecSize;
CVariantVector::Type variantVec = {};
for (uint64_t i = 0; i < variantVecSizeValue; ++i) {
std::optional<uint64_t> variantIndex = varsizedIntUnpack(data, offset);
if (!variantIndex.has_value()) {
return std::nullopt;
}
switch (*variantIndex) {
case GetTypeIndex<uint64_t>(): {
std::optional<uint64_t> value = varsizedIntUnpack(data, offset);
if (!value.has_value()) {
return std::nullopt;
}
variantVec.push_back(*value);
}
break;
case GetTypeIndex<std::string>(): {
std::optional<uint64_t> valueSize = varsizedIntUnpack(data, offset);
if (!valueSize.has_value()) {
return std::nullopt;
}
uint64_t valueSizeValue = *valueSize;
if (data.size() < offset + valueSizeValue) {
return std::nullopt;
}
std::string value = std::string((char*)&data[offset], valueSizeValue);
offset += valueSizeValue;
variantVec.push_back(value);
}
break;
case GetTypeIndex<std::vector<uint8_t>>(): {
std::optional<uint64_t> valueSize = varsizedIntUnpack(data, offset);
if (!valueSize.has_value()) {
return std::nullopt;
}
uint64_t valueSizeValue = *valueSize;
if (data.size() < offset + valueSizeValue) {
return std::nullopt;
}
std::vector<uint8_t> value = std::vector<uint8_t>(&data[offset], &data[offset] + valueSizeValue);
offset += valueSizeValue;
variantVec.push_back(value);
}
break;
}
}
return variantVec;
}