diff options
author | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
---|---|---|
committer | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
commit | 22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch) | |
tree | bffa27765faf54126ad44bcafa89fadecb7a73d7 /library/cpp/xdelta3/state/state.cpp | |
parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (diff) | |
download | ydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz |
validate canons without yatest_common
Diffstat (limited to 'library/cpp/xdelta3/state/state.cpp')
-rw-r--r-- | library/cpp/xdelta3/state/state.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/library/cpp/xdelta3/state/state.cpp b/library/cpp/xdelta3/state/state.cpp new file mode 100644 index 00000000000..f09dde04259 --- /dev/null +++ b/library/cpp/xdelta3/state/state.cpp @@ -0,0 +1,147 @@ +#include "state.h" + +#include <library/cpp/xdelta3/state/hash.h> +#include <library/cpp/xdelta3/xdelta_codec/codec.h> + +#include <util/stream/null.h> + +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/io/zero_copy_stream_impl_lite.h> + +namespace NXdeltaAggregateColumn { + size_t SizeOfHeaderSize(size_t headerSize) + { + using namespace NProtoBuf::io; + + ui32 dummy = 0; + auto data = reinterpret_cast<ui8*>(&dummy); + return CodedOutputStream::WriteVarint32ToArray(headerSize, data) - data; + } + + size_t SizeOfHeader(const TStateHeader& header) + { + // length of header + calculated length + auto headerSize = header.ByteSize(); + return SizeOfHeaderSize(headerSize) + headerSize; + } + + TStateHeader* ParseHeader(NProtoBuf::Arena& arena, const ui8* data, size_t size) + { + using namespace NProtoBuf::io; + + auto header = NProtoBuf::Arena::CreateMessage<TStateHeader>(&arena); + if (nullptr == data || 0 == size) { + header->set_error_code(TStateHeader::HEADER_PARSE_ERROR); + return header; + } + + ui32 headerSize = 0; + CodedInputStream in(data, size); + if (in.ReadVarint32(&headerSize)) { + auto sizeofHeaderSize = in.CurrentPosition(); + if (size - sizeofHeaderSize < headerSize) { + header->set_error_code(TStateHeader::HEADER_PARSE_ERROR); + return header; + } + + if (!header->ParseFromArray(data + sizeofHeaderSize, headerSize)) { + header->Clear(); + header->set_error_code(TStateHeader::HEADER_PARSE_ERROR); + } + } else { + header->set_error_code(TStateHeader::HEADER_PARSE_ERROR); + } + + return header; + } + + bool EncodeHeaderTo(const TStateHeader& header, ui8* data, size_t size, size_t& resultSize) + { + using namespace NProtoBuf::io; + + resultSize = 0; + auto headerSize = header.ByteSize(); + auto sizeOfHeaderSize = SizeOfHeaderSize(headerSize); + if (header.SerializeToArray(data + sizeOfHeaderSize, size - sizeOfHeaderSize)) { + sizeOfHeaderSize = CodedOutputStream::WriteVarint32ToArray(headerSize, data) - data; + resultSize = sizeOfHeaderSize + headerSize; + return true; + } + return false; + } + + TStateHeader::EErrorCode CheckProto(const TStateHeader* header, size_t dataSize) + { + auto hasRequiredFields = false; + if (header->type() == TStateHeader::BASE) { + hasRequiredFields = header->has_data_size(); + } else if (header->type() == TStateHeader::PATCH) { + hasRequiredFields = header->has_base_hash() && + header->has_state_hash() && + header->has_state_size() && + header->has_data_size(); + } else { + hasRequiredFields = header->has_error_code(); + } + if (!hasRequiredFields) { + return TStateHeader::MISSING_REQUIRED_FIELD_ERROR; + } + + auto payloadSizeOk = header->data_size() <= dataSize - SizeOfHeader(*header); + if (!payloadSizeOk) { + return TStateHeader::WRONG_DATA_SIZE; + } + return TStateHeader::NO_ERROR; + } + + TState::TState(NProtoBuf::Arena& arena, const ui8* data, size_t size) + { + if (nullptr == data || 0 == size) { + return; + } + + HeaderPtr = ParseHeader(arena, data, size); + if (HeaderPtr->has_error_code() && HeaderPtr->error_code() == TStateHeader::HEADER_PARSE_ERROR) { + return; + } + + auto errorCode = CheckProto(HeaderPtr, size); + if (errorCode != TStateHeader::NO_ERROR) { + HeaderPtr->Clear(); + HeaderPtr->set_error_code(errorCode); + return; + } + + if (HeaderPtr->type() != TStateHeader::NONE_TYPE) { + if (HeaderPtr->data_size()) { + Data = data + SizeOfHeader(*HeaderPtr); + } + } + } + + ui32 TState::CalcHash() const + { + if (nullptr != PayloadData() && 0 != PayloadSize()) { + return NXdeltaAggregateColumn::CalcHash(PayloadData(), PayloadSize()); + } + return 0; + } + + size_t TState::PayloadSize() const + { + return HeaderPtr->data_size(); + } + + TStateHeader::EErrorCode TState::Error() const + { + return HeaderPtr->has_error_code() + ? HeaderPtr->error_code() + : TStateHeader::NO_ERROR; + } + + TStateHeader::EType TState::Type() const + { + return HeaderPtr->type(); + } +} |