#include "simple_reflection.h" namespace NProtoBuf { const Message* GetMessageHelper(const TConstField& curField, bool) { return curField.HasValue() && curField.IsMessage() ? curField.Get() : nullptr; } Message* GetMessageHelper(TMutableField& curField, bool createPath) { if (curField.IsMessage()) { if (!curField.HasValue()) { if (createPath) return curField.Field()->is_repeated() ? curField.AddMessage() : curField.MutableMessage(); } else { return curField.MutableMessage(); } } return nullptr; } template TMaybe ByPathImpl(TMsg& msg, const TVector& fieldsPath, bool createPath) { if (fieldsPath.empty()) return TMaybe(); TMsg* curParent = &msg; for (size_t i = 0, size = fieldsPath.size(); i < size; ++i) { const FieldDescriptor* field = fieldsPath[i]; if (!curParent) return TMaybe(); TField curField(*curParent, field); if (size - i == 1) // last element in path return curField; curParent = GetMessageHelper(curField, createPath); } if (curParent) return TField(*curParent, fieldsPath.back()); else return TMaybe(); } TMaybe TConstField::ByPath(const Message& msg, const TVector& fieldsPath) { return ByPathImpl(msg, fieldsPath, false); } TMaybe TConstField::ByPath(const Message& msg, const TStringBuf& path) { TFieldPath fieldPath; if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) return TMaybe(); return ByPathImpl(msg, fieldPath.Fields(), false); } TMaybe TConstField::ByPath(const Message& msg, const TFieldPath& path) { return ByPathImpl(msg, path.Fields(), false); } TMaybe TMutableField::ByPath(Message& msg, const TVector& fieldsPath, bool createPath) { return ByPathImpl(msg, fieldsPath, createPath); } TMaybe TMutableField::ByPath(Message& msg, const TStringBuf& path, bool createPath) { TFieldPath fieldPath; if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) return TMaybe(); return ByPathImpl(msg, fieldPath.Fields(), createPath); } TMaybe TMutableField::ByPath(Message& msg, const TFieldPath& path, bool createPath) { return ByPathImpl(msg, path.Fields(), createPath); } }