diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/protobuf/util/walk.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/protobuf/util/walk.cpp')
-rw-r--r-- | library/cpp/protobuf/util/walk.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/library/cpp/protobuf/util/walk.cpp b/library/cpp/protobuf/util/walk.cpp new file mode 100644 index 0000000000..b65ec03e04 --- /dev/null +++ b/library/cpp/protobuf/util/walk.cpp @@ -0,0 +1,72 @@ +#include "walk.h" + +#include <util/generic/hash_set.h> + +namespace { + using namespace NProtoBuf; + + template <typename TMessage, typename TOnField> + void DoWalkReflection(TMessage& msg, TOnField& onField) { + const Descriptor* descr = msg.GetDescriptor(); + for (int i1 = 0; i1 < descr->field_count(); ++i1) { + const FieldDescriptor* fd = descr->field(i1); + if (!onField(msg, fd)) { + continue; + } + + std::conditional_t<std::is_const_v<TMessage>, TConstField, TMutableField> ff(msg, fd); + if (ff.IsMessage()) { + for (size_t i2 = 0; i2 < ff.Size(); ++i2) { + if constexpr (std::is_const_v<TMessage>) { + WalkReflection(*ff.template Get<Message>(i2), onField); + } else { + WalkReflection(*ff.MutableMessage(i2), onField); + } + } + } + } + } + + void DoWalkSchema(const Descriptor* descriptor, + std::function<bool(const FieldDescriptor*)>& onField, + THashSet<const Descriptor*>& visited) + { + if (!visited.emplace(descriptor).second) { + return; + } + for (int i1 = 0; i1 < descriptor->field_count(); ++i1) { + const FieldDescriptor* fd = descriptor->field(i1); + if (!onField(fd)) { + continue; + } + + if (fd->type() == FieldDescriptor::Type::TYPE_MESSAGE) { + DoWalkSchema(fd->message_type(), onField, visited); + } + } + visited.erase(descriptor); + } + +} + +namespace NProtoBuf { + void WalkReflection(Message& msg, + std::function<bool(Message&, const FieldDescriptor*)> onField) + { + DoWalkReflection(msg, onField); + } + + void WalkReflection(const Message& msg, + std::function<bool(const Message&, const FieldDescriptor*)> onField) + { + DoWalkReflection(msg, onField); + } + + void WalkSchema(const Descriptor* descriptor, + std::function<bool(const FieldDescriptor*)> onField) + { + THashSet<const Descriptor*> visited; + DoWalkSchema(descriptor, onField, visited); + } + +} // namespace NProtoBuf |