#include "walk.h" #include namespace { using namespace NProtoBuf; template 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, TConstField, TMutableField> ff(msg, fd); if (ff.IsMessage()) { for (size_t i2 = 0; i2 < ff.Size(); ++i2) { if constexpr (std::is_const_v) { WalkReflection(*ff.template Get(i2), onField); } else { WalkReflection(*ff.MutableMessage(i2), onField); } } } } } void DoWalkSchema(const Descriptor* descriptor, std::function& onField, THashSet& 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 onField) { DoWalkReflection(msg, onField); } void WalkReflection(const Message& msg, std::function onField) { DoWalkReflection(msg, onField); } void WalkSchema(const Descriptor* descriptor, std::function onField) { THashSet visited; DoWalkSchema(descriptor, onField, visited); } } // namespace NProtoBuf