#include "VariantVector.h" #include "VarsizedInt.cpp/VarsizedInt.h" static inline void varsizedIntPack(std::vector& packed, uint64_t x) { uint8_t bytes[CVarsizedInt::MaxSize] = {}; int bytesSize = CVarsizedInt::Encode(bytes, x); packed.insert(packed.end(), bytes, bytes + bytesSize); } std::vector CVariantVector::Pack(const CVariantVector::Type& variantVec) { std::vector packed = {}; varsizedIntPack(packed, variantVec.size()); for (const auto& variant : variantVec) { uint64_t variantIndex = variant.index(); varsizedIntPack(packed, variantIndex); switch (variantIndex) { case GetTypeIndex(): varsizedIntPack(packed, std::get(variant)); break; case GetTypeIndex(): { const std::string& value = std::get(variant); varsizedIntPack(packed, value.size()); packed.insert(packed.end(), value.begin(), value.end()); } break; case GetTypeIndex>(): { const std::vector& value = std::get>(variant); varsizedIntPack(packed, value.size()); packed.insert(packed.end(), value.begin(), value.end()); } break; } } return packed; } static inline std::optional varsizedIntUnpack(const std::vector& 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::Unpack(const std::vector& data) { uint64_t offset = 0; std::optional 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 variantIndex = varsizedIntUnpack(data, offset); if (!variantIndex.has_value()) { return std::nullopt; } switch (*variantIndex) { case GetTypeIndex(): { std::optional value = varsizedIntUnpack(data, offset); if (!value.has_value()) { return std::nullopt; } variantVec.push_back(*value); } break; case GetTypeIndex(): { std::optional 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::optional 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 value = std::vector(&data[offset], &data[offset] + valueSizeValue); offset += valueSizeValue; variantVec.push_back(value); } break; } } return variantVec; }