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