path.cpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #include "path.h"
  2. #include <util/generic/yexception.h>
  3. namespace NProtoBuf {
  4. TFieldPath::TFieldPath() {
  5. }
  6. TFieldPath::TFieldPath(const Descriptor* msgType, const TStringBuf& path) {
  7. Init(msgType, path);
  8. }
  9. TFieldPath::TFieldPath(const TVector<const FieldDescriptor*>& path)
  10. : Path(path)
  11. {
  12. }
  13. bool TFieldPath::InitUnsafe(const Descriptor* msgType, TStringBuf path) {
  14. Path.clear();
  15. while (path) {
  16. TStringBuf next;
  17. while (!next && path)
  18. next = path.NextTok('/');
  19. if (!next)
  20. return true;
  21. if (!msgType) // need field but no message type
  22. return false;
  23. TString nextStr(next);
  24. const FieldDescriptor* field = msgType->FindFieldByName(nextStr);
  25. if (!field) {
  26. // Try to find extension field by FindAllExtensions()
  27. const DescriptorPool* pool = msgType->file()->pool();
  28. Y_ASSERT(pool); // never NULL by protobuf docs
  29. TVector<const FieldDescriptor*> extensions;
  30. pool->FindAllExtensions(msgType, &extensions); // find all extensions of this extendee
  31. for (const FieldDescriptor* ext : extensions) {
  32. if (ext->full_name() == nextStr || ext->name() == nextStr) {
  33. if (field)
  34. return false; // ambiguity
  35. field = ext;
  36. }
  37. }
  38. }
  39. if (!field)
  40. return false;
  41. Path.push_back(field);
  42. msgType = field->type() == FieldDescriptor::TYPE_MESSAGE ? field->message_type() : nullptr;
  43. }
  44. return true;
  45. }
  46. void TFieldPath::Init(const Descriptor* msgType, const TStringBuf& path) {
  47. if (!InitUnsafe(msgType, path))
  48. ythrow yexception() << "Failed to resolve path \"" << path << "\" relative to " << msgType->full_name();
  49. }
  50. }