diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/protobuf-mutator/src/field_instance.h | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/libs/protobuf-mutator/src/field_instance.h')
-rw-r--r-- | contrib/libs/protobuf-mutator/src/field_instance.h | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/contrib/libs/protobuf-mutator/src/field_instance.h b/contrib/libs/protobuf-mutator/src/field_instance.h new file mode 100644 index 0000000000..11ab465e8a --- /dev/null +++ b/contrib/libs/protobuf-mutator/src/field_instance.h @@ -0,0 +1,449 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_FIELD_INSTANCE_H_ +#define SRC_FIELD_INSTANCE_H_ + +#include <memory> +#include <string> + +#include "port/protobuf.h" + +namespace protobuf_mutator { + +// Helper class for common protobuf fields operations. +class ConstFieldInstance { + public: + static const size_t kInvalidIndex = -1; + + struct Enum { + size_t index; + size_t count; + }; + + ConstFieldInstance() + : message_(nullptr), descriptor_(nullptr), index_(kInvalidIndex) {} + + ConstFieldInstance(const protobuf::Message* message, + const protobuf::FieldDescriptor* field, size_t index) + : message_(message), descriptor_(field), index_(index) { + assert(message_); + assert(descriptor_); + assert(index_ != kInvalidIndex); + assert(descriptor_->is_repeated()); + } + + ConstFieldInstance(const protobuf::Message* message, + const protobuf::FieldDescriptor* field) + : message_(message), descriptor_(field), index_(kInvalidIndex) { + assert(message_); + assert(descriptor_); + assert(!descriptor_->is_repeated()); + } + + void GetDefault(int32_t* out) const { + *out = descriptor_->default_value_int32(); + } + + void GetDefault(int64_t* out) const { + *out = descriptor_->default_value_int64(); + } + + void GetDefault(uint32_t* out) const { + *out = descriptor_->default_value_uint32(); + } + + void GetDefault(uint64_t* out) const { + *out = descriptor_->default_value_uint64(); + } + + void GetDefault(double* out) const { + *out = descriptor_->default_value_double(); + } + + void GetDefault(float* out) const { + *out = descriptor_->default_value_float(); + } + + void GetDefault(bool* out) const { *out = descriptor_->default_value_bool(); } + + void GetDefault(Enum* out) const { + const protobuf::EnumValueDescriptor* value = + descriptor_->default_value_enum(); + const protobuf::EnumDescriptor* type = value->type(); + *out = {static_cast<size_t>(value->index()), + static_cast<size_t>(type->value_count())}; + } + + void GetDefault(TProtoStringType* out) const { + *out = descriptor_->default_value_string(); + } + + void GetDefault(std::unique_ptr<protobuf::Message>* out) const { + out->reset(reflection() + .GetMessageFactory() + ->GetPrototype(descriptor_->message_type()) + ->New()); + } + + void Load(int32_t* value) const { + *value = is_repeated() + ? reflection().GetRepeatedInt32(*message_, descriptor_, index_) + : reflection().GetInt32(*message_, descriptor_); + } + + void Load(int64_t* value) const { + *value = is_repeated() + ? reflection().GetRepeatedInt64(*message_, descriptor_, index_) + : reflection().GetInt64(*message_, descriptor_); + } + + void Load(uint32_t* value) const { + *value = is_repeated() ? reflection().GetRepeatedUInt32(*message_, + descriptor_, index_) + : reflection().GetUInt32(*message_, descriptor_); + } + + void Load(uint64_t* value) const { + *value = is_repeated() ? reflection().GetRepeatedUInt64(*message_, + descriptor_, index_) + : reflection().GetUInt64(*message_, descriptor_); + } + + void Load(double* value) const { + *value = is_repeated() ? reflection().GetRepeatedDouble(*message_, + descriptor_, index_) + : reflection().GetDouble(*message_, descriptor_); + } + + void Load(float* value) const { + *value = is_repeated() + ? reflection().GetRepeatedFloat(*message_, descriptor_, index_) + : reflection().GetFloat(*message_, descriptor_); + } + + void Load(bool* value) const { + *value = is_repeated() + ? reflection().GetRepeatedBool(*message_, descriptor_, index_) + : reflection().GetBool(*message_, descriptor_); + } + + void Load(Enum* value) const { + const protobuf::EnumValueDescriptor* value_descriptor = + is_repeated() + ? reflection().GetRepeatedEnum(*message_, descriptor_, index_) + : reflection().GetEnum(*message_, descriptor_); + *value = {static_cast<size_t>(value_descriptor->index()), + static_cast<size_t>(value_descriptor->type()->value_count())}; + if (value->index >= value->count) GetDefault(value); + } + + void Load(TProtoStringType* value) const { + *value = is_repeated() ? reflection().GetRepeatedString(*message_, + descriptor_, index_) + : reflection().GetString(*message_, descriptor_); + } + + void Load(std::unique_ptr<protobuf::Message>* value) const { + const protobuf::Message& source = + is_repeated() + ? reflection().GetRepeatedMessage(*message_, descriptor_, index_) + : reflection().GetMessage(*message_, descriptor_); + value->reset(source.New()); + (*value)->CopyFrom(source); + } + + template <class T> + bool CanStore(const T& value) const { + return true; + } + + bool CanStore(const TProtoStringType& value) const { + if (!EnforceUtf8()) return true; + using protobuf::internal::WireFormatLite; + return WireFormatLite::VerifyUtf8String(value.data(), value.length(), + WireFormatLite::PARSE, ""); + } + + TProtoStringType name() const { return descriptor_->name(); } + + protobuf::FieldDescriptor::CppType cpp_type() const { + return descriptor_->cpp_type(); + } + + const protobuf::EnumDescriptor* enum_type() const { + return descriptor_->enum_type(); + } + + const protobuf::Descriptor* message_type() const { + return descriptor_->message_type(); + } + + bool EnforceUtf8() const { + return descriptor_->type() == protobuf::FieldDescriptor::TYPE_STRING && + descriptor()->file()->syntax() == + protobuf::FileDescriptor::SYNTAX_PROTO3; + } + + const protobuf::FieldDescriptor* descriptor() const { return descriptor_; } + + TProtoStringType DebugString() const { + TProtoStringType s = descriptor_->DebugString(); + if (is_repeated()) s += "[" + std::to_string(index_) + "]"; + return s + " of\n" + message_->DebugString(); + } + + protected: + bool is_repeated() const { return descriptor_->is_repeated(); } + + const protobuf::Reflection& reflection() const { + return *message_->GetReflection(); + } + + size_t index() const { return index_; } + + private: + template <class Fn, class T> + friend struct FieldFunction; + + const protobuf::Message* message_; + const protobuf::FieldDescriptor* descriptor_; + size_t index_; +}; + +class FieldInstance : public ConstFieldInstance { + public: + static const size_t kInvalidIndex = -1; + + FieldInstance() : ConstFieldInstance(), message_(nullptr) {} + + FieldInstance(protobuf::Message* message, + const protobuf::FieldDescriptor* field, size_t index) + : ConstFieldInstance(message, field, index), message_(message) {} + + FieldInstance(protobuf::Message* message, + const protobuf::FieldDescriptor* field) + : ConstFieldInstance(message, field), message_(message) {} + + void Delete() const { + if (!is_repeated()) return reflection().ClearField(message_, descriptor()); + int field_size = reflection().FieldSize(*message_, descriptor()); + // API has only method to delete the last message, so we move method from + // the + // middle to the end. + for (int i = index() + 1; i < field_size; ++i) + reflection().SwapElements(message_, descriptor(), i, i - 1); + reflection().RemoveLast(message_, descriptor()); + } + + template <class T> + void Create(const T& value) const { + if (!is_repeated()) return Store(value); + InsertRepeated(value); + } + + void Store(int32_t value) const { + if (is_repeated()) + reflection().SetRepeatedInt32(message_, descriptor(), index(), value); + else + reflection().SetInt32(message_, descriptor(), value); + } + + void Store(int64_t value) const { + if (is_repeated()) + reflection().SetRepeatedInt64(message_, descriptor(), index(), value); + else + reflection().SetInt64(message_, descriptor(), value); + } + + void Store(uint32_t value) const { + if (is_repeated()) + reflection().SetRepeatedUInt32(message_, descriptor(), index(), value); + else + reflection().SetUInt32(message_, descriptor(), value); + } + + void Store(uint64_t value) const { + if (is_repeated()) + reflection().SetRepeatedUInt64(message_, descriptor(), index(), value); + else + reflection().SetUInt64(message_, descriptor(), value); + } + + void Store(double value) const { + if (is_repeated()) + reflection().SetRepeatedDouble(message_, descriptor(), index(), value); + else + reflection().SetDouble(message_, descriptor(), value); + } + + void Store(float value) const { + if (is_repeated()) + reflection().SetRepeatedFloat(message_, descriptor(), index(), value); + else + reflection().SetFloat(message_, descriptor(), value); + } + + void Store(bool value) const { + if (is_repeated()) + reflection().SetRepeatedBool(message_, descriptor(), index(), value); + else + reflection().SetBool(message_, descriptor(), value); + } + + void Store(const Enum& value) const { + assert(value.index < value.count); + const protobuf::EnumValueDescriptor* enum_value = + descriptor()->enum_type()->value(value.index); + if (is_repeated()) + reflection().SetRepeatedEnum(message_, descriptor(), index(), enum_value); + else + reflection().SetEnum(message_, descriptor(), enum_value); + } + + void Store(const TProtoStringType& value) const { + if (is_repeated()) + reflection().SetRepeatedString(message_, descriptor(), index(), value); + else + reflection().SetString(message_, descriptor(), value); + } + + void Store(const std::unique_ptr<protobuf::Message>& value) const { + protobuf::Message* mutable_message = + is_repeated() ? reflection().MutableRepeatedMessage( + message_, descriptor(), index()) + : reflection().MutableMessage(message_, descriptor()); + mutable_message->Clear(); + if (value) mutable_message->CopyFrom(*value); + } + + private: + template <class T> + void InsertRepeated(const T& value) const { + PushBackRepeated(value); + size_t field_size = reflection().FieldSize(*message_, descriptor()); + if (field_size == 1) return; + // API has only method to add field to the end of the list. So we add + // descriptor() + // and move it into the middle. + for (size_t i = field_size - 1; i > index(); --i) + reflection().SwapElements(message_, descriptor(), i, i - 1); + } + + void PushBackRepeated(int32_t value) const { + assert(is_repeated()); + reflection().AddInt32(message_, descriptor(), value); + } + + void PushBackRepeated(int64_t value) const { + assert(is_repeated()); + reflection().AddInt64(message_, descriptor(), value); + } + + void PushBackRepeated(uint32_t value) const { + assert(is_repeated()); + reflection().AddUInt32(message_, descriptor(), value); + } + + void PushBackRepeated(uint64_t value) const { + assert(is_repeated()); + reflection().AddUInt64(message_, descriptor(), value); + } + + void PushBackRepeated(double value) const { + assert(is_repeated()); + reflection().AddDouble(message_, descriptor(), value); + } + + void PushBackRepeated(float value) const { + assert(is_repeated()); + reflection().AddFloat(message_, descriptor(), value); + } + + void PushBackRepeated(bool value) const { + assert(is_repeated()); + reflection().AddBool(message_, descriptor(), value); + } + + void PushBackRepeated(const Enum& value) const { + assert(value.index < value.count); + const protobuf::EnumValueDescriptor* enum_value = + descriptor()->enum_type()->value(value.index); + assert(is_repeated()); + reflection().AddEnum(message_, descriptor(), enum_value); + } + + void PushBackRepeated(const TProtoStringType& value) const { + assert(is_repeated()); + reflection().AddString(message_, descriptor(), value); + } + + void PushBackRepeated(const std::unique_ptr<protobuf::Message>& value) const { + assert(is_repeated()); + protobuf::Message* mutable_message = + reflection().AddMessage(message_, descriptor()); + mutable_message->Clear(); + if (value) mutable_message->CopyFrom(*value); + } + + protobuf::Message* message_; +}; + +template <class Fn, class R = void> +struct FieldFunction { + template <class Field, class... Args> + R operator()(const Field& field, const Args&... args) const { + assert(field.descriptor()); + using protobuf::FieldDescriptor; + switch (field.cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return static_cast<const Fn*>(this)->template ForType<int32_t>(field, + args...); + case FieldDescriptor::CPPTYPE_INT64: + return static_cast<const Fn*>(this)->template ForType<int64_t>(field, + args...); + case FieldDescriptor::CPPTYPE_UINT32: + return static_cast<const Fn*>(this)->template ForType<uint32_t>( + field, args...); + case FieldDescriptor::CPPTYPE_UINT64: + return static_cast<const Fn*>(this)->template ForType<uint64_t>( + field, args...); + case FieldDescriptor::CPPTYPE_DOUBLE: + return static_cast<const Fn*>(this)->template ForType<double>(field, + args...); + case FieldDescriptor::CPPTYPE_FLOAT: + return static_cast<const Fn*>(this)->template ForType<float>(field, + args...); + case FieldDescriptor::CPPTYPE_BOOL: + return static_cast<const Fn*>(this)->template ForType<bool>(field, + args...); + case FieldDescriptor::CPPTYPE_ENUM: + return static_cast<const Fn*>(this) + ->template ForType<ConstFieldInstance::Enum>(field, args...); + case FieldDescriptor::CPPTYPE_STRING: + return static_cast<const Fn*>(this)->template ForType<TProtoStringType>( + field, args...); + case FieldDescriptor::CPPTYPE_MESSAGE: + return static_cast<const Fn*>(this) + ->template ForType<std::unique_ptr<protobuf::Message>>(field, + args...); + } + assert(false && "Unknown type"); + abort(); + } +}; + +} // namespace protobuf_mutator + +#endif // SRC_FIELD_INSTANCE_H_ |