1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34
35 #include <algorithm>
36 #include <functional>
37 #include <limits>
38 #include <map>
39 #include <memory>
40 #include <set>
41 #include <string>
42 #include <unordered_map>
43 #include <unordered_set>
44 #include <vector>
45
46 #include <google/protobuf/stubs/common.h>
47 #include <google/protobuf/stubs/logging.h>
48 #include <google/protobuf/stubs/stringprintf.h>
49 #include <google/protobuf/stubs/strutil.h>
50 #include <google/protobuf/descriptor.pb.h>
51 #include <google/protobuf/io/strtod.h>
52 #include <google/protobuf/io/coded_stream.h>
53 #include <google/protobuf/io/tokenizer.h>
54 #include <google/protobuf/io/zero_copy_stream_impl.h>
55 #include <google/protobuf/descriptor.h>
56 #include <google/protobuf/descriptor_database.h>
57 #include <google/protobuf/dynamic_message.h>
58 #include <google/protobuf/generated_message_util.h>
59 #include <google/protobuf/text_format.h>
60 #include <google/protobuf/unknown_field_set.h>
61 #include <google/protobuf/wire_format.h>
62 #include <google/protobuf/stubs/substitute.h>
63 #include <google/protobuf/stubs/casts.h>
64
65
66
67 #include <google/protobuf/stubs/map_util.h>
68 #include <google/protobuf/stubs/stl_util.h>
69 #include <google/protobuf/stubs/hash.h>
70
71 #undef PACKAGE // autoheader #defines this. :(
72
73
74 #include <google/protobuf/port_def.inc>
75
76 namespace google {
77 namespace protobuf {
78
79 struct Symbol {
80 enum Type {
81 NULL_SYMBOL,
82 MESSAGE,
83 FIELD,
84 ONEOF,
85 ENUM,
86 ENUM_VALUE,
87 SERVICE,
88 METHOD,
89 PACKAGE
90 };
91 Type type;
92 union {
93 const Descriptor* descriptor;
94 const FieldDescriptor* field_descriptor;
95 const OneofDescriptor* oneof_descriptor;
96 const EnumDescriptor* enum_descriptor;
97 const EnumValueDescriptor* enum_value_descriptor;
98 const ServiceDescriptor* service_descriptor;
99 const MethodDescriptor* method_descriptor;
100 const FileDescriptor* package_file_descriptor;
101 };
102
Symbolgoogle::protobuf::Symbol103 inline Symbol() : type(NULL_SYMBOL) { descriptor = nullptr; }
IsNullgoogle::protobuf::Symbol104 inline bool IsNull() const { return type == NULL_SYMBOL; }
IsTypegoogle::protobuf::Symbol105 inline bool IsType() const { return type == MESSAGE || type == ENUM; }
IsAggregategoogle::protobuf::Symbol106 inline bool IsAggregate() const {
107 return type == MESSAGE || type == PACKAGE || type == ENUM ||
108 type == SERVICE;
109 }
110
111 #define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \
112 inline explicit Symbol(const TYPE* value) { \
113 type = TYPE_CONSTANT; \
114 this->FIELD = value; \
115 }
116
CONSTRUCTORgoogle::protobuf::Symbol117 CONSTRUCTOR(Descriptor, MESSAGE, descriptor)
118 CONSTRUCTOR(FieldDescriptor, FIELD, field_descriptor)
119 CONSTRUCTOR(OneofDescriptor, ONEOF, oneof_descriptor)
120 CONSTRUCTOR(EnumDescriptor, ENUM, enum_descriptor)
121 CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor)
122 CONSTRUCTOR(ServiceDescriptor, SERVICE, service_descriptor)
123 CONSTRUCTOR(MethodDescriptor, METHOD, method_descriptor)
124 CONSTRUCTOR(FileDescriptor, PACKAGE, package_file_descriptor)
125 #undef CONSTRUCTOR
126
127 const FileDescriptor* GetFile() const {
128 switch (type) {
129 case NULL_SYMBOL:
130 return nullptr;
131 case MESSAGE:
132 return descriptor->file();
133 case FIELD:
134 return field_descriptor->file();
135 case ONEOF:
136 return oneof_descriptor->containing_type()->file();
137 case ENUM:
138 return enum_descriptor->file();
139 case ENUM_VALUE:
140 return enum_value_descriptor->type()->file();
141 case SERVICE:
142 return service_descriptor->file();
143 case METHOD:
144 return method_descriptor->service()->file();
145 case PACKAGE:
146 return package_file_descriptor;
147 }
148 return nullptr;
149 }
150 };
151
152 const FieldDescriptor::CppType
153 FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
154 static_cast<CppType>(0), // 0 is reserved for errors
155
156 CPPTYPE_DOUBLE, // TYPE_DOUBLE
157 CPPTYPE_FLOAT, // TYPE_FLOAT
158 CPPTYPE_INT64, // TYPE_INT64
159 CPPTYPE_UINT64, // TYPE_UINT64
160 CPPTYPE_INT32, // TYPE_INT32
161 CPPTYPE_UINT64, // TYPE_FIXED64
162 CPPTYPE_UINT32, // TYPE_FIXED32
163 CPPTYPE_BOOL, // TYPE_BOOL
164 CPPTYPE_STRING, // TYPE_STRING
165 CPPTYPE_MESSAGE, // TYPE_GROUP
166 CPPTYPE_MESSAGE, // TYPE_MESSAGE
167 CPPTYPE_STRING, // TYPE_BYTES
168 CPPTYPE_UINT32, // TYPE_UINT32
169 CPPTYPE_ENUM, // TYPE_ENUM
170 CPPTYPE_INT32, // TYPE_SFIXED32
171 CPPTYPE_INT64, // TYPE_SFIXED64
172 CPPTYPE_INT32, // TYPE_SINT32
173 CPPTYPE_INT64, // TYPE_SINT64
174 };
175
176 const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
177 "ERROR", // 0 is reserved for errors
178
179 "double", // TYPE_DOUBLE
180 "float", // TYPE_FLOAT
181 "int64", // TYPE_INT64
182 "uint64", // TYPE_UINT64
183 "int32", // TYPE_INT32
184 "fixed64", // TYPE_FIXED64
185 "fixed32", // TYPE_FIXED32
186 "bool", // TYPE_BOOL
187 "string", // TYPE_STRING
188 "group", // TYPE_GROUP
189 "message", // TYPE_MESSAGE
190 "bytes", // TYPE_BYTES
191 "uint32", // TYPE_UINT32
192 "enum", // TYPE_ENUM
193 "sfixed32", // TYPE_SFIXED32
194 "sfixed64", // TYPE_SFIXED64
195 "sint32", // TYPE_SINT32
196 "sint64", // TYPE_SINT64
197 };
198
199 const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
200 "ERROR", // 0 is reserved for errors
201
202 "int32", // CPPTYPE_INT32
203 "int64", // CPPTYPE_INT64
204 "uint32", // CPPTYPE_UINT32
205 "uint64", // CPPTYPE_UINT64
206 "double", // CPPTYPE_DOUBLE
207 "float", // CPPTYPE_FLOAT
208 "bool", // CPPTYPE_BOOL
209 "enum", // CPPTYPE_ENUM
210 "string", // CPPTYPE_STRING
211 "message", // CPPTYPE_MESSAGE
212 };
213
214 const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
215 "ERROR", // 0 is reserved for errors
216
217 "optional", // LABEL_OPTIONAL
218 "required", // LABEL_REQUIRED
219 "repeated", // LABEL_REPEATED
220 };
221
SyntaxName(FileDescriptor::Syntax syntax)222 const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
223 switch (syntax) {
224 case SYNTAX_PROTO2:
225 return "proto2";
226 case SYNTAX_PROTO3:
227 return "proto3";
228 case SYNTAX_UNKNOWN:
229 return "unknown";
230 }
231 GOOGLE_LOG(FATAL) << "can't reach here.";
232 return nullptr;
233 }
234
235 static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
236
237 #if !defined(_MSC_VER) || _MSC_VER >= 1900
238 const int FieldDescriptor::kMaxNumber;
239 const int FieldDescriptor::kFirstReservedNumber;
240 const int FieldDescriptor::kLastReservedNumber;
241 #endif
242
243 namespace {
244
245 // Note: I distrust ctype.h due to locales.
ToUpper(char ch)246 char ToUpper(char ch) {
247 return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
248 }
249
ToLower(char ch)250 char ToLower(char ch) {
251 return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
252 }
253
ToCamelCase(const std::string & input,bool lower_first)254 std::string ToCamelCase(const std::string& input, bool lower_first) {
255 bool capitalize_next = !lower_first;
256 std::string result;
257 result.reserve(input.size());
258
259 for (int i = 0; i < input.size(); i++) {
260 if (input[i] == '_') {
261 capitalize_next = true;
262 } else if (capitalize_next) {
263 result.push_back(ToUpper(input[i]));
264 capitalize_next = false;
265 } else {
266 result.push_back(input[i]);
267 }
268 }
269
270 // Lower-case the first letter.
271 if (lower_first && !result.empty()) {
272 result[0] = ToLower(result[0]);
273 }
274
275 return result;
276 }
277
ToJsonName(const std::string & input)278 std::string ToJsonName(const std::string& input) {
279 bool capitalize_next = false;
280 std::string result;
281 result.reserve(input.size());
282
283 for (int i = 0; i < input.size(); i++) {
284 if (input[i] == '_') {
285 capitalize_next = true;
286 } else if (capitalize_next) {
287 result.push_back(ToUpper(input[i]));
288 capitalize_next = false;
289 } else {
290 result.push_back(input[i]);
291 }
292 }
293
294 return result;
295 }
296
EnumValueToPascalCase(const std::string & input)297 std::string EnumValueToPascalCase(const std::string& input) {
298 bool next_upper = true;
299 std::string result;
300 result.reserve(input.size());
301
302 for (int i = 0; i < input.size(); i++) {
303 if (input[i] == '_') {
304 next_upper = true;
305 } else {
306 if (next_upper) {
307 result.push_back(ToUpper(input[i]));
308 } else {
309 result.push_back(ToLower(input[i]));
310 }
311 next_upper = false;
312 }
313 }
314
315 return result;
316 }
317
318 // Class to remove an enum prefix from enum values.
319 class PrefixRemover {
320 public:
PrefixRemover(StringPiece prefix)321 PrefixRemover(StringPiece prefix) {
322 // Strip underscores and lower-case the prefix.
323 for (int i = 0; i < prefix.size(); i++) {
324 if (prefix[i] != '_') {
325 prefix_ += ascii_tolower(prefix[i]);
326 }
327 }
328 }
329
330 // Tries to remove the enum prefix from this enum value.
331 // If this is not possible, returns the input verbatim.
MaybeRemove(StringPiece str)332 std::string MaybeRemove(StringPiece str) {
333 // We can't just lowercase and strip str and look for a prefix.
334 // We need to properly recognize the difference between:
335 //
336 // enum Foo {
337 // FOO_BAR_BAZ = 0;
338 // FOO_BARBAZ = 1;
339 // }
340 //
341 // This is acceptable (though perhaps not advisable) because even when
342 // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
343 size_t i, j;
344
345 // Skip past prefix_ in str if we can.
346 for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
347 if (str[i] == '_') {
348 continue;
349 }
350
351 if (ascii_tolower(str[i]) != prefix_[j++]) {
352 return std::string(str);
353 }
354 }
355
356 // If we didn't make it through the prefix, we've failed to strip the
357 // prefix.
358 if (j < prefix_.size()) {
359 return std::string(str);
360 }
361
362 // Skip underscores between prefix and further characters.
363 while (i < str.size() && str[i] == '_') {
364 i++;
365 }
366
367 // Enum label can't be the empty string.
368 if (i == str.size()) {
369 return std::string(str);
370 }
371
372 // We successfully stripped the prefix.
373 str.remove_prefix(i);
374 return std::string(str);
375 }
376
377 private:
378 std::string prefix_;
379 };
380
381 // A DescriptorPool contains a bunch of hash-maps to implement the
382 // various Find*By*() methods. Since hashtable lookups are O(1), it's
383 // most efficient to construct a fixed set of large hash-maps used by
384 // all objects in the pool rather than construct one or more small
385 // hash-maps for each object.
386 //
387 // The keys to these hash-maps are (parent, name) or (parent, number) pairs.
388 //
389 // TODO(kenton): Use StringPiece rather than const char* in keys? It would
390 // be a lot cleaner but we'd just have to convert it back to const char*
391 // for the open source release.
392
393 typedef std::pair<const void*, const char*> PointerStringPair;
394
395 struct PointerStringPairEqual {
operator ()google::protobuf::__anoneb3ce4ee0211::PointerStringPairEqual396 inline bool operator()(const PointerStringPair& a,
397 const PointerStringPair& b) const {
398 return a.first == b.first && strcmp(a.second, b.second) == 0;
399 }
400 };
401
402 typedef std::pair<const Descriptor*, int> DescriptorIntPair;
403 typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
404
405 #define HASH_MAP std::unordered_map
406 #define HASH_SET std::unordered_set
407 #define HASH_FXN hash
408
409 template <typename PairType>
410 struct PointerIntegerPairHash {
operator ()google::protobuf::__anoneb3ce4ee0211::PointerIntegerPairHash411 size_t operator()(const PairType& p) const {
412 static const size_t prime1 = 16777499;
413 static const size_t prime2 = 16777619;
414 return reinterpret_cast<size_t>(p.first) * prime1 ^
415 static_cast<size_t>(p.second) * prime2;
416 }
417
418 #ifdef _MSC_VER
419 // Used only by MSVC and platforms where hash_map is not available.
420 static const size_t bucket_size = 4;
421 static const size_t min_buckets = 8;
422 #endif
operator ()google::protobuf::__anoneb3ce4ee0211::PointerIntegerPairHash423 inline bool operator()(const PairType& a, const PairType& b) const {
424 return a.first < b.first || (a.first == b.first && a.second < b.second);
425 }
426 };
427
428 struct PointerStringPairHash {
operator ()google::protobuf::__anoneb3ce4ee0211::PointerStringPairHash429 size_t operator()(const PointerStringPair& p) const {
430 static const size_t prime = 16777619;
431 hash<const char*> cstring_hash;
432 return reinterpret_cast<size_t>(p.first) * prime ^
433 static_cast<size_t>(cstring_hash(p.second));
434 }
435
436 #ifdef _MSC_VER
437 // Used only by MSVC and platforms where hash_map is not available.
438 static const size_t bucket_size = 4;
439 static const size_t min_buckets = 8;
440 #endif
operator ()google::protobuf::__anoneb3ce4ee0211::PointerStringPairHash441 inline bool operator()(const PointerStringPair& a,
442 const PointerStringPair& b) const {
443 if (a.first < b.first) return true;
444 if (a.first > b.first) return false;
445 return strcmp(a.second, b.second) < 0;
446 }
447 };
448
449
450 const Symbol kNullSymbol;
451
452 typedef HASH_MAP<const char*, Symbol, HASH_FXN<const char*>, streq>
453 SymbolsByNameMap;
454
455 typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash,
456 PointerStringPairEqual>
457 SymbolsByParentMap;
458
459 typedef HASH_MAP<const char*, const FileDescriptor*, HASH_FXN<const char*>,
460 streq>
461 FilesByNameMap;
462
463 typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
464 PointerStringPairHash, PointerStringPairEqual>
465 FieldsByNameMap;
466
467 typedef HASH_MAP<DescriptorIntPair, const FieldDescriptor*,
468 PointerIntegerPairHash<DescriptorIntPair>,
469 std::equal_to<DescriptorIntPair>>
470 FieldsByNumberMap;
471
472 typedef HASH_MAP<EnumIntPair, const EnumValueDescriptor*,
473 PointerIntegerPairHash<EnumIntPair>,
474 std::equal_to<EnumIntPair>>
475 EnumValuesByNumberMap;
476 // This is a map rather than a hash-map, since we use it to iterate
477 // through all the extensions that extend a given Descriptor, and an
478 // ordered data structure that implements lower_bound is convenient
479 // for that.
480 typedef std::map<DescriptorIntPair, const FieldDescriptor*>
481 ExtensionsGroupedByDescriptorMap;
482 typedef HASH_MAP<std::string, const SourceCodeInfo_Location*>
483 LocationsByPathMap;
484
NewAllowedProto3Extendee()485 std::set<std::string>* NewAllowedProto3Extendee() {
486 auto allowed_proto3_extendees = new std::set<std::string>;
487 const char* kOptionNames[] = {
488 "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions",
489 "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
490 for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) {
491 // descriptor.proto has a different package name in opensource. We allow
492 // both so the opensource protocol compiler can also compile internal
493 // proto3 files with custom options. See: b/27567912
494 allowed_proto3_extendees->insert(std::string("google.protobuf.") +
495 kOptionNames[i]);
496 // Split the word to trick the opensource processing scripts so they
497 // will keep the origial package name.
498 allowed_proto3_extendees->insert(std::string("proto") + "2." +
499 kOptionNames[i]);
500 }
501 return allowed_proto3_extendees;
502 }
503
504 // Checks whether the extendee type is allowed in proto3.
505 // Only extensions to descriptor options are allowed. We use name comparison
506 // instead of comparing the descriptor directly because the extensions may be
507 // defined in a different pool.
AllowedExtendeeInProto3(const std::string & name)508 bool AllowedExtendeeInProto3(const std::string& name) {
509 static auto allowed_proto3_extendees =
510 internal::OnShutdownDelete(NewAllowedProto3Extendee());
511 return allowed_proto3_extendees->find(name) !=
512 allowed_proto3_extendees->end();
513 }
514
515 } // anonymous namespace
516
517 // ===================================================================
518 // DescriptorPool::Tables
519
520 class DescriptorPool::Tables {
521 public:
522 Tables();
523 ~Tables();
524
525 // Record the current state of the tables to the stack of checkpoints.
526 // Each call to AddCheckpoint() must be paired with exactly one call to either
527 // ClearLastCheckpoint() or RollbackToLastCheckpoint().
528 //
529 // This is used when building files, since some kinds of validation errors
530 // cannot be detected until the file's descriptors have already been added to
531 // the tables.
532 //
533 // This supports recursive checkpoints, since building a file may trigger
534 // recursive building of other files. Note that recursive checkpoints are not
535 // normally necessary; explicit dependencies are built prior to checkpointing.
536 // So although we recursively build transitive imports, there is at most one
537 // checkpoint in the stack during dependency building.
538 //
539 // Recursive checkpoints only arise during cross-linking of the descriptors.
540 // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
541 // friends. If the pending file references an unknown symbol
542 // (e.g., it is not defined in the pending file's explicit dependencies), and
543 // the pool is using a fallback database, and that database contains a file
544 // defining that symbol, and that file has not yet been built by the pool,
545 // the pool builds the file during cross-linking, leading to another
546 // checkpoint.
547 void AddCheckpoint();
548
549 // Mark the last checkpoint as having cleared successfully, removing it from
550 // the stack. If the stack is empty, all pending symbols will be committed.
551 //
552 // Note that this does not guarantee that the symbols added since the last
553 // checkpoint won't be rolled back: if a checkpoint gets rolled back,
554 // everything past that point gets rolled back, including symbols added after
555 // checkpoints that were pushed onto the stack after it and marked as cleared.
556 void ClearLastCheckpoint();
557
558 // Roll back the Tables to the state of the checkpoint at the top of the
559 // stack, removing everything that was added after that point.
560 void RollbackToLastCheckpoint();
561
562 // The stack of files which are currently being built. Used to detect
563 // cyclic dependencies when loading files from a DescriptorDatabase. Not
564 // used when fallback_database_ == nullptr.
565 std::vector<std::string> pending_files_;
566
567 // A set of files which we have tried to load from the fallback database
568 // and encountered errors. We will not attempt to load them again during
569 // execution of the current public API call, but for compatibility with
570 // legacy clients, this is cleared at the beginning of each public API call.
571 // Not used when fallback_database_ == nullptr.
572 HASH_SET<std::string> known_bad_files_;
573
574 // A set of symbols which we have tried to load from the fallback database
575 // and encountered errors. We will not attempt to load them again during
576 // execution of the current public API call, but for compatibility with
577 // legacy clients, this is cleared at the beginning of each public API call.
578 HASH_SET<std::string> known_bad_symbols_;
579
580 // The set of descriptors for which we've already loaded the full
581 // set of extensions numbers from fallback_database_.
582 HASH_SET<const Descriptor*> extensions_loaded_from_db_;
583
584 // -----------------------------------------------------------------
585 // Finding items.
586
587 // Find symbols. This returns a null Symbol (symbol.IsNull() is true)
588 // if not found.
589 inline Symbol FindSymbol(const std::string& key) const;
590
591 // This implements the body of DescriptorPool::Find*ByName(). It should
592 // really be a private method of DescriptorPool, but that would require
593 // declaring Symbol in descriptor.h, which would drag all kinds of other
594 // stuff into the header. Yay C++.
595 Symbol FindByNameHelper(const DescriptorPool* pool, const std::string& name);
596
597 // These return nullptr if not found.
598 inline const FileDescriptor* FindFile(const std::string& key) const;
599 inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
600 int number) const;
601 inline void FindAllExtensions(const Descriptor* extendee,
602 std::vector<const FieldDescriptor*>* out) const;
603
604 // -----------------------------------------------------------------
605 // Adding items.
606
607 // These add items to the corresponding tables. They return false if
608 // the key already exists in the table. For AddSymbol(), the string passed
609 // in must be one that was constructed using AllocateString(), as it will
610 // be used as a key in the symbols_by_name_ map without copying.
611 bool AddSymbol(const std::string& full_name, Symbol symbol);
612 bool AddFile(const FileDescriptor* file);
613 bool AddExtension(const FieldDescriptor* field);
614
615 // -----------------------------------------------------------------
616 // Allocating memory.
617
618 // Allocate an object which will be reclaimed when the pool is
619 // destroyed. Note that the object's destructor will never be called,
620 // so its fields must be plain old data (primitive data types and
621 // pointers). All of the descriptor types are such objects.
622 template <typename Type>
623 Type* Allocate();
624
625 // Allocate an array of objects which will be reclaimed when the
626 // pool in destroyed. Again, destructors are never called.
627 template <typename Type>
628 Type* AllocateArray(int count);
629
630 // Allocate a string which will be destroyed when the pool is destroyed.
631 // The string is initialized to the given value for convenience.
632 std::string* AllocateString(const std::string& value);
633
634 // Allocate empty string which will be destroyed when the pool is destroyed.
635 std::string* AllocateEmptyString();
636
637 // Allocate a internal::call_once which will be destroyed when the pool is
638 // destroyed.
639 internal::once_flag* AllocateOnceDynamic();
640
641 // Allocate a protocol message object. Some older versions of GCC have
642 // trouble understanding explicit template instantiations in some cases, so
643 // in those cases we have to pass a dummy pointer of the right type as the
644 // parameter instead of specifying the type explicitly.
645 template <typename Type>
646 Type* AllocateMessage(Type* dummy = nullptr);
647
648 // Allocate a FileDescriptorTables object.
649 FileDescriptorTables* AllocateFileTables();
650
651 private:
652 std::vector<std::string*> strings_; // All strings in the pool.
653 std::vector<Message*> messages_; // All messages in the pool.
654 std::vector<internal::once_flag*>
655 once_dynamics_; // All internal::call_onces in the pool.
656 std::vector<FileDescriptorTables*>
657 file_tables_; // All file tables in the pool.
658 std::vector<void*> allocations_; // All other memory allocated in the pool.
659
660 SymbolsByNameMap symbols_by_name_;
661 FilesByNameMap files_by_name_;
662 ExtensionsGroupedByDescriptorMap extensions_;
663
664 struct CheckPoint {
CheckPointgoogle::protobuf::DescriptorPool::Tables::CheckPoint665 explicit CheckPoint(const Tables* tables)
666 : strings_before_checkpoint(tables->strings_.size()),
667 messages_before_checkpoint(tables->messages_.size()),
668 once_dynamics_before_checkpoint(tables->once_dynamics_.size()),
669 file_tables_before_checkpoint(tables->file_tables_.size()),
670 allocations_before_checkpoint(tables->allocations_.size()),
671 pending_symbols_before_checkpoint(
672 tables->symbols_after_checkpoint_.size()),
673 pending_files_before_checkpoint(
674 tables->files_after_checkpoint_.size()),
675 pending_extensions_before_checkpoint(
676 tables->extensions_after_checkpoint_.size()) {}
677 int strings_before_checkpoint;
678 int messages_before_checkpoint;
679 int once_dynamics_before_checkpoint;
680 int file_tables_before_checkpoint;
681 int allocations_before_checkpoint;
682 int pending_symbols_before_checkpoint;
683 int pending_files_before_checkpoint;
684 int pending_extensions_before_checkpoint;
685 };
686 std::vector<CheckPoint> checkpoints_;
687 std::vector<const char*> symbols_after_checkpoint_;
688 std::vector<const char*> files_after_checkpoint_;
689 std::vector<DescriptorIntPair> extensions_after_checkpoint_;
690
691 // Allocate some bytes which will be reclaimed when the pool is
692 // destroyed.
693 void* AllocateBytes(int size);
694 };
695
696 // Contains tables specific to a particular file. These tables are not
697 // modified once the file has been constructed, so they need not be
698 // protected by a mutex. This makes operations that depend only on the
699 // contents of a single file -- e.g. Descriptor::FindFieldByName() --
700 // lock-free.
701 //
702 // For historical reasons, the definitions of the methods of
703 // FileDescriptorTables and DescriptorPool::Tables are interleaved below.
704 // These used to be a single class.
705 class FileDescriptorTables {
706 public:
707 FileDescriptorTables();
708 ~FileDescriptorTables();
709
710 // Empty table, used with placeholder files.
711 inline static const FileDescriptorTables& GetEmptyInstance();
712
713 // -----------------------------------------------------------------
714 // Finding items.
715
716 // Find symbols. These return a null Symbol (symbol.IsNull() is true)
717 // if not found.
718 inline Symbol FindNestedSymbol(const void* parent,
719 const std::string& name) const;
720 inline Symbol FindNestedSymbolOfType(const void* parent,
721 const std::string& name,
722 const Symbol::Type type) const;
723
724 // These return nullptr if not found.
725 inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
726 int number) const;
727 inline const FieldDescriptor* FindFieldByLowercaseName(
728 const void* parent, const std::string& lowercase_name) const;
729 inline const FieldDescriptor* FindFieldByCamelcaseName(
730 const void* parent, const std::string& camelcase_name) const;
731 inline const EnumValueDescriptor* FindEnumValueByNumber(
732 const EnumDescriptor* parent, int number) const;
733 // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
734 inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
735 const EnumDescriptor* parent, int number) const;
736
737 // -----------------------------------------------------------------
738 // Adding items.
739
740 // These add items to the corresponding tables. They return false if
741 // the key already exists in the table. For AddAliasUnderParent(), the
742 // string passed in must be one that was constructed using AllocateString(),
743 // as it will be used as a key in the symbols_by_parent_ map without copying.
744 bool AddAliasUnderParent(const void* parent, const std::string& name,
745 Symbol symbol);
746 bool AddFieldByNumber(const FieldDescriptor* field);
747 bool AddEnumValueByNumber(const EnumValueDescriptor* value);
748
749 // Adds the field to the lowercase_name and camelcase_name maps. Never
750 // fails because we allow duplicates; the first field by the name wins.
751 void AddFieldByStylizedNames(const FieldDescriptor* field);
752
753 // Populates p->first->locations_by_path_ from p->second.
754 // Unusual signature dictated by internal::call_once.
755 static void BuildLocationsByPath(
756 std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
757
758 // Returns the location denoted by the specified path through info,
759 // or nullptr if not found.
760 // The value of info must be that of the corresponding FileDescriptor.
761 // (Conceptually a pure function, but stateful as an optimisation.)
762 const SourceCodeInfo_Location* GetSourceLocation(
763 const std::vector<int>& path, const SourceCodeInfo* info) const;
764
765 // Must be called after BuildFileImpl(), even if the build failed and
766 // we are going to roll back to the last checkpoint.
767 void FinalizeTables();
768
769 private:
770 const void* FindParentForFieldsByMap(const FieldDescriptor* field) const;
771 static void FieldsByLowercaseNamesLazyInitStatic(
772 const FileDescriptorTables* tables);
773 void FieldsByLowercaseNamesLazyInitInternal() const;
774 static void FieldsByCamelcaseNamesLazyInitStatic(
775 const FileDescriptorTables* tables);
776 void FieldsByCamelcaseNamesLazyInitInternal() const;
777
778 SymbolsByParentMap symbols_by_parent_;
779 mutable FieldsByNameMap fields_by_lowercase_name_;
780 std::unique_ptr<FieldsByNameMap> fields_by_lowercase_name_tmp_;
781 mutable internal::once_flag fields_by_lowercase_name_once_;
782 mutable FieldsByNameMap fields_by_camelcase_name_;
783 std::unique_ptr<FieldsByNameMap> fields_by_camelcase_name_tmp_;
784 mutable internal::once_flag fields_by_camelcase_name_once_;
785 FieldsByNumberMap fields_by_number_; // Not including extensions.
786 EnumValuesByNumberMap enum_values_by_number_;
787 mutable EnumValuesByNumberMap unknown_enum_values_by_number_
788 PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
789
790 // Populated on first request to save space, hence constness games.
791 mutable internal::once_flag locations_by_path_once_;
792 mutable LocationsByPathMap locations_by_path_;
793
794 // Mutex to protect the unknown-enum-value map due to dynamic
795 // EnumValueDescriptor creation on unknown values.
796 mutable internal::WrappedMutex unknown_enum_values_mu_;
797 };
798
Tables()799 DescriptorPool::Tables::Tables()
800 // Start some hash-map and hash-set objects with a small # of buckets
801 : known_bad_files_(3),
802 known_bad_symbols_(3),
803 extensions_loaded_from_db_(3),
804 symbols_by_name_(3),
805 files_by_name_(3) {}
806
~Tables()807 DescriptorPool::Tables::~Tables() {
808 GOOGLE_DCHECK(checkpoints_.empty());
809 // Note that the deletion order is important, since the destructors of some
810 // messages may refer to objects in allocations_.
811 STLDeleteElements(&messages_);
812 for (int i = 0; i < allocations_.size(); i++) {
813 operator delete(allocations_[i]);
814 }
815 STLDeleteElements(&strings_);
816 STLDeleteElements(&file_tables_);
817 STLDeleteElements(&once_dynamics_);
818 }
819
FileDescriptorTables()820 FileDescriptorTables::FileDescriptorTables()
821 // Initialize all the hash tables to start out with a small # of buckets.
822 : symbols_by_parent_(3),
823 fields_by_lowercase_name_(3),
824 fields_by_lowercase_name_tmp_(new FieldsByNameMap()),
825 fields_by_camelcase_name_(3),
826 fields_by_camelcase_name_tmp_(new FieldsByNameMap()),
827 fields_by_number_(3),
828 enum_values_by_number_(3),
829 unknown_enum_values_by_number_(3),
830 locations_by_path_(3) {}
831
~FileDescriptorTables()832 FileDescriptorTables::~FileDescriptorTables() {}
833
GetEmptyInstance()834 inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
835 static auto file_descriptor_tables =
836 internal::OnShutdownDelete(new FileDescriptorTables());
837 return *file_descriptor_tables;
838 }
839
AddCheckpoint()840 void DescriptorPool::Tables::AddCheckpoint() {
841 checkpoints_.push_back(CheckPoint(this));
842 }
843
ClearLastCheckpoint()844 void DescriptorPool::Tables::ClearLastCheckpoint() {
845 GOOGLE_DCHECK(!checkpoints_.empty());
846 checkpoints_.pop_back();
847 if (checkpoints_.empty()) {
848 // All checkpoints have been cleared: we can now commit all of the pending
849 // data.
850 symbols_after_checkpoint_.clear();
851 files_after_checkpoint_.clear();
852 extensions_after_checkpoint_.clear();
853 }
854 }
855
RollbackToLastCheckpoint()856 void DescriptorPool::Tables::RollbackToLastCheckpoint() {
857 GOOGLE_DCHECK(!checkpoints_.empty());
858 const CheckPoint& checkpoint = checkpoints_.back();
859
860 for (int i = checkpoint.pending_symbols_before_checkpoint;
861 i < symbols_after_checkpoint_.size(); i++) {
862 symbols_by_name_.erase(symbols_after_checkpoint_[i]);
863 }
864 for (int i = checkpoint.pending_files_before_checkpoint;
865 i < files_after_checkpoint_.size(); i++) {
866 files_by_name_.erase(files_after_checkpoint_[i]);
867 }
868 for (int i = checkpoint.pending_extensions_before_checkpoint;
869 i < extensions_after_checkpoint_.size(); i++) {
870 extensions_.erase(extensions_after_checkpoint_[i]);
871 }
872
873 symbols_after_checkpoint_.resize(
874 checkpoint.pending_symbols_before_checkpoint);
875 files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
876 extensions_after_checkpoint_.resize(
877 checkpoint.pending_extensions_before_checkpoint);
878
879 STLDeleteContainerPointers(
880 strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end());
881 STLDeleteContainerPointers(
882 messages_.begin() + checkpoint.messages_before_checkpoint,
883 messages_.end());
884 STLDeleteContainerPointers(
885 once_dynamics_.begin() + checkpoint.once_dynamics_before_checkpoint,
886 once_dynamics_.end());
887 STLDeleteContainerPointers(
888 file_tables_.begin() + checkpoint.file_tables_before_checkpoint,
889 file_tables_.end());
890 for (int i = checkpoint.allocations_before_checkpoint;
891 i < allocations_.size(); i++) {
892 operator delete(allocations_[i]);
893 }
894
895 strings_.resize(checkpoint.strings_before_checkpoint);
896 messages_.resize(checkpoint.messages_before_checkpoint);
897 once_dynamics_.resize(checkpoint.once_dynamics_before_checkpoint);
898 file_tables_.resize(checkpoint.file_tables_before_checkpoint);
899 allocations_.resize(checkpoint.allocations_before_checkpoint);
900 checkpoints_.pop_back();
901 }
902
903 // -------------------------------------------------------------------
904
FindSymbol(const std::string & key) const905 inline Symbol DescriptorPool::Tables::FindSymbol(const std::string& key) const {
906 const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
907 if (result == nullptr) {
908 return kNullSymbol;
909 } else {
910 return *result;
911 }
912 }
913
FindNestedSymbol(const void * parent,const std::string & name) const914 inline Symbol FileDescriptorTables::FindNestedSymbol(
915 const void* parent, const std::string& name) const {
916 const Symbol* result = FindOrNull(
917 symbols_by_parent_, PointerStringPair(parent, name.c_str()));
918 if (result == nullptr) {
919 return kNullSymbol;
920 } else {
921 return *result;
922 }
923 }
924
FindNestedSymbolOfType(const void * parent,const std::string & name,const Symbol::Type type) const925 inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
926 const void* parent, const std::string& name,
927 const Symbol::Type type) const {
928 Symbol result = FindNestedSymbol(parent, name);
929 if (result.type != type) return kNullSymbol;
930 return result;
931 }
932
FindByNameHelper(const DescriptorPool * pool,const std::string & name)933 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
934 const std::string& name) {
935 MutexLockMaybe lock(pool->mutex_);
936 if (pool->fallback_database_ != nullptr) {
937 known_bad_symbols_.clear();
938 known_bad_files_.clear();
939 }
940 Symbol result = FindSymbol(name);
941
942 if (result.IsNull() && pool->underlay_ != nullptr) {
943 // Symbol not found; check the underlay.
944 result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
945 }
946
947 if (result.IsNull()) {
948 // Symbol still not found, so check fallback database.
949 if (pool->TryFindSymbolInFallbackDatabase(name)) {
950 result = FindSymbol(name);
951 }
952 }
953
954 return result;
955 }
956
FindFile(const std::string & key) const957 inline const FileDescriptor* DescriptorPool::Tables::FindFile(
958 const std::string& key) const {
959 return FindPtrOrNull(files_by_name_, key.c_str());
960 }
961
FindFieldByNumber(const Descriptor * parent,int number) const962 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
963 const Descriptor* parent, int number) const {
964 return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
965 }
966
FindParentForFieldsByMap(const FieldDescriptor * field) const967 const void* FileDescriptorTables::FindParentForFieldsByMap(
968 const FieldDescriptor* field) const {
969 if (field->is_extension()) {
970 if (field->extension_scope() == nullptr) {
971 return field->file();
972 } else {
973 return field->extension_scope();
974 }
975 } else {
976 return field->containing_type();
977 }
978 }
979
FieldsByLowercaseNamesLazyInitStatic(const FileDescriptorTables * tables)980 void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
981 const FileDescriptorTables* tables) {
982 tables->FieldsByLowercaseNamesLazyInitInternal();
983 }
984
FieldsByLowercaseNamesLazyInitInternal() const985 void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
986 for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
987 it != fields_by_number_.end(); it++) {
988 PointerStringPair lowercase_key(FindParentForFieldsByMap(it->second),
989 it->second->lowercase_name().c_str());
990 InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key,
991 it->second);
992 }
993 }
994
FindFieldByLowercaseName(const void * parent,const std::string & lowercase_name) const995 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
996 const void* parent, const std::string& lowercase_name) const {
997 internal::call_once(
998 fields_by_lowercase_name_once_,
999 &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this);
1000 return FindPtrOrNull(fields_by_lowercase_name_,
1001 PointerStringPair(parent, lowercase_name.c_str()));
1002 }
1003
FieldsByCamelcaseNamesLazyInitStatic(const FileDescriptorTables * tables)1004 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
1005 const FileDescriptorTables* tables) {
1006 tables->FieldsByCamelcaseNamesLazyInitInternal();
1007 }
1008
FieldsByCamelcaseNamesLazyInitInternal() const1009 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
1010 for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
1011 it != fields_by_number_.end(); it++) {
1012 PointerStringPair camelcase_key(FindParentForFieldsByMap(it->second),
1013 it->second->camelcase_name().c_str());
1014 InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key,
1015 it->second);
1016 }
1017 }
1018
FindFieldByCamelcaseName(const void * parent,const std::string & camelcase_name) const1019 inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
1020 const void* parent, const std::string& camelcase_name) const {
1021 internal::call_once(
1022 fields_by_camelcase_name_once_,
1023 FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this);
1024 return FindPtrOrNull(fields_by_camelcase_name_,
1025 PointerStringPair(parent, camelcase_name.c_str()));
1026 }
1027
FindEnumValueByNumber(const EnumDescriptor * parent,int number) const1028 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
1029 const EnumDescriptor* parent, int number) const {
1030 return FindPtrOrNull(enum_values_by_number_,
1031 std::make_pair(parent, number));
1032 }
1033
1034 inline const EnumValueDescriptor*
FindEnumValueByNumberCreatingIfUnknown(const EnumDescriptor * parent,int number) const1035 FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
1036 const EnumDescriptor* parent, int number) const {
1037 // First try, with map of compiled-in values.
1038 {
1039 const EnumValueDescriptor* desc = FindPtrOrNull(
1040 enum_values_by_number_, std::make_pair(parent, number));
1041 if (desc != nullptr) {
1042 return desc;
1043 }
1044 }
1045 // Second try, with reader lock held on unknown enum values: common case.
1046 {
1047 ReaderMutexLock l(&unknown_enum_values_mu_);
1048 const EnumValueDescriptor* desc = FindPtrOrNull(
1049 unknown_enum_values_by_number_, std::make_pair(parent, number));
1050 if (desc != nullptr) {
1051 return desc;
1052 }
1053 }
1054 // If not found, try again with writer lock held, and create new descriptor if
1055 // necessary.
1056 {
1057 WriterMutexLock l(&unknown_enum_values_mu_);
1058 const EnumValueDescriptor* desc = FindPtrOrNull(
1059 unknown_enum_values_by_number_, std::make_pair(parent, number));
1060 if (desc != nullptr) {
1061 return desc;
1062 }
1063
1064 // Create an EnumValueDescriptor dynamically. We don't insert it into the
1065 // EnumDescriptor (it's not a part of the enum as originally defined), but
1066 // we do insert it into the table so that we can return the same pointer
1067 // later.
1068 std::string enum_value_name = StringPrintf("UNKNOWN_ENUM_VALUE_%s_%d",
1069 parent->name().c_str(), number);
1070 DescriptorPool::Tables* tables = const_cast<DescriptorPool::Tables*>(
1071 DescriptorPool::generated_pool()->tables_.get());
1072 EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
1073 result->name_ = tables->AllocateString(enum_value_name);
1074 result->full_name_ =
1075 tables->AllocateString(parent->full_name() + "." + enum_value_name);
1076 result->number_ = number;
1077 result->type_ = parent;
1078 result->options_ = &EnumValueOptions::default_instance();
1079 InsertIfNotPresent(&unknown_enum_values_by_number_,
1080 std::make_pair(parent, number), result);
1081 return result;
1082 }
1083 }
1084
FindExtension(const Descriptor * extendee,int number) const1085 inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1086 const Descriptor* extendee, int number) const {
1087 return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
1088 }
1089
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1090 inline void DescriptorPool::Tables::FindAllExtensions(
1091 const Descriptor* extendee,
1092 std::vector<const FieldDescriptor*>* out) const {
1093 ExtensionsGroupedByDescriptorMap::const_iterator it =
1094 extensions_.lower_bound(std::make_pair(extendee, 0));
1095 for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1096 out->push_back(it->second);
1097 }
1098 }
1099
1100 // -------------------------------------------------------------------
1101
AddSymbol(const std::string & full_name,Symbol symbol)1102 bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
1103 Symbol symbol) {
1104 if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
1105 symbols_after_checkpoint_.push_back(full_name.c_str());
1106 return true;
1107 } else {
1108 return false;
1109 }
1110 }
1111
AddAliasUnderParent(const void * parent,const std::string & name,Symbol symbol)1112 bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
1113 const std::string& name,
1114 Symbol symbol) {
1115 PointerStringPair by_parent_key(parent, name.c_str());
1116 return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
1117 }
1118
AddFile(const FileDescriptor * file)1119 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1120 if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) {
1121 files_after_checkpoint_.push_back(file->name().c_str());
1122 return true;
1123 } else {
1124 return false;
1125 }
1126 }
1127
FinalizeTables()1128 void FileDescriptorTables::FinalizeTables() {
1129 // Clean up the temporary maps used by AddFieldByStylizedNames().
1130 fields_by_lowercase_name_tmp_ = nullptr;
1131 fields_by_camelcase_name_tmp_ = nullptr;
1132 }
1133
AddFieldByStylizedNames(const FieldDescriptor * field)1134 void FileDescriptorTables::AddFieldByStylizedNames(
1135 const FieldDescriptor* field) {
1136 const void* parent = FindParentForFieldsByMap(field);
1137
1138 // We want fields_by_{lower,camel}case_name_ to be lazily built, but
1139 // cross-link order determines which entry will be present in the case of a
1140 // conflict. So we use the temporary maps that get destroyed after
1141 // BuildFileImpl() to detect the conflicts, and only store the conflicts in
1142 // the map that will persist. We will then lazily populate the rest of the
1143 // entries from fields_by_number_.
1144
1145 PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
1146 if (!InsertIfNotPresent(fields_by_lowercase_name_tmp_.get(),
1147 lowercase_key, field)) {
1148 InsertIfNotPresent(
1149 &fields_by_lowercase_name_, lowercase_key,
1150 FindPtrOrNull(*fields_by_lowercase_name_tmp_, lowercase_key));
1151 }
1152
1153 PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
1154 if (!InsertIfNotPresent(fields_by_camelcase_name_tmp_.get(),
1155 camelcase_key, field)) {
1156 InsertIfNotPresent(
1157 &fields_by_camelcase_name_, camelcase_key,
1158 FindPtrOrNull(*fields_by_camelcase_name_tmp_, camelcase_key));
1159 }
1160 }
1161
AddFieldByNumber(const FieldDescriptor * field)1162 bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
1163 DescriptorIntPair key(field->containing_type(), field->number());
1164 return InsertIfNotPresent(&fields_by_number_, key, field);
1165 }
1166
AddEnumValueByNumber(const EnumValueDescriptor * value)1167 bool FileDescriptorTables::AddEnumValueByNumber(
1168 const EnumValueDescriptor* value) {
1169 EnumIntPair key(value->type(), value->number());
1170 return InsertIfNotPresent(&enum_values_by_number_, key, value);
1171 }
1172
AddExtension(const FieldDescriptor * field)1173 bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1174 DescriptorIntPair key(field->containing_type(), field->number());
1175 if (InsertIfNotPresent(&extensions_, key, field)) {
1176 extensions_after_checkpoint_.push_back(key);
1177 return true;
1178 } else {
1179 return false;
1180 }
1181 }
1182
1183 // -------------------------------------------------------------------
1184
1185 template <typename Type>
Allocate()1186 Type* DescriptorPool::Tables::Allocate() {
1187 return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type)));
1188 }
1189
1190 template <typename Type>
AllocateArray(int count)1191 Type* DescriptorPool::Tables::AllocateArray(int count) {
1192 return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
1193 }
1194
AllocateString(const std::string & value)1195 std::string* DescriptorPool::Tables::AllocateString(const std::string& value) {
1196 std::string* result = new std::string(value);
1197 strings_.push_back(result);
1198 return result;
1199 }
1200
AllocateEmptyString()1201 std::string* DescriptorPool::Tables::AllocateEmptyString() {
1202 std::string* result = new std::string();
1203 strings_.push_back(result);
1204 return result;
1205 }
1206
AllocateOnceDynamic()1207 internal::once_flag* DescriptorPool::Tables::AllocateOnceDynamic() {
1208 internal::once_flag* result = new internal::once_flag();
1209 once_dynamics_.push_back(result);
1210 return result;
1211 }
1212
1213 template <typename Type>
AllocateMessage(Type *)1214 Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) {
1215 Type* result = new Type;
1216 messages_.push_back(result);
1217 return result;
1218 }
1219
AllocateFileTables()1220 FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
1221 FileDescriptorTables* result = new FileDescriptorTables;
1222 file_tables_.push_back(result);
1223 return result;
1224 }
1225
AllocateBytes(int size)1226 void* DescriptorPool::Tables::AllocateBytes(int size) {
1227 // TODO(kenton): Would it be worthwhile to implement this in some more
1228 // sophisticated way? Probably not for the open source release, but for
1229 // internal use we could easily plug in one of our existing memory pool
1230 // allocators...
1231 if (size == 0) return nullptr;
1232
1233 void* result = operator new(size);
1234 allocations_.push_back(result);
1235 return result;
1236 }
1237
BuildLocationsByPath(std::pair<const FileDescriptorTables *,const SourceCodeInfo * > * p)1238 void FileDescriptorTables::BuildLocationsByPath(
1239 std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1240 for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1241 const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1242 p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
1243 }
1244 }
1245
GetSourceLocation(const std::vector<int> & path,const SourceCodeInfo * info) const1246 const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1247 const std::vector<int>& path, const SourceCodeInfo* info) const {
1248 std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1249 std::make_pair(this, info));
1250 internal::call_once(locations_by_path_once_,
1251 FileDescriptorTables::BuildLocationsByPath, &p);
1252 return FindPtrOrNull(locations_by_path_, Join(path, ","));
1253 }
1254
1255 // ===================================================================
1256 // DescriptorPool
1257
~ErrorCollector()1258 DescriptorPool::ErrorCollector::~ErrorCollector() {}
1259
DescriptorPool()1260 DescriptorPool::DescriptorPool()
1261 : mutex_(nullptr),
1262 fallback_database_(nullptr),
1263 default_error_collector_(nullptr),
1264 underlay_(nullptr),
1265 tables_(new Tables),
1266 enforce_dependencies_(true),
1267 lazily_build_dependencies_(false),
1268 allow_unknown_(false),
1269 enforce_weak_(false),
1270 disallow_enforce_utf8_(false) {}
1271
DescriptorPool(DescriptorDatabase * fallback_database,ErrorCollector * error_collector)1272 DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1273 ErrorCollector* error_collector)
1274 : mutex_(new internal::WrappedMutex),
1275 fallback_database_(fallback_database),
1276 default_error_collector_(error_collector),
1277 underlay_(nullptr),
1278 tables_(new Tables),
1279 enforce_dependencies_(true),
1280 lazily_build_dependencies_(false),
1281 allow_unknown_(false),
1282 enforce_weak_(false),
1283 disallow_enforce_utf8_(false) {}
1284
DescriptorPool(const DescriptorPool * underlay)1285 DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1286 : mutex_(nullptr),
1287 fallback_database_(nullptr),
1288 default_error_collector_(nullptr),
1289 underlay_(underlay),
1290 tables_(new Tables),
1291 enforce_dependencies_(true),
1292 lazily_build_dependencies_(false),
1293 allow_unknown_(false),
1294 enforce_weak_(false),
1295 disallow_enforce_utf8_(false) {}
1296
~DescriptorPool()1297 DescriptorPool::~DescriptorPool() {
1298 if (mutex_ != nullptr) delete mutex_;
1299 }
1300
1301 // DescriptorPool::BuildFile() defined later.
1302 // DescriptorPool::BuildFileCollectingErrors() defined later.
1303
InternalDontEnforceDependencies()1304 void DescriptorPool::InternalDontEnforceDependencies() {
1305 enforce_dependencies_ = false;
1306 }
1307
AddUnusedImportTrackFile(const std::string & file_name)1308 void DescriptorPool::AddUnusedImportTrackFile(const std::string& file_name) {
1309 unused_import_track_files_.insert(file_name);
1310 }
1311
ClearUnusedImportTrackFiles()1312 void DescriptorPool::ClearUnusedImportTrackFiles() {
1313 unused_import_track_files_.clear();
1314 }
1315
InternalIsFileLoaded(const std::string & filename) const1316 bool DescriptorPool::InternalIsFileLoaded(const std::string& filename) const {
1317 MutexLockMaybe lock(mutex_);
1318 return tables_->FindFile(filename) != nullptr;
1319 }
1320
1321 // generated_pool ====================================================
1322
1323 namespace {
1324
1325
GeneratedDatabase()1326 EncodedDescriptorDatabase* GeneratedDatabase() {
1327 static auto generated_database =
1328 internal::OnShutdownDelete(new EncodedDescriptorDatabase());
1329 return generated_database;
1330 }
1331
NewGeneratedPool()1332 DescriptorPool* NewGeneratedPool() {
1333 auto generated_pool = new DescriptorPool(GeneratedDatabase());
1334 generated_pool->InternalSetLazilyBuildDependencies();
1335 return generated_pool;
1336 }
1337
1338 } // anonymous namespace
1339
internal_generated_pool()1340 DescriptorPool* DescriptorPool::internal_generated_pool() {
1341 static DescriptorPool* generated_pool =
1342 internal::OnShutdownDelete(NewGeneratedPool());
1343 return generated_pool;
1344 }
1345
generated_pool()1346 const DescriptorPool* DescriptorPool::generated_pool() {
1347 const DescriptorPool* pool = internal_generated_pool();
1348 // Ensure that descriptor.proto has been registered in the generated pool.
1349 DescriptorProto::descriptor();
1350 return pool;
1351 }
1352
1353
1354
InternalAddGeneratedFile(const void * encoded_file_descriptor,int size)1355 void DescriptorPool::InternalAddGeneratedFile(
1356 const void* encoded_file_descriptor, int size) {
1357 // So, this function is called in the process of initializing the
1358 // descriptors for generated proto classes. Each generated .pb.cc file
1359 // has an internal procedure called AddDescriptors() which is called at
1360 // process startup, and that function calls this one in order to register
1361 // the raw bytes of the FileDescriptorProto representing the file.
1362 //
1363 // We do not actually construct the descriptor objects right away. We just
1364 // hang on to the bytes until they are actually needed. We actually construct
1365 // the descriptor the first time one of the following things happens:
1366 // * Someone calls a method like descriptor(), GetDescriptor(), or
1367 // GetReflection() on the generated types, which requires returning the
1368 // descriptor or an object based on it.
1369 // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1370 //
1371 // Once one of these happens, the DescriptorPool actually parses the
1372 // FileDescriptorProto and generates a FileDescriptor (and all its children)
1373 // based on it.
1374 //
1375 // Note that FileDescriptorProto is itself a generated protocol message.
1376 // Therefore, when we parse one, we have to be very careful to avoid using
1377 // any descriptor-based operations, since this might cause infinite recursion
1378 // or deadlock.
1379 GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
1380 }
1381
1382
1383 // Find*By* methods ==================================================
1384
1385 // TODO(kenton): There's a lot of repeated code here, but I'm not sure if
1386 // there's any good way to factor it out. Think about this some time when
1387 // there's nothing more important to do (read: never).
1388
FindFileByName(const std::string & name) const1389 const FileDescriptor* DescriptorPool::FindFileByName(
1390 const std::string& name) const {
1391 MutexLockMaybe lock(mutex_);
1392 if (fallback_database_ != nullptr) {
1393 tables_->known_bad_symbols_.clear();
1394 tables_->known_bad_files_.clear();
1395 }
1396 const FileDescriptor* result = tables_->FindFile(name);
1397 if (result != nullptr) return result;
1398 if (underlay_ != nullptr) {
1399 result = underlay_->FindFileByName(name);
1400 if (result != nullptr) return result;
1401 }
1402 if (TryFindFileInFallbackDatabase(name)) {
1403 result = tables_->FindFile(name);
1404 if (result != nullptr) return result;
1405 }
1406 return nullptr;
1407 }
1408
FindFileContainingSymbol(const std::string & symbol_name) const1409 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
1410 const std::string& symbol_name) const {
1411 MutexLockMaybe lock(mutex_);
1412 if (fallback_database_ != nullptr) {
1413 tables_->known_bad_symbols_.clear();
1414 tables_->known_bad_files_.clear();
1415 }
1416 Symbol result = tables_->FindSymbol(symbol_name);
1417 if (!result.IsNull()) return result.GetFile();
1418 if (underlay_ != nullptr) {
1419 const FileDescriptor* file_result =
1420 underlay_->FindFileContainingSymbol(symbol_name);
1421 if (file_result != nullptr) return file_result;
1422 }
1423 if (TryFindSymbolInFallbackDatabase(symbol_name)) {
1424 result = tables_->FindSymbol(symbol_name);
1425 if (!result.IsNull()) return result.GetFile();
1426 }
1427 return nullptr;
1428 }
1429
FindMessageTypeByName(const std::string & name) const1430 const Descriptor* DescriptorPool::FindMessageTypeByName(
1431 const std::string& name) const {
1432 Symbol result = tables_->FindByNameHelper(this, name);
1433 return (result.type == Symbol::MESSAGE) ? result.descriptor : nullptr;
1434 }
1435
FindFieldByName(const std::string & name) const1436 const FieldDescriptor* DescriptorPool::FindFieldByName(
1437 const std::string& name) const {
1438 Symbol result = tables_->FindByNameHelper(this, name);
1439 if (result.type == Symbol::FIELD &&
1440 !result.field_descriptor->is_extension()) {
1441 return result.field_descriptor;
1442 } else {
1443 return nullptr;
1444 }
1445 }
1446
FindExtensionByName(const std::string & name) const1447 const FieldDescriptor* DescriptorPool::FindExtensionByName(
1448 const std::string& name) const {
1449 Symbol result = tables_->FindByNameHelper(this, name);
1450 if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) {
1451 return result.field_descriptor;
1452 } else {
1453 return nullptr;
1454 }
1455 }
1456
FindOneofByName(const std::string & name) const1457 const OneofDescriptor* DescriptorPool::FindOneofByName(
1458 const std::string& name) const {
1459 Symbol result = tables_->FindByNameHelper(this, name);
1460 return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : nullptr;
1461 }
1462
FindEnumTypeByName(const std::string & name) const1463 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
1464 const std::string& name) const {
1465 Symbol result = tables_->FindByNameHelper(this, name);
1466 return (result.type == Symbol::ENUM) ? result.enum_descriptor : nullptr;
1467 }
1468
FindEnumValueByName(const std::string & name) const1469 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
1470 const std::string& name) const {
1471 Symbol result = tables_->FindByNameHelper(this, name);
1472 return (result.type == Symbol::ENUM_VALUE) ? result.enum_value_descriptor
1473 : nullptr;
1474 }
1475
FindServiceByName(const std::string & name) const1476 const ServiceDescriptor* DescriptorPool::FindServiceByName(
1477 const std::string& name) const {
1478 Symbol result = tables_->FindByNameHelper(this, name);
1479 return (result.type == Symbol::SERVICE) ? result.service_descriptor : nullptr;
1480 }
1481
FindMethodByName(const std::string & name) const1482 const MethodDescriptor* DescriptorPool::FindMethodByName(
1483 const std::string& name) const {
1484 Symbol result = tables_->FindByNameHelper(this, name);
1485 return (result.type == Symbol::METHOD) ? result.method_descriptor : nullptr;
1486 }
1487
FindExtensionByNumber(const Descriptor * extendee,int number) const1488 const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
1489 const Descriptor* extendee, int number) const {
1490 if (extendee->extension_range_count() == 0) return nullptr;
1491 // A faster path to reduce lock contention in finding extensions, assuming
1492 // most extensions will be cache hit.
1493 if (mutex_ != nullptr) {
1494 ReaderMutexLock lock(mutex_);
1495 const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1496 if (result != nullptr) {
1497 return result;
1498 }
1499 }
1500 MutexLockMaybe lock(mutex_);
1501 if (fallback_database_ != nullptr) {
1502 tables_->known_bad_symbols_.clear();
1503 tables_->known_bad_files_.clear();
1504 }
1505 const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1506 if (result != nullptr) {
1507 return result;
1508 }
1509 if (underlay_ != nullptr) {
1510 result = underlay_->FindExtensionByNumber(extendee, number);
1511 if (result != nullptr) return result;
1512 }
1513 if (TryFindExtensionInFallbackDatabase(extendee, number)) {
1514 result = tables_->FindExtension(extendee, number);
1515 if (result != nullptr) {
1516 return result;
1517 }
1518 }
1519 return nullptr;
1520 }
1521
FindExtensionByPrintableName(const Descriptor * extendee,const std::string & printable_name) const1522 const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
1523 const Descriptor* extendee, const std::string& printable_name) const {
1524 if (extendee->extension_range_count() == 0) return nullptr;
1525 const FieldDescriptor* result = FindExtensionByName(printable_name);
1526 if (result != nullptr && result->containing_type() == extendee) {
1527 return result;
1528 }
1529 if (extendee->options().message_set_wire_format()) {
1530 // MessageSet extensions may be identified by type name.
1531 const Descriptor* type = FindMessageTypeByName(printable_name);
1532 if (type != nullptr) {
1533 // Look for a matching extension in the foreign type's scope.
1534 const int type_extension_count = type->extension_count();
1535 for (int i = 0; i < type_extension_count; i++) {
1536 const FieldDescriptor* extension = type->extension(i);
1537 if (extension->containing_type() == extendee &&
1538 extension->type() == FieldDescriptor::TYPE_MESSAGE &&
1539 extension->is_optional() && extension->message_type() == type) {
1540 // Found it.
1541 return extension;
1542 }
1543 }
1544 }
1545 }
1546 return nullptr;
1547 }
1548
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1549 void DescriptorPool::FindAllExtensions(
1550 const Descriptor* extendee,
1551 std::vector<const FieldDescriptor*>* out) const {
1552 MutexLockMaybe lock(mutex_);
1553 if (fallback_database_ != nullptr) {
1554 tables_->known_bad_symbols_.clear();
1555 tables_->known_bad_files_.clear();
1556 }
1557
1558 // Initialize tables_->extensions_ from the fallback database first
1559 // (but do this only once per descriptor).
1560 if (fallback_database_ != nullptr &&
1561 tables_->extensions_loaded_from_db_.count(extendee) == 0) {
1562 std::vector<int> numbers;
1563 if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
1564 &numbers)) {
1565 for (int i = 0; i < numbers.size(); ++i) {
1566 int number = numbers[i];
1567 if (tables_->FindExtension(extendee, number) == nullptr) {
1568 TryFindExtensionInFallbackDatabase(extendee, number);
1569 }
1570 }
1571 tables_->extensions_loaded_from_db_.insert(extendee);
1572 }
1573 }
1574
1575 tables_->FindAllExtensions(extendee, out);
1576 if (underlay_ != nullptr) {
1577 underlay_->FindAllExtensions(extendee, out);
1578 }
1579 }
1580
1581
1582 // -------------------------------------------------------------------
1583
FindFieldByNumber(int key) const1584 const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
1585 const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
1586 if (result == nullptr || result->is_extension()) {
1587 return nullptr;
1588 } else {
1589 return result;
1590 }
1591 }
1592
FindFieldByLowercaseName(const std::string & key) const1593 const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
1594 const std::string& key) const {
1595 const FieldDescriptor* result =
1596 file()->tables_->FindFieldByLowercaseName(this, key);
1597 if (result == nullptr || result->is_extension()) {
1598 return nullptr;
1599 } else {
1600 return result;
1601 }
1602 }
1603
FindFieldByCamelcaseName(const std::string & key) const1604 const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
1605 const std::string& key) const {
1606 const FieldDescriptor* result =
1607 file()->tables_->FindFieldByCamelcaseName(this, key);
1608 if (result == nullptr || result->is_extension()) {
1609 return nullptr;
1610 } else {
1611 return result;
1612 }
1613 }
1614
FindFieldByName(const std::string & key) const1615 const FieldDescriptor* Descriptor::FindFieldByName(
1616 const std::string& key) const {
1617 Symbol result =
1618 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1619 if (!result.IsNull() && !result.field_descriptor->is_extension()) {
1620 return result.field_descriptor;
1621 } else {
1622 return nullptr;
1623 }
1624 }
1625
FindOneofByName(const std::string & key) const1626 const OneofDescriptor* Descriptor::FindOneofByName(
1627 const std::string& key) const {
1628 Symbol result =
1629 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
1630 if (!result.IsNull()) {
1631 return result.oneof_descriptor;
1632 } else {
1633 return nullptr;
1634 }
1635 }
1636
FindExtensionByName(const std::string & key) const1637 const FieldDescriptor* Descriptor::FindExtensionByName(
1638 const std::string& key) const {
1639 Symbol result =
1640 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1641 if (!result.IsNull() && result.field_descriptor->is_extension()) {
1642 return result.field_descriptor;
1643 } else {
1644 return nullptr;
1645 }
1646 }
1647
FindExtensionByLowercaseName(const std::string & key) const1648 const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
1649 const std::string& key) const {
1650 const FieldDescriptor* result =
1651 file()->tables_->FindFieldByLowercaseName(this, key);
1652 if (result == nullptr || !result->is_extension()) {
1653 return nullptr;
1654 } else {
1655 return result;
1656 }
1657 }
1658
FindExtensionByCamelcaseName(const std::string & key) const1659 const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
1660 const std::string& key) const {
1661 const FieldDescriptor* result =
1662 file()->tables_->FindFieldByCamelcaseName(this, key);
1663 if (result == nullptr || !result->is_extension()) {
1664 return nullptr;
1665 } else {
1666 return result;
1667 }
1668 }
1669
FindNestedTypeByName(const std::string & key) const1670 const Descriptor* Descriptor::FindNestedTypeByName(
1671 const std::string& key) const {
1672 Symbol result =
1673 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1674 if (!result.IsNull()) {
1675 return result.descriptor;
1676 } else {
1677 return nullptr;
1678 }
1679 }
1680
FindEnumTypeByName(const std::string & key) const1681 const EnumDescriptor* Descriptor::FindEnumTypeByName(
1682 const std::string& key) const {
1683 Symbol result =
1684 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1685 if (!result.IsNull()) {
1686 return result.enum_descriptor;
1687 } else {
1688 return nullptr;
1689 }
1690 }
1691
FindEnumValueByName(const std::string & key) const1692 const EnumValueDescriptor* Descriptor::FindEnumValueByName(
1693 const std::string& key) const {
1694 Symbol result =
1695 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1696 if (!result.IsNull()) {
1697 return result.enum_value_descriptor;
1698 } else {
1699 return nullptr;
1700 }
1701 }
1702
FindValueByName(const std::string & key) const1703 const EnumValueDescriptor* EnumDescriptor::FindValueByName(
1704 const std::string& key) const {
1705 Symbol result =
1706 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1707 if (!result.IsNull()) {
1708 return result.enum_value_descriptor;
1709 } else {
1710 return nullptr;
1711 }
1712 }
1713
FindValueByNumber(int key) const1714 const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const {
1715 return file()->tables_->FindEnumValueByNumber(this, key);
1716 }
1717
FindValueByNumberCreatingIfUnknown(int key) const1718 const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown(
1719 int key) const {
1720 return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
1721 }
1722
FindMethodByName(const std::string & key) const1723 const MethodDescriptor* ServiceDescriptor::FindMethodByName(
1724 const std::string& key) const {
1725 Symbol result =
1726 file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
1727 if (!result.IsNull()) {
1728 return result.method_descriptor;
1729 } else {
1730 return nullptr;
1731 }
1732 }
1733
FindMessageTypeByName(const std::string & key) const1734 const Descriptor* FileDescriptor::FindMessageTypeByName(
1735 const std::string& key) const {
1736 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1737 if (!result.IsNull()) {
1738 return result.descriptor;
1739 } else {
1740 return nullptr;
1741 }
1742 }
1743
FindEnumTypeByName(const std::string & key) const1744 const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
1745 const std::string& key) const {
1746 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1747 if (!result.IsNull()) {
1748 return result.enum_descriptor;
1749 } else {
1750 return nullptr;
1751 }
1752 }
1753
FindEnumValueByName(const std::string & key) const1754 const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
1755 const std::string& key) const {
1756 Symbol result =
1757 tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1758 if (!result.IsNull()) {
1759 return result.enum_value_descriptor;
1760 } else {
1761 return nullptr;
1762 }
1763 }
1764
FindServiceByName(const std::string & key) const1765 const ServiceDescriptor* FileDescriptor::FindServiceByName(
1766 const std::string& key) const {
1767 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
1768 if (!result.IsNull()) {
1769 return result.service_descriptor;
1770 } else {
1771 return nullptr;
1772 }
1773 }
1774
FindExtensionByName(const std::string & key) const1775 const FieldDescriptor* FileDescriptor::FindExtensionByName(
1776 const std::string& key) const {
1777 Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1778 if (!result.IsNull() && result.field_descriptor->is_extension()) {
1779 return result.field_descriptor;
1780 } else {
1781 return nullptr;
1782 }
1783 }
1784
FindExtensionByLowercaseName(const std::string & key) const1785 const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
1786 const std::string& key) const {
1787 const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
1788 if (result == nullptr || !result->is_extension()) {
1789 return nullptr;
1790 } else {
1791 return result;
1792 }
1793 }
1794
FindExtensionByCamelcaseName(const std::string & key) const1795 const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
1796 const std::string& key) const {
1797 const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
1798 if (result == nullptr || !result->is_extension()) {
1799 return nullptr;
1800 } else {
1801 return result;
1802 }
1803 }
1804
CopyTo(DescriptorProto_ExtensionRange * proto) const1805 void Descriptor::ExtensionRange::CopyTo(
1806 DescriptorProto_ExtensionRange* proto) const {
1807 proto->set_start(this->start);
1808 proto->set_end(this->end);
1809 if (options_ != &ExtensionRangeOptions::default_instance()) {
1810 *proto->mutable_options() = *options_;
1811 }
1812 }
1813
1814 const Descriptor::ExtensionRange*
FindExtensionRangeContainingNumber(int number) const1815 Descriptor::FindExtensionRangeContainingNumber(int number) const {
1816 // Linear search should be fine because we don't expect a message to have
1817 // more than a couple extension ranges.
1818 for (int i = 0; i < extension_range_count(); i++) {
1819 if (number >= extension_range(i)->start &&
1820 number < extension_range(i)->end) {
1821 return extension_range(i);
1822 }
1823 }
1824 return nullptr;
1825 }
1826
FindReservedRangeContainingNumber(int number) const1827 const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
1828 int number) const {
1829 // TODO(chrisn): Consider a non-linear search.
1830 for (int i = 0; i < reserved_range_count(); i++) {
1831 if (number >= reserved_range(i)->start && number < reserved_range(i)->end) {
1832 return reserved_range(i);
1833 }
1834 }
1835 return nullptr;
1836 }
1837
1838 const EnumDescriptor::ReservedRange*
FindReservedRangeContainingNumber(int number) const1839 EnumDescriptor::FindReservedRangeContainingNumber(int number) const {
1840 // TODO(chrisn): Consider a non-linear search.
1841 for (int i = 0; i < reserved_range_count(); i++) {
1842 if (number >= reserved_range(i)->start &&
1843 number <= reserved_range(i)->end) {
1844 return reserved_range(i);
1845 }
1846 }
1847 return nullptr;
1848 }
1849
1850 // -------------------------------------------------------------------
1851
TryFindFileInFallbackDatabase(const std::string & name) const1852 bool DescriptorPool::TryFindFileInFallbackDatabase(
1853 const std::string& name) const {
1854 if (fallback_database_ == nullptr) return false;
1855
1856 if (tables_->known_bad_files_.count(name) > 0) return false;
1857
1858 FileDescriptorProto file_proto;
1859 if (!fallback_database_->FindFileByName(name, &file_proto) ||
1860 BuildFileFromDatabase(file_proto) == nullptr) {
1861 tables_->known_bad_files_.insert(name);
1862 return false;
1863 }
1864 return true;
1865 }
1866
IsSubSymbolOfBuiltType(const std::string & name) const1867 bool DescriptorPool::IsSubSymbolOfBuiltType(const std::string& name) const {
1868 std::string prefix = name;
1869 for (;;) {
1870 std::string::size_type dot_pos = prefix.find_last_of('.');
1871 if (dot_pos == std::string::npos) {
1872 break;
1873 }
1874 prefix = prefix.substr(0, dot_pos);
1875 Symbol symbol = tables_->FindSymbol(prefix);
1876 // If the symbol type is anything other than PACKAGE, then its complete
1877 // definition is already known.
1878 if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
1879 return true;
1880 }
1881 }
1882 if (underlay_ != nullptr) {
1883 // Check to see if any prefix of this symbol exists in the underlay.
1884 return underlay_->IsSubSymbolOfBuiltType(name);
1885 }
1886 return false;
1887 }
1888
TryFindSymbolInFallbackDatabase(const std::string & name) const1889 bool DescriptorPool::TryFindSymbolInFallbackDatabase(
1890 const std::string& name) const {
1891 if (fallback_database_ == nullptr) return false;
1892
1893 if (tables_->known_bad_symbols_.count(name) > 0) return false;
1894
1895 FileDescriptorProto file_proto;
1896 if ( // We skip looking in the fallback database if the name is a sub-symbol
1897 // of any descriptor that already exists in the descriptor pool (except
1898 // for package descriptors). This is valid because all symbols except
1899 // for packages are defined in a single file, so if the symbol exists
1900 // then we should already have its definition.
1901 //
1902 // The other reason to do this is to support "overriding" type
1903 // definitions by merging two databases that define the same type. (Yes,
1904 // people do this.) The main difficulty with making this work is that
1905 // FindFileContainingSymbol() is allowed to return both false positives
1906 // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and
1907 // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
1908 // When two such databases are merged, looking up a non-existent
1909 // sub-symbol of a type that already exists in the descriptor pool can
1910 // result in an attempt to load multiple definitions of the same type.
1911 // The check below avoids this.
1912 IsSubSymbolOfBuiltType(name)
1913
1914 // Look up file containing this symbol in fallback database.
1915 || !fallback_database_->FindFileContainingSymbol(name, &file_proto)
1916
1917 // Check if we've already built this file. If so, it apparently doesn't
1918 // contain the symbol we're looking for. Some DescriptorDatabases
1919 // return false positives.
1920 || tables_->FindFile(file_proto.name()) != nullptr
1921
1922 // Build the file.
1923 || BuildFileFromDatabase(file_proto) == nullptr) {
1924 tables_->known_bad_symbols_.insert(name);
1925 return false;
1926 }
1927
1928 return true;
1929 }
1930
TryFindExtensionInFallbackDatabase(const Descriptor * containing_type,int field_number) const1931 bool DescriptorPool::TryFindExtensionInFallbackDatabase(
1932 const Descriptor* containing_type, int field_number) const {
1933 if (fallback_database_ == nullptr) return false;
1934
1935 FileDescriptorProto file_proto;
1936 if (!fallback_database_->FindFileContainingExtension(
1937 containing_type->full_name(), field_number, &file_proto)) {
1938 return false;
1939 }
1940
1941 if (tables_->FindFile(file_proto.name()) != nullptr) {
1942 // We've already loaded this file, and it apparently doesn't contain the
1943 // extension we're looking for. Some DescriptorDatabases return false
1944 // positives.
1945 return false;
1946 }
1947
1948 if (BuildFileFromDatabase(file_proto) == nullptr) {
1949 return false;
1950 }
1951
1952 return true;
1953 }
1954
1955 // ===================================================================
1956
is_map_message_type() const1957 bool FieldDescriptor::is_map_message_type() const {
1958 return message_type_->options().map_entry();
1959 }
1960
DefaultValueAsString(bool quote_string_type) const1961 std::string FieldDescriptor::DefaultValueAsString(
1962 bool quote_string_type) const {
1963 GOOGLE_CHECK(has_default_value()) << "No default value";
1964 switch (cpp_type()) {
1965 case CPPTYPE_INT32:
1966 return StrCat(default_value_int32());
1967 break;
1968 case CPPTYPE_INT64:
1969 return StrCat(default_value_int64());
1970 break;
1971 case CPPTYPE_UINT32:
1972 return StrCat(default_value_uint32());
1973 break;
1974 case CPPTYPE_UINT64:
1975 return StrCat(default_value_uint64());
1976 break;
1977 case CPPTYPE_FLOAT:
1978 return SimpleFtoa(default_value_float());
1979 break;
1980 case CPPTYPE_DOUBLE:
1981 return SimpleDtoa(default_value_double());
1982 break;
1983 case CPPTYPE_BOOL:
1984 return default_value_bool() ? "true" : "false";
1985 break;
1986 case CPPTYPE_STRING:
1987 if (quote_string_type) {
1988 return "\"" + CEscape(default_value_string()) + "\"";
1989 } else {
1990 if (type() == TYPE_BYTES) {
1991 return CEscape(default_value_string());
1992 } else {
1993 return default_value_string();
1994 }
1995 }
1996 break;
1997 case CPPTYPE_ENUM:
1998 return default_value_enum()->name();
1999 break;
2000 case CPPTYPE_MESSAGE:
2001 GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
2002 break;
2003 }
2004 GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string";
2005 return "";
2006 }
2007
2008 // CopyTo methods ====================================================
2009
CopyTo(FileDescriptorProto * proto) const2010 void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
2011 proto->set_name(name());
2012 if (!package().empty()) proto->set_package(package());
2013 // TODO(liujisi): Also populate when syntax="proto2".
2014 if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
2015
2016 for (int i = 0; i < dependency_count(); i++) {
2017 proto->add_dependency(dependency(i)->name());
2018 }
2019
2020 for (int i = 0; i < public_dependency_count(); i++) {
2021 proto->add_public_dependency(public_dependencies_[i]);
2022 }
2023
2024 for (int i = 0; i < weak_dependency_count(); i++) {
2025 proto->add_weak_dependency(weak_dependencies_[i]);
2026 }
2027
2028 for (int i = 0; i < message_type_count(); i++) {
2029 message_type(i)->CopyTo(proto->add_message_type());
2030 }
2031 for (int i = 0; i < enum_type_count(); i++) {
2032 enum_type(i)->CopyTo(proto->add_enum_type());
2033 }
2034 for (int i = 0; i < service_count(); i++) {
2035 service(i)->CopyTo(proto->add_service());
2036 }
2037 for (int i = 0; i < extension_count(); i++) {
2038 extension(i)->CopyTo(proto->add_extension());
2039 }
2040
2041 if (&options() != &FileOptions::default_instance()) {
2042 proto->mutable_options()->CopyFrom(options());
2043 }
2044 }
2045
CopyJsonNameTo(FileDescriptorProto * proto) const2046 void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
2047 if (message_type_count() != proto->message_type_size() ||
2048 extension_count() != proto->extension_size()) {
2049 GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2050 return;
2051 }
2052 for (int i = 0; i < message_type_count(); i++) {
2053 message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
2054 }
2055 for (int i = 0; i < extension_count(); i++) {
2056 extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2057 }
2058 }
2059
CopySourceCodeInfoTo(FileDescriptorProto * proto) const2060 void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
2061 if (source_code_info_ &&
2062 source_code_info_ != &SourceCodeInfo::default_instance()) {
2063 proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
2064 }
2065 }
2066
CopyTo(DescriptorProto * proto) const2067 void Descriptor::CopyTo(DescriptorProto* proto) const {
2068 proto->set_name(name());
2069
2070 for (int i = 0; i < field_count(); i++) {
2071 field(i)->CopyTo(proto->add_field());
2072 }
2073 for (int i = 0; i < oneof_decl_count(); i++) {
2074 oneof_decl(i)->CopyTo(proto->add_oneof_decl());
2075 }
2076 for (int i = 0; i < nested_type_count(); i++) {
2077 nested_type(i)->CopyTo(proto->add_nested_type());
2078 }
2079 for (int i = 0; i < enum_type_count(); i++) {
2080 enum_type(i)->CopyTo(proto->add_enum_type());
2081 }
2082 for (int i = 0; i < extension_range_count(); i++) {
2083 extension_range(i)->CopyTo(proto->add_extension_range());
2084 }
2085 for (int i = 0; i < extension_count(); i++) {
2086 extension(i)->CopyTo(proto->add_extension());
2087 }
2088 for (int i = 0; i < reserved_range_count(); i++) {
2089 DescriptorProto::ReservedRange* range = proto->add_reserved_range();
2090 range->set_start(reserved_range(i)->start);
2091 range->set_end(reserved_range(i)->end);
2092 }
2093 for (int i = 0; i < reserved_name_count(); i++) {
2094 proto->add_reserved_name(reserved_name(i));
2095 }
2096
2097 if (&options() != &MessageOptions::default_instance()) {
2098 proto->mutable_options()->CopyFrom(options());
2099 }
2100 }
2101
CopyJsonNameTo(DescriptorProto * proto) const2102 void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
2103 if (field_count() != proto->field_size() ||
2104 nested_type_count() != proto->nested_type_size() ||
2105 extension_count() != proto->extension_size()) {
2106 GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2107 return;
2108 }
2109 for (int i = 0; i < field_count(); i++) {
2110 field(i)->CopyJsonNameTo(proto->mutable_field(i));
2111 }
2112 for (int i = 0; i < nested_type_count(); i++) {
2113 nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
2114 }
2115 for (int i = 0; i < extension_count(); i++) {
2116 extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2117 }
2118 }
2119
CopyTo(FieldDescriptorProto * proto) const2120 void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
2121 proto->set_name(name());
2122 proto->set_number(number());
2123 if (has_json_name_) {
2124 proto->set_json_name(json_name());
2125 }
2126
2127 // Some compilers do not allow static_cast directly between two enum types,
2128 // so we must cast to int first.
2129 proto->set_label(static_cast<FieldDescriptorProto::Label>(
2130 implicit_cast<int>(label())));
2131 proto->set_type(static_cast<FieldDescriptorProto::Type>(
2132 implicit_cast<int>(type())));
2133
2134 if (is_extension()) {
2135 if (!containing_type()->is_unqualified_placeholder_) {
2136 proto->set_extendee(".");
2137 }
2138 proto->mutable_extendee()->append(containing_type()->full_name());
2139 }
2140
2141 if (cpp_type() == CPPTYPE_MESSAGE) {
2142 if (message_type()->is_placeholder_) {
2143 // We don't actually know if the type is a message type. It could be
2144 // an enum.
2145 proto->clear_type();
2146 }
2147
2148 if (!message_type()->is_unqualified_placeholder_) {
2149 proto->set_type_name(".");
2150 }
2151 proto->mutable_type_name()->append(message_type()->full_name());
2152 } else if (cpp_type() == CPPTYPE_ENUM) {
2153 if (!enum_type()->is_unqualified_placeholder_) {
2154 proto->set_type_name(".");
2155 }
2156 proto->mutable_type_name()->append(enum_type()->full_name());
2157 }
2158
2159 if (has_default_value()) {
2160 proto->set_default_value(DefaultValueAsString(false));
2161 }
2162
2163 if (containing_oneof() != nullptr && !is_extension()) {
2164 proto->set_oneof_index(containing_oneof()->index());
2165 }
2166
2167 if (&options() != &FieldOptions::default_instance()) {
2168 proto->mutable_options()->CopyFrom(options());
2169 }
2170 }
2171
CopyJsonNameTo(FieldDescriptorProto * proto) const2172 void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2173 proto->set_json_name(json_name());
2174 }
2175
CopyTo(OneofDescriptorProto * proto) const2176 void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2177 proto->set_name(name());
2178 if (&options() != &OneofOptions::default_instance()) {
2179 proto->mutable_options()->CopyFrom(options());
2180 }
2181 }
2182
CopyTo(EnumDescriptorProto * proto) const2183 void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2184 proto->set_name(name());
2185
2186 for (int i = 0; i < value_count(); i++) {
2187 value(i)->CopyTo(proto->add_value());
2188 }
2189 for (int i = 0; i < reserved_range_count(); i++) {
2190 EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range();
2191 range->set_start(reserved_range(i)->start);
2192 range->set_end(reserved_range(i)->end);
2193 }
2194 for (int i = 0; i < reserved_name_count(); i++) {
2195 proto->add_reserved_name(reserved_name(i));
2196 }
2197
2198 if (&options() != &EnumOptions::default_instance()) {
2199 proto->mutable_options()->CopyFrom(options());
2200 }
2201 }
2202
CopyTo(EnumValueDescriptorProto * proto) const2203 void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2204 proto->set_name(name());
2205 proto->set_number(number());
2206
2207 if (&options() != &EnumValueOptions::default_instance()) {
2208 proto->mutable_options()->CopyFrom(options());
2209 }
2210 }
2211
CopyTo(ServiceDescriptorProto * proto) const2212 void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2213 proto->set_name(name());
2214
2215 for (int i = 0; i < method_count(); i++) {
2216 method(i)->CopyTo(proto->add_method());
2217 }
2218
2219 if (&options() != &ServiceOptions::default_instance()) {
2220 proto->mutable_options()->CopyFrom(options());
2221 }
2222 }
2223
CopyTo(MethodDescriptorProto * proto) const2224 void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2225 proto->set_name(name());
2226
2227 if (!input_type()->is_unqualified_placeholder_) {
2228 proto->set_input_type(".");
2229 }
2230 proto->mutable_input_type()->append(input_type()->full_name());
2231
2232 if (!output_type()->is_unqualified_placeholder_) {
2233 proto->set_output_type(".");
2234 }
2235 proto->mutable_output_type()->append(output_type()->full_name());
2236
2237 if (&options() != &MethodOptions::default_instance()) {
2238 proto->mutable_options()->CopyFrom(options());
2239 }
2240
2241 if (client_streaming_) {
2242 proto->set_client_streaming(true);
2243 }
2244 if (server_streaming_) {
2245 proto->set_server_streaming(true);
2246 }
2247 }
2248
2249 // DebugString methods ===============================================
2250
2251 namespace {
2252
RetrieveOptionsAssumingRightPool(int depth,const Message & options,std::vector<std::string> * option_entries)2253 bool RetrieveOptionsAssumingRightPool(
2254 int depth, const Message& options,
2255 std::vector<std::string>* option_entries) {
2256 option_entries->clear();
2257 const Reflection* reflection = options.GetReflection();
2258 std::vector<const FieldDescriptor*> fields;
2259 reflection->ListFields(options, &fields);
2260 for (int i = 0; i < fields.size(); i++) {
2261 int count = 1;
2262 bool repeated = false;
2263 if (fields[i]->is_repeated()) {
2264 count = reflection->FieldSize(options, fields[i]);
2265 repeated = true;
2266 }
2267 for (int j = 0; j < count; j++) {
2268 std::string fieldval;
2269 if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2270 std::string tmp;
2271 TextFormat::Printer printer;
2272 printer.SetInitialIndentLevel(depth + 1);
2273 printer.PrintFieldValueToString(options, fields[i], repeated ? j : -1,
2274 &tmp);
2275 fieldval.append("{\n");
2276 fieldval.append(tmp);
2277 fieldval.append(depth * 2, ' ');
2278 fieldval.append("}");
2279 } else {
2280 TextFormat::PrintFieldValueToString(options, fields[i],
2281 repeated ? j : -1, &fieldval);
2282 }
2283 std::string name;
2284 if (fields[i]->is_extension()) {
2285 name = "(." + fields[i]->full_name() + ")";
2286 } else {
2287 name = fields[i]->name();
2288 }
2289 option_entries->push_back(name + " = " + fieldval);
2290 }
2291 }
2292 return !option_entries->empty();
2293 }
2294
2295 // Used by each of the option formatters.
RetrieveOptions(int depth,const Message & options,const DescriptorPool * pool,std::vector<std::string> * option_entries)2296 bool RetrieveOptions(int depth, const Message& options,
2297 const DescriptorPool* pool,
2298 std::vector<std::string>* option_entries) {
2299 // When printing custom options for a descriptor, we must use an options
2300 // message built on top of the same DescriptorPool where the descriptor
2301 // is coming from. This is to ensure we are interpreting custom options
2302 // against the right pool.
2303 if (options.GetDescriptor()->file()->pool() == pool) {
2304 return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2305 } else {
2306 const Descriptor* option_descriptor =
2307 pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2308 if (option_descriptor == nullptr) {
2309 // descriptor.proto is not in the pool. This means no custom options are
2310 // used so we are safe to proceed with the compiled options message type.
2311 return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2312 }
2313 DynamicMessageFactory factory;
2314 std::unique_ptr<Message> dynamic_options(
2315 factory.GetPrototype(option_descriptor)->New());
2316 if (dynamic_options->ParseFromString(options.SerializeAsString())) {
2317 return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2318 option_entries);
2319 } else {
2320 GOOGLE_LOG(ERROR) << "Found invalid proto option data for: "
2321 << options.GetDescriptor()->full_name();
2322 return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2323 }
2324 }
2325 }
2326
2327 // Formats options that all appear together in brackets. Does not include
2328 // brackets.
FormatBracketedOptions(int depth,const Message & options,const DescriptorPool * pool,std::string * output)2329 bool FormatBracketedOptions(int depth, const Message& options,
2330 const DescriptorPool* pool, std::string* output) {
2331 std::vector<std::string> all_options;
2332 if (RetrieveOptions(depth, options, pool, &all_options)) {
2333 output->append(Join(all_options, ", "));
2334 }
2335 return !all_options.empty();
2336 }
2337
2338 // Formats options one per line
FormatLineOptions(int depth,const Message & options,const DescriptorPool * pool,std::string * output)2339 bool FormatLineOptions(int depth, const Message& options,
2340 const DescriptorPool* pool, std::string* output) {
2341 std::string prefix(depth * 2, ' ');
2342 std::vector<std::string> all_options;
2343 if (RetrieveOptions(depth, options, pool, &all_options)) {
2344 for (int i = 0; i < all_options.size(); i++) {
2345 strings::SubstituteAndAppend(output, "$0option $1;\n", prefix,
2346 all_options[i]);
2347 }
2348 }
2349 return !all_options.empty();
2350 }
2351
2352 class SourceLocationCommentPrinter {
2353 public:
2354 template <typename DescType>
SourceLocationCommentPrinter(const DescType * desc,const std::string & prefix,const DebugStringOptions & options)2355 SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix,
2356 const DebugStringOptions& options)
2357 : options_(options), prefix_(prefix) {
2358 // Perform the SourceLocation lookup only if we're including user comments,
2359 // because the lookup is fairly expensive.
2360 have_source_loc_ =
2361 options.include_comments && desc->GetSourceLocation(&source_loc_);
2362 }
SourceLocationCommentPrinter(const FileDescriptor * file,const std::vector<int> & path,const std::string & prefix,const DebugStringOptions & options)2363 SourceLocationCommentPrinter(const FileDescriptor* file,
2364 const std::vector<int>& path,
2365 const std::string& prefix,
2366 const DebugStringOptions& options)
2367 : options_(options), prefix_(prefix) {
2368 // Perform the SourceLocation lookup only if we're including user comments,
2369 // because the lookup is fairly expensive.
2370 have_source_loc_ =
2371 options.include_comments && file->GetSourceLocation(path, &source_loc_);
2372 }
AddPreComment(std::string * output)2373 void AddPreComment(std::string* output) {
2374 if (have_source_loc_) {
2375 // Detached leading comments.
2376 for (int i = 0; i < source_loc_.leading_detached_comments.size(); ++i) {
2377 *output += FormatComment(source_loc_.leading_detached_comments[i]);
2378 *output += "\n";
2379 }
2380 // Attached leading comments.
2381 if (!source_loc_.leading_comments.empty()) {
2382 *output += FormatComment(source_loc_.leading_comments);
2383 }
2384 }
2385 }
AddPostComment(std::string * output)2386 void AddPostComment(std::string* output) {
2387 if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2388 *output += FormatComment(source_loc_.trailing_comments);
2389 }
2390 }
2391
2392 // Format comment such that each line becomes a full-line C++-style comment in
2393 // the DebugString() output.
FormatComment(const std::string & comment_text)2394 std::string FormatComment(const std::string& comment_text) {
2395 std::string stripped_comment = comment_text;
2396 StripWhitespace(&stripped_comment);
2397 std::vector<std::string> lines = Split(stripped_comment, "\n");
2398 std::string output;
2399 for (int i = 0; i < lines.size(); ++i) {
2400 const std::string& line = lines[i];
2401 strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
2402 }
2403 return output;
2404 }
2405
2406 private:
2407
2408 bool have_source_loc_;
2409 SourceLocation source_loc_;
2410 DebugStringOptions options_;
2411 std::string prefix_;
2412 };
2413
2414 } // anonymous namespace
2415
DebugString() const2416 std::string FileDescriptor::DebugString() const {
2417 DebugStringOptions options; // default options
2418 return DebugStringWithOptions(options);
2419 }
2420
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2421 std::string FileDescriptor::DebugStringWithOptions(
2422 const DebugStringOptions& debug_string_options) const {
2423 std::string contents;
2424 {
2425 std::vector<int> path;
2426 path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
2427 SourceLocationCommentPrinter syntax_comment(this, path, "",
2428 debug_string_options);
2429 syntax_comment.AddPreComment(&contents);
2430 strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
2431 SyntaxName(syntax()));
2432 syntax_comment.AddPostComment(&contents);
2433 }
2434
2435 SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
2436 comment_printer.AddPreComment(&contents);
2437
2438 std::set<int> public_dependencies;
2439 std::set<int> weak_dependencies;
2440 public_dependencies.insert(public_dependencies_,
2441 public_dependencies_ + public_dependency_count_);
2442 weak_dependencies.insert(weak_dependencies_,
2443 weak_dependencies_ + weak_dependency_count_);
2444
2445 for (int i = 0; i < dependency_count(); i++) {
2446 if (public_dependencies.count(i) > 0) {
2447 strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
2448 dependency(i)->name());
2449 } else if (weak_dependencies.count(i) > 0) {
2450 strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
2451 dependency(i)->name());
2452 } else {
2453 strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
2454 dependency(i)->name());
2455 }
2456 }
2457
2458 if (!package().empty()) {
2459 std::vector<int> path;
2460 path.push_back(FileDescriptorProto::kPackageFieldNumber);
2461 SourceLocationCommentPrinter package_comment(this, path, "",
2462 debug_string_options);
2463 package_comment.AddPreComment(&contents);
2464 strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
2465 package_comment.AddPostComment(&contents);
2466 }
2467
2468 if (FormatLineOptions(0, options(), pool(), &contents)) {
2469 contents.append("\n"); // add some space if we had options
2470 }
2471
2472 for (int i = 0; i < enum_type_count(); i++) {
2473 enum_type(i)->DebugString(0, &contents, debug_string_options);
2474 contents.append("\n");
2475 }
2476
2477 // Find all the 'group' type extensions; we will not output their nested
2478 // definitions (those will be done with their group field descriptor).
2479 std::set<const Descriptor*> groups;
2480 for (int i = 0; i < extension_count(); i++) {
2481 if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2482 groups.insert(extension(i)->message_type());
2483 }
2484 }
2485
2486 for (int i = 0; i < message_type_count(); i++) {
2487 if (groups.count(message_type(i)) == 0) {
2488 message_type(i)->DebugString(0, &contents, debug_string_options,
2489 /* include_opening_clause */ true);
2490 contents.append("\n");
2491 }
2492 }
2493
2494 for (int i = 0; i < service_count(); i++) {
2495 service(i)->DebugString(&contents, debug_string_options);
2496 contents.append("\n");
2497 }
2498
2499 const Descriptor* containing_type = nullptr;
2500 for (int i = 0; i < extension_count(); i++) {
2501 if (extension(i)->containing_type() != containing_type) {
2502 if (i > 0) contents.append("}\n\n");
2503 containing_type = extension(i)->containing_type();
2504 strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2505 containing_type->full_name());
2506 }
2507 extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents,
2508 debug_string_options);
2509 }
2510 if (extension_count() > 0) contents.append("}\n\n");
2511
2512 comment_printer.AddPostComment(&contents);
2513
2514 return contents;
2515 }
2516
DebugString() const2517 std::string Descriptor::DebugString() const {
2518 DebugStringOptions options; // default options
2519 return DebugStringWithOptions(options);
2520 }
2521
DebugStringWithOptions(const DebugStringOptions & options) const2522 std::string Descriptor::DebugStringWithOptions(
2523 const DebugStringOptions& options) const {
2524 std::string contents;
2525 DebugString(0, &contents, options, /* include_opening_clause */ true);
2526 return contents;
2527 }
2528
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options,bool include_opening_clause) const2529 void Descriptor::DebugString(int depth, std::string* contents,
2530 const DebugStringOptions& debug_string_options,
2531 bool include_opening_clause) const {
2532 if (options().map_entry()) {
2533 // Do not generate debug string for auto-generated map-entry type.
2534 return;
2535 }
2536 std::string prefix(depth * 2, ' ');
2537 ++depth;
2538
2539 SourceLocationCommentPrinter comment_printer(this, prefix,
2540 debug_string_options);
2541 comment_printer.AddPreComment(contents);
2542
2543 if (include_opening_clause) {
2544 strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
2545 }
2546 contents->append(" {\n");
2547
2548 FormatLineOptions(depth, options(), file()->pool(), contents);
2549
2550 // Find all the 'group' types for fields and extensions; we will not output
2551 // their nested definitions (those will be done with their group field
2552 // descriptor).
2553 std::set<const Descriptor*> groups;
2554 for (int i = 0; i < field_count(); i++) {
2555 if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
2556 groups.insert(field(i)->message_type());
2557 }
2558 }
2559 for (int i = 0; i < extension_count(); i++) {
2560 if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2561 groups.insert(extension(i)->message_type());
2562 }
2563 }
2564
2565 for (int i = 0; i < nested_type_count(); i++) {
2566 if (groups.count(nested_type(i)) == 0) {
2567 nested_type(i)->DebugString(depth, contents, debug_string_options,
2568 /* include_opening_clause */ true);
2569 }
2570 }
2571 for (int i = 0; i < enum_type_count(); i++) {
2572 enum_type(i)->DebugString(depth, contents, debug_string_options);
2573 }
2574 for (int i = 0; i < field_count(); i++) {
2575 if (field(i)->containing_oneof() == nullptr) {
2576 field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents,
2577 debug_string_options);
2578 } else if (field(i)->containing_oneof()->field(0) == field(i)) {
2579 // This is the first field in this oneof, so print the whole oneof.
2580 field(i)->containing_oneof()->DebugString(depth, contents,
2581 debug_string_options);
2582 }
2583 }
2584
2585 for (int i = 0; i < extension_range_count(); i++) {
2586 strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", prefix,
2587 extension_range(i)->start,
2588 extension_range(i)->end - 1);
2589 }
2590
2591 // Group extensions by what they extend, so they can be printed out together.
2592 const Descriptor* containing_type = nullptr;
2593 for (int i = 0; i < extension_count(); i++) {
2594 if (extension(i)->containing_type() != containing_type) {
2595 if (i > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
2596 containing_type = extension(i)->containing_type();
2597 strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", prefix,
2598 containing_type->full_name());
2599 }
2600 extension(i)->DebugString(depth + 1, FieldDescriptor::PRINT_LABEL, contents,
2601 debug_string_options);
2602 }
2603 if (extension_count() > 0)
2604 strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
2605
2606 if (reserved_range_count() > 0) {
2607 strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
2608 for (int i = 0; i < reserved_range_count(); i++) {
2609 const Descriptor::ReservedRange* range = reserved_range(i);
2610 if (range->end == range->start + 1) {
2611 strings::SubstituteAndAppend(contents, "$0, ", range->start);
2612 } else {
2613 strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
2614 range->end - 1);
2615 }
2616 }
2617 contents->replace(contents->size() - 2, 2, ";\n");
2618 }
2619
2620 if (reserved_name_count() > 0) {
2621 strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
2622 for (int i = 0; i < reserved_name_count(); i++) {
2623 strings::SubstituteAndAppend(contents, "\"$0\", ",
2624 CEscape(reserved_name(i)));
2625 }
2626 contents->replace(contents->size() - 2, 2, ";\n");
2627 }
2628
2629 strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2630 comment_printer.AddPostComment(contents);
2631 }
2632
DebugString() const2633 std::string FieldDescriptor::DebugString() const {
2634 DebugStringOptions options; // default options
2635 return DebugStringWithOptions(options);
2636 }
2637
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2638 std::string FieldDescriptor::DebugStringWithOptions(
2639 const DebugStringOptions& debug_string_options) const {
2640 std::string contents;
2641 int depth = 0;
2642 if (is_extension()) {
2643 strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2644 containing_type()->full_name());
2645 depth = 1;
2646 }
2647 DebugString(depth, PRINT_LABEL, &contents, debug_string_options);
2648 if (is_extension()) {
2649 contents.append("}\n");
2650 }
2651 return contents;
2652 }
2653
2654 // The field type string used in FieldDescriptor::DebugString()
FieldTypeNameDebugString() const2655 std::string FieldDescriptor::FieldTypeNameDebugString() const {
2656 switch (type()) {
2657 case TYPE_MESSAGE:
2658 return "." + message_type()->full_name();
2659 case TYPE_ENUM:
2660 return "." + enum_type()->full_name();
2661 default:
2662 return kTypeToName[type()];
2663 }
2664 }
2665
DebugString(int depth,PrintLabelFlag print_label_flag,std::string * contents,const DebugStringOptions & debug_string_options) const2666 void FieldDescriptor::DebugString(
2667 int depth, PrintLabelFlag print_label_flag, std::string* contents,
2668 const DebugStringOptions& debug_string_options) const {
2669 std::string prefix(depth * 2, ' ');
2670 std::string field_type;
2671
2672 // Special case map fields.
2673 if (is_map()) {
2674 strings::SubstituteAndAppend(
2675 &field_type, "map<$0, $1>",
2676 message_type()->field(0)->FieldTypeNameDebugString(),
2677 message_type()->field(1)->FieldTypeNameDebugString());
2678 } else {
2679 field_type = FieldTypeNameDebugString();
2680 }
2681
2682 bool print_label = true;
2683 // Determine whether to omit label:
2684 // 1. For an optional field, omit label if it's in oneof or in proto3.
2685 // 2. For a repeated field, omit label if it's a map.
2686 if (is_optional() && (print_label_flag == OMIT_LABEL ||
2687 file()->syntax() == FileDescriptor::SYNTAX_PROTO3)) {
2688 print_label = false;
2689 } else if (is_map()) {
2690 print_label = false;
2691 }
2692 std::string label;
2693 if (print_label) {
2694 label = kLabelToName[this->label()];
2695 label.push_back(' ');
2696 }
2697
2698 SourceLocationCommentPrinter comment_printer(this, prefix,
2699 debug_string_options);
2700 comment_printer.AddPreComment(contents);
2701
2702 strings::SubstituteAndAppend(
2703 contents, "$0$1$2 $3 = $4", prefix, label, field_type,
2704 type() == TYPE_GROUP ? message_type()->name() : name(), number());
2705
2706 bool bracketed = false;
2707 if (has_default_value()) {
2708 bracketed = true;
2709 strings::SubstituteAndAppend(contents, " [default = $0",
2710 DefaultValueAsString(true));
2711 }
2712 if (has_json_name_) {
2713 if (!bracketed) {
2714 bracketed = true;
2715 contents->append("[");
2716 } else {
2717 contents->append(", ");
2718 }
2719 contents->append("json_name = \"");
2720 contents->append(CEscape(json_name()));
2721 contents->append("\"");
2722 }
2723
2724 std::string formatted_options;
2725 if (FormatBracketedOptions(depth, options(), file()->pool(),
2726 &formatted_options)) {
2727 contents->append(bracketed ? ", " : " [");
2728 bracketed = true;
2729 contents->append(formatted_options);
2730 }
2731
2732 if (bracketed) {
2733 contents->append("]");
2734 }
2735
2736 if (type() == TYPE_GROUP) {
2737 if (debug_string_options.elide_group_body) {
2738 contents->append(" { ... };\n");
2739 } else {
2740 message_type()->DebugString(depth, contents, debug_string_options,
2741 /* include_opening_clause */ false);
2742 }
2743 } else {
2744 contents->append(";\n");
2745 }
2746
2747 comment_printer.AddPostComment(contents);
2748 }
2749
DebugString() const2750 std::string OneofDescriptor::DebugString() const {
2751 DebugStringOptions options; // default values
2752 return DebugStringWithOptions(options);
2753 }
2754
DebugStringWithOptions(const DebugStringOptions & options) const2755 std::string OneofDescriptor::DebugStringWithOptions(
2756 const DebugStringOptions& options) const {
2757 std::string contents;
2758 DebugString(0, &contents, options);
2759 return contents;
2760 }
2761
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2762 void OneofDescriptor::DebugString(
2763 int depth, std::string* contents,
2764 const DebugStringOptions& debug_string_options) const {
2765 std::string prefix(depth * 2, ' ');
2766 ++depth;
2767 SourceLocationCommentPrinter comment_printer(this, prefix,
2768 debug_string_options);
2769 comment_printer.AddPreComment(contents);
2770 strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
2771
2772 FormatLineOptions(depth, options(), containing_type()->file()->pool(),
2773 contents);
2774
2775 if (debug_string_options.elide_oneof_body) {
2776 contents->append(" ... }\n");
2777 } else {
2778 contents->append("\n");
2779 for (int i = 0; i < field_count(); i++) {
2780 field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
2781 debug_string_options);
2782 }
2783 strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2784 }
2785 comment_printer.AddPostComment(contents);
2786 }
2787
DebugString() const2788 std::string EnumDescriptor::DebugString() const {
2789 DebugStringOptions options; // default values
2790 return DebugStringWithOptions(options);
2791 }
2792
DebugStringWithOptions(const DebugStringOptions & options) const2793 std::string EnumDescriptor::DebugStringWithOptions(
2794 const DebugStringOptions& options) const {
2795 std::string contents;
2796 DebugString(0, &contents, options);
2797 return contents;
2798 }
2799
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2800 void EnumDescriptor::DebugString(
2801 int depth, std::string* contents,
2802 const DebugStringOptions& debug_string_options) const {
2803 std::string prefix(depth * 2, ' ');
2804 ++depth;
2805
2806 SourceLocationCommentPrinter comment_printer(this, prefix,
2807 debug_string_options);
2808 comment_printer.AddPreComment(contents);
2809
2810 strings::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
2811
2812 FormatLineOptions(depth, options(), file()->pool(), contents);
2813
2814 for (int i = 0; i < value_count(); i++) {
2815 value(i)->DebugString(depth, contents, debug_string_options);
2816 }
2817
2818 if (reserved_range_count() > 0) {
2819 strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
2820 for (int i = 0; i < reserved_range_count(); i++) {
2821 const EnumDescriptor::ReservedRange* range = reserved_range(i);
2822 if (range->end == range->start) {
2823 strings::SubstituteAndAppend(contents, "$0, ", range->start);
2824 } else {
2825 strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
2826 range->end);
2827 }
2828 }
2829 contents->replace(contents->size() - 2, 2, ";\n");
2830 }
2831
2832 if (reserved_name_count() > 0) {
2833 strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
2834 for (int i = 0; i < reserved_name_count(); i++) {
2835 strings::SubstituteAndAppend(contents, "\"$0\", ",
2836 CEscape(reserved_name(i)));
2837 }
2838 contents->replace(contents->size() - 2, 2, ";\n");
2839 }
2840
2841 strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2842
2843 comment_printer.AddPostComment(contents);
2844 }
2845
DebugString() const2846 std::string EnumValueDescriptor::DebugString() const {
2847 DebugStringOptions options; // default values
2848 return DebugStringWithOptions(options);
2849 }
2850
DebugStringWithOptions(const DebugStringOptions & options) const2851 std::string EnumValueDescriptor::DebugStringWithOptions(
2852 const DebugStringOptions& options) const {
2853 std::string contents;
2854 DebugString(0, &contents, options);
2855 return contents;
2856 }
2857
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2858 void EnumValueDescriptor::DebugString(
2859 int depth, std::string* contents,
2860 const DebugStringOptions& debug_string_options) const {
2861 std::string prefix(depth * 2, ' ');
2862
2863 SourceLocationCommentPrinter comment_printer(this, prefix,
2864 debug_string_options);
2865 comment_printer.AddPreComment(contents);
2866
2867 strings::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
2868
2869 std::string formatted_options;
2870 if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
2871 &formatted_options)) {
2872 strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
2873 }
2874 contents->append(";\n");
2875
2876 comment_printer.AddPostComment(contents);
2877 }
2878
DebugString() const2879 std::string ServiceDescriptor::DebugString() const {
2880 DebugStringOptions options; // default values
2881 return DebugStringWithOptions(options);
2882 }
2883
DebugStringWithOptions(const DebugStringOptions & options) const2884 std::string ServiceDescriptor::DebugStringWithOptions(
2885 const DebugStringOptions& options) const {
2886 std::string contents;
2887 DebugString(&contents, options);
2888 return contents;
2889 }
2890
DebugString(std::string * contents,const DebugStringOptions & debug_string_options) const2891 void ServiceDescriptor::DebugString(
2892 std::string* contents,
2893 const DebugStringOptions& debug_string_options) const {
2894 SourceLocationCommentPrinter comment_printer(this, /* prefix */ "",
2895 debug_string_options);
2896 comment_printer.AddPreComment(contents);
2897
2898 strings::SubstituteAndAppend(contents, "service $0 {\n", name());
2899
2900 FormatLineOptions(1, options(), file()->pool(), contents);
2901
2902 for (int i = 0; i < method_count(); i++) {
2903 method(i)->DebugString(1, contents, debug_string_options);
2904 }
2905
2906 contents->append("}\n");
2907
2908 comment_printer.AddPostComment(contents);
2909 }
2910
DebugString() const2911 std::string MethodDescriptor::DebugString() const {
2912 DebugStringOptions options; // default values
2913 return DebugStringWithOptions(options);
2914 }
2915
DebugStringWithOptions(const DebugStringOptions & options) const2916 std::string MethodDescriptor::DebugStringWithOptions(
2917 const DebugStringOptions& options) const {
2918 std::string contents;
2919 DebugString(0, &contents, options);
2920 return contents;
2921 }
2922
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2923 void MethodDescriptor::DebugString(
2924 int depth, std::string* contents,
2925 const DebugStringOptions& debug_string_options) const {
2926 std::string prefix(depth * 2, ' ');
2927 ++depth;
2928
2929 SourceLocationCommentPrinter comment_printer(this, prefix,
2930 debug_string_options);
2931 comment_printer.AddPreComment(contents);
2932
2933 strings::SubstituteAndAppend(
2934 contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
2935 input_type()->full_name(), output_type()->full_name(),
2936 client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
2937
2938 std::string formatted_options;
2939 if (FormatLineOptions(depth, options(), service()->file()->pool(),
2940 &formatted_options)) {
2941 strings::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
2942 prefix);
2943 } else {
2944 contents->append(";\n");
2945 }
2946
2947 comment_printer.AddPostComment(contents);
2948 }
2949
2950
2951 // Location methods ===============================================
2952
GetSourceLocation(const std::vector<int> & path,SourceLocation * out_location) const2953 bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
2954 SourceLocation* out_location) const {
2955 GOOGLE_CHECK(out_location != nullptr);
2956 if (source_code_info_) {
2957 if (const SourceCodeInfo_Location* loc =
2958 tables_->GetSourceLocation(path, source_code_info_)) {
2959 const RepeatedField<int32>& span = loc->span();
2960 if (span.size() == 3 || span.size() == 4) {
2961 out_location->start_line = span.Get(0);
2962 out_location->start_column = span.Get(1);
2963 out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
2964 out_location->end_column = span.Get(span.size() - 1);
2965
2966 out_location->leading_comments = loc->leading_comments();
2967 out_location->trailing_comments = loc->trailing_comments();
2968 out_location->leading_detached_comments.assign(
2969 loc->leading_detached_comments().begin(),
2970 loc->leading_detached_comments().end());
2971 return true;
2972 }
2973 }
2974 }
2975 return false;
2976 }
2977
GetSourceLocation(SourceLocation * out_location) const2978 bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2979 std::vector<int> path; // empty path for root FileDescriptor
2980 return GetSourceLocation(path, out_location);
2981 }
2982
is_packed() const2983 bool FieldDescriptor::is_packed() const {
2984 if (!is_packable()) return false;
2985 if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
2986 return (options_ != nullptr) && options_->packed();
2987 } else {
2988 return options_ == nullptr || !options_->has_packed() || options_->packed();
2989 }
2990 }
2991
GetSourceLocation(SourceLocation * out_location) const2992 bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
2993 std::vector<int> path;
2994 GetLocationPath(&path);
2995 return file()->GetSourceLocation(path, out_location);
2996 }
2997
GetSourceLocation(SourceLocation * out_location) const2998 bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2999 std::vector<int> path;
3000 GetLocationPath(&path);
3001 return file()->GetSourceLocation(path, out_location);
3002 }
3003
GetSourceLocation(SourceLocation * out_location) const3004 bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3005 std::vector<int> path;
3006 GetLocationPath(&path);
3007 return containing_type()->file()->GetSourceLocation(path, out_location);
3008 }
3009
GetSourceLocation(SourceLocation * out_location) const3010 bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3011 std::vector<int> path;
3012 GetLocationPath(&path);
3013 return file()->GetSourceLocation(path, out_location);
3014 }
3015
GetSourceLocation(SourceLocation * out_location) const3016 bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3017 std::vector<int> path;
3018 GetLocationPath(&path);
3019 return service()->file()->GetSourceLocation(path, out_location);
3020 }
3021
GetSourceLocation(SourceLocation * out_location) const3022 bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3023 std::vector<int> path;
3024 GetLocationPath(&path);
3025 return file()->GetSourceLocation(path, out_location);
3026 }
3027
GetSourceLocation(SourceLocation * out_location) const3028 bool EnumValueDescriptor::GetSourceLocation(
3029 SourceLocation* out_location) const {
3030 std::vector<int> path;
3031 GetLocationPath(&path);
3032 return type()->file()->GetSourceLocation(path, out_location);
3033 }
3034
GetLocationPath(std::vector<int> * output) const3035 void Descriptor::GetLocationPath(std::vector<int>* output) const {
3036 if (containing_type()) {
3037 containing_type()->GetLocationPath(output);
3038 output->push_back(DescriptorProto::kNestedTypeFieldNumber);
3039 output->push_back(index());
3040 } else {
3041 output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
3042 output->push_back(index());
3043 }
3044 }
3045
GetLocationPath(std::vector<int> * output) const3046 void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
3047 if (is_extension()) {
3048 if (extension_scope() == nullptr) {
3049 output->push_back(FileDescriptorProto::kExtensionFieldNumber);
3050 output->push_back(index());
3051 } else {
3052 extension_scope()->GetLocationPath(output);
3053 output->push_back(DescriptorProto::kExtensionFieldNumber);
3054 output->push_back(index());
3055 }
3056 } else {
3057 containing_type()->GetLocationPath(output);
3058 output->push_back(DescriptorProto::kFieldFieldNumber);
3059 output->push_back(index());
3060 }
3061 }
3062
GetLocationPath(std::vector<int> * output) const3063 void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
3064 containing_type()->GetLocationPath(output);
3065 output->push_back(DescriptorProto::kOneofDeclFieldNumber);
3066 output->push_back(index());
3067 }
3068
GetLocationPath(std::vector<int> * output) const3069 void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
3070 if (containing_type()) {
3071 containing_type()->GetLocationPath(output);
3072 output->push_back(DescriptorProto::kEnumTypeFieldNumber);
3073 output->push_back(index());
3074 } else {
3075 output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
3076 output->push_back(index());
3077 }
3078 }
3079
GetLocationPath(std::vector<int> * output) const3080 void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
3081 type()->GetLocationPath(output);
3082 output->push_back(EnumDescriptorProto::kValueFieldNumber);
3083 output->push_back(index());
3084 }
3085
GetLocationPath(std::vector<int> * output) const3086 void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
3087 output->push_back(FileDescriptorProto::kServiceFieldNumber);
3088 output->push_back(index());
3089 }
3090
GetLocationPath(std::vector<int> * output) const3091 void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
3092 service()->GetLocationPath(output);
3093 output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
3094 output->push_back(index());
3095 }
3096
3097 // ===================================================================
3098
3099 namespace {
3100
3101 // Represents an options message to interpret. Extension names in the option
3102 // name are resolved relative to name_scope. element_name and orig_opt are
3103 // used only for error reporting (since the parser records locations against
3104 // pointers in the original options, not the mutable copy). The Message must be
3105 // one of the Options messages in descriptor.proto.
3106 struct OptionsToInterpret {
OptionsToInterpretgoogle::protobuf::__anoneb3ce4ee0511::OptionsToInterpret3107 OptionsToInterpret(const std::string& ns, const std::string& el,
3108 const std::vector<int>& path, const Message* orig_opt,
3109 Message* opt)
3110 : name_scope(ns),
3111 element_name(el),
3112 element_path(path),
3113 original_options(orig_opt),
3114 options(opt) {}
3115 std::string name_scope;
3116 std::string element_name;
3117 std::vector<int> element_path;
3118 const Message* original_options;
3119 Message* options;
3120 };
3121
3122 } // namespace
3123
3124 class DescriptorBuilder {
3125 public:
3126 DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables,
3127 DescriptorPool::ErrorCollector* error_collector);
3128 ~DescriptorBuilder();
3129
3130 const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
3131
3132 private:
3133 friend class OptionInterpreter;
3134
3135 // Non-recursive part of BuildFile functionality.
3136 FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto);
3137
3138 const DescriptorPool* pool_;
3139 DescriptorPool::Tables* tables_; // for convenience
3140 DescriptorPool::ErrorCollector* error_collector_;
3141
3142 // As we build descriptors we store copies of the options messages in
3143 // them. We put pointers to those copies in this vector, as we build, so we
3144 // can later (after cross-linking) interpret those options.
3145 std::vector<OptionsToInterpret> options_to_interpret_;
3146
3147 bool had_errors_;
3148 std::string filename_;
3149 FileDescriptor* file_;
3150 FileDescriptorTables* file_tables_;
3151 std::set<const FileDescriptor*> dependencies_;
3152
3153 // unused_dependency_ is used to record the unused imported files.
3154 // Note: public import is not considered.
3155 std::set<const FileDescriptor*> unused_dependency_;
3156
3157 // If LookupSymbol() finds a symbol that is in a file which is not a declared
3158 // dependency of this file, it will fail, but will set
3159 // possible_undeclared_dependency_ to point at that file. This is only used
3160 // by AddNotDefinedError() to report a more useful error message.
3161 // possible_undeclared_dependency_name_ is the name of the symbol that was
3162 // actually found in possible_undeclared_dependency_, which may be a parent
3163 // of the symbol actually looked for.
3164 const FileDescriptor* possible_undeclared_dependency_;
3165 std::string possible_undeclared_dependency_name_;
3166
3167 // If LookupSymbol() could resolve a symbol which is not defined,
3168 // record the resolved name. This is only used by AddNotDefinedError()
3169 // to report a more useful error message.
3170 std::string undefine_resolved_name_;
3171
3172 void AddError(const std::string& element_name, const Message& descriptor,
3173 DescriptorPool::ErrorCollector::ErrorLocation location,
3174 const std::string& error);
3175 void AddError(const std::string& element_name, const Message& descriptor,
3176 DescriptorPool::ErrorCollector::ErrorLocation location,
3177 const char* error);
3178 void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3179 void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3180 void AddImportError(const FileDescriptorProto& proto, int index);
3181
3182 // Adds an error indicating that undefined_symbol was not defined. Must
3183 // only be called after LookupSymbol() fails.
3184 void AddNotDefinedError(
3185 const std::string& element_name, const Message& descriptor,
3186 DescriptorPool::ErrorCollector::ErrorLocation location,
3187 const std::string& undefined_symbol);
3188
3189 void AddWarning(const std::string& element_name, const Message& descriptor,
3190 DescriptorPool::ErrorCollector::ErrorLocation location,
3191 const std::string& error);
3192
3193 // Silly helper which determines if the given file is in the given package.
3194 // I.e., either file->package() == package_name or file->package() is a
3195 // nested package within package_name.
3196 bool IsInPackage(const FileDescriptor* file, const std::string& package_name);
3197
3198 // Helper function which finds all public dependencies of the given file, and
3199 // stores the them in the dependencies_ set in the builder.
3200 void RecordPublicDependencies(const FileDescriptor* file);
3201
3202 // Like tables_->FindSymbol(), but additionally:
3203 // - Search the pool's underlay if not found in tables_.
3204 // - Insure that the resulting Symbol is from one of the file's declared
3205 // dependencies.
3206 Symbol FindSymbol(const std::string& name, bool build_it = true);
3207
3208 // Like FindSymbol() but does not require that the symbol is in one of the
3209 // file's declared dependencies.
3210 Symbol FindSymbolNotEnforcingDeps(const std::string& name,
3211 bool build_it = true);
3212
3213 // This implements the body of FindSymbolNotEnforcingDeps().
3214 Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3215 const std::string& name,
3216 bool build_it = true);
3217
3218 // Like FindSymbol(), but looks up the name relative to some other symbol
3219 // name. This first searches siblings of relative_to, then siblings of its
3220 // parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
3221 // the following calls, returning the first non-null result:
3222 // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
3223 // FindSymbol("foo.bar"). If AllowUnknownDependencies() has been called
3224 // on the DescriptorPool, this will generate a placeholder type if
3225 // the name is not found (unless the name itself is malformed). The
3226 // placeholder_type parameter indicates what kind of placeholder should be
3227 // constructed in this case. The resolve_mode parameter determines whether
3228 // any symbol is returned, or only symbols that are types. Note, however,
3229 // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3230 // if it believes that's all it could refer to. The caller should always
3231 // check that it receives the type of symbol it was expecting.
3232 enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES };
3233 Symbol LookupSymbol(const std::string& name, const std::string& relative_to,
3234 DescriptorPool::PlaceholderType placeholder_type =
3235 DescriptorPool::PLACEHOLDER_MESSAGE,
3236 ResolveMode resolve_mode = LOOKUP_ALL,
3237 bool build_it = true);
3238
3239 // Like LookupSymbol() but will not return a placeholder even if
3240 // AllowUnknownDependencies() has been used.
3241 Symbol LookupSymbolNoPlaceholder(const std::string& name,
3242 const std::string& relative_to,
3243 ResolveMode resolve_mode = LOOKUP_ALL,
3244 bool build_it = true);
3245
3246 // Calls tables_->AddSymbol() and records an error if it fails. Returns
3247 // true if successful or false if failed, though most callers can ignore
3248 // the return value since an error has already been recorded.
3249 bool AddSymbol(const std::string& full_name, const void* parent,
3250 const std::string& name, const Message& proto, Symbol symbol);
3251
3252 // Like AddSymbol(), but succeeds if the symbol is already defined as long
3253 // as the existing definition is also a package (because it's OK to define
3254 // the same package in two different files). Also adds all parents of the
3255 // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3256 // "foo.bar" and "foo" to the table).
3257 void AddPackage(const std::string& name, const Message& proto,
3258 const FileDescriptor* file);
3259
3260 // Checks that the symbol name contains only alphanumeric characters and
3261 // underscores. Records an error otherwise.
3262 void ValidateSymbolName(const std::string& name, const std::string& full_name,
3263 const Message& proto);
3264
3265 // Used by BUILD_ARRAY macro (below) to avoid having to have the type
3266 // specified as a macro parameter.
3267 template <typename Type>
AllocateArray(int size,Type ** output)3268 inline void AllocateArray(int size, Type** output) {
3269 *output = tables_->AllocateArray<Type>(size);
3270 }
3271
3272 // Allocates a copy of orig_options in tables_ and stores it in the
3273 // descriptor. Remembers its uninterpreted options, to be interpreted
3274 // later. DescriptorT must be one of the Descriptor messages from
3275 // descriptor.proto.
3276 template <class DescriptorT>
3277 void AllocateOptions(const typename DescriptorT::OptionsType& orig_options,
3278 DescriptorT* descriptor, int options_field_tag);
3279 // Specialization for FileOptions.
3280 void AllocateOptions(const FileOptions& orig_options,
3281 FileDescriptor* descriptor);
3282
3283 // Implementation for AllocateOptions(). Don't call this directly.
3284 template <class DescriptorT>
3285 void AllocateOptionsImpl(
3286 const std::string& name_scope, const std::string& element_name,
3287 const typename DescriptorT::OptionsType& orig_options,
3288 DescriptorT* descriptor, const std::vector<int>& options_path);
3289
3290 // Allocate string on the string pool and initialize it to full proto name.
3291 // Full proto name is "scope.proto_name" if scope is non-empty and
3292 // "proto_name" otherwise.
3293 std::string* AllocateNameString(const std::string& scope,
3294 const std::string& proto_name);
3295
3296 // These methods all have the same signature for the sake of the BUILD_ARRAY
3297 // macro, below.
3298 void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
3299 Descriptor* result);
3300 void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3301 const Descriptor* parent, FieldDescriptor* result,
3302 bool is_extension);
BuildField(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result)3303 void BuildField(const FieldDescriptorProto& proto, const Descriptor* parent,
3304 FieldDescriptor* result) {
3305 BuildFieldOrExtension(proto, parent, result, false);
3306 }
BuildExtension(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result)3307 void BuildExtension(const FieldDescriptorProto& proto,
3308 const Descriptor* parent, FieldDescriptor* result) {
3309 BuildFieldOrExtension(proto, parent, result, true);
3310 }
3311 void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3312 const Descriptor* parent,
3313 Descriptor::ExtensionRange* result);
3314 void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
3315 const Descriptor* parent,
3316 Descriptor::ReservedRange* result);
3317 void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto,
3318 const EnumDescriptor* parent,
3319 EnumDescriptor::ReservedRange* result);
3320 void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent,
3321 OneofDescriptor* result);
3322 void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
3323 const EnumDescriptor* result);
3324 void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent,
3325 EnumDescriptor* result);
3326 void BuildEnumValue(const EnumValueDescriptorProto& proto,
3327 const EnumDescriptor* parent,
3328 EnumValueDescriptor* result);
3329 void BuildService(const ServiceDescriptorProto& proto, const void* dummy,
3330 ServiceDescriptor* result);
3331 void BuildMethod(const MethodDescriptorProto& proto,
3332 const ServiceDescriptor* parent, MethodDescriptor* result);
3333
3334 void LogUnusedDependency(const FileDescriptorProto& proto,
3335 const FileDescriptor* result);
3336
3337 // Must be run only after building.
3338 //
3339 // NOTE: Options will not be available during cross-linking, as they
3340 // have not yet been interpreted. Defer any handling of options to the
3341 // Validate*Options methods.
3342 void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
3343 void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
3344 void CrossLinkField(FieldDescriptor* field,
3345 const FieldDescriptorProto& proto);
3346 void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
3347 const DescriptorProto::ExtensionRange& proto);
3348 void CrossLinkEnum(EnumDescriptor* enum_type,
3349 const EnumDescriptorProto& proto);
3350 void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
3351 const EnumValueDescriptorProto& proto);
3352 void CrossLinkService(ServiceDescriptor* service,
3353 const ServiceDescriptorProto& proto);
3354 void CrossLinkMethod(MethodDescriptor* method,
3355 const MethodDescriptorProto& proto);
3356
3357 // Must be run only after cross-linking.
3358 void InterpretOptions();
3359
3360 // A helper class for interpreting options.
3361 class OptionInterpreter {
3362 public:
3363 // Creates an interpreter that operates in the context of the pool of the
3364 // specified builder, which must not be nullptr. We don't take ownership of
3365 // the builder.
3366 explicit OptionInterpreter(DescriptorBuilder* builder);
3367
3368 ~OptionInterpreter();
3369
3370 // Interprets the uninterpreted options in the specified Options message.
3371 // On error, calls AddError() on the underlying builder and returns false.
3372 // Otherwise returns true.
3373 bool InterpretOptions(OptionsToInterpret* options_to_interpret);
3374
3375 // Updates the given source code info by re-writing uninterpreted option
3376 // locations to refer to the corresponding interpreted option.
3377 void UpdateSourceCodeInfo(SourceCodeInfo* info);
3378
3379 class AggregateOptionFinder;
3380
3381 private:
3382 // Interprets uninterpreted_option_ on the specified message, which
3383 // must be the mutable copy of the original options message to which
3384 // uninterpreted_option_ belongs. The given src_path is the source
3385 // location path to the uninterpreted option, and options_path is the
3386 // source location path to the options message. The location paths are
3387 // recorded and then used in UpdateSourceCodeInfo.
3388 bool InterpretSingleOption(Message* options,
3389 const std::vector<int>& src_path,
3390 const std::vector<int>& options_path);
3391
3392 // Adds the uninterpreted_option to the given options message verbatim.
3393 // Used when AllowUnknownDependencies() is in effect and we can't find
3394 // the option's definition.
3395 void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
3396 Message* options);
3397
3398 // A recursive helper function that drills into the intermediate fields
3399 // in unknown_fields to check if field innermost_field is set on the
3400 // innermost message. Returns false and sets an error if so.
3401 bool ExamineIfOptionIsSet(
3402 std::vector<const FieldDescriptor*>::const_iterator
3403 intermediate_fields_iter,
3404 std::vector<const FieldDescriptor*>::const_iterator
3405 intermediate_fields_end,
3406 const FieldDescriptor* innermost_field,
3407 const std::string& debug_msg_name,
3408 const UnknownFieldSet& unknown_fields);
3409
3410 // Validates the value for the option field of the currently interpreted
3411 // option and then sets it on the unknown_field.
3412 bool SetOptionValue(const FieldDescriptor* option_field,
3413 UnknownFieldSet* unknown_fields);
3414
3415 // Parses an aggregate value for a CPPTYPE_MESSAGE option and
3416 // saves it into *unknown_fields.
3417 bool SetAggregateOption(const FieldDescriptor* option_field,
3418 UnknownFieldSet* unknown_fields);
3419
3420 // Convenience functions to set an int field the right way, depending on
3421 // its wire type (a single int CppType can represent multiple wire types).
3422 void SetInt32(int number, int32 value, FieldDescriptor::Type type,
3423 UnknownFieldSet* unknown_fields);
3424 void SetInt64(int number, int64 value, FieldDescriptor::Type type,
3425 UnknownFieldSet* unknown_fields);
3426 void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
3427 UnknownFieldSet* unknown_fields);
3428 void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
3429 UnknownFieldSet* unknown_fields);
3430
3431 // A helper function that adds an error at the specified location of the
3432 // option we're currently interpreting, and returns false.
AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & msg)3433 bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
3434 const std::string& msg) {
3435 builder_->AddError(options_to_interpret_->element_name,
3436 *uninterpreted_option_, location, msg);
3437 return false;
3438 }
3439
3440 // A helper function that adds an error at the location of the option name
3441 // and returns false.
AddNameError(const std::string & msg)3442 bool AddNameError(const std::string& msg) {
3443 return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
3444 }
3445
3446 // A helper function that adds an error at the location of the option name
3447 // and returns false.
AddValueError(const std::string & msg)3448 bool AddValueError(const std::string& msg) {
3449 return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
3450 }
3451
3452 // We interpret against this builder's pool. Is never nullptr. We don't own
3453 // this pointer.
3454 DescriptorBuilder* builder_;
3455
3456 // The options we're currently interpreting, or nullptr if we're not in a
3457 // call to InterpretOptions.
3458 const OptionsToInterpret* options_to_interpret_;
3459
3460 // The option we're currently interpreting within options_to_interpret_, or
3461 // nullptr if we're not in a call to InterpretOptions(). This points to a
3462 // submessage of the original option, not the mutable copy. Therefore we
3463 // can use it to find locations recorded by the parser.
3464 const UninterpretedOption* uninterpreted_option_;
3465
3466 // This maps the element path of uninterpreted options to the element path
3467 // of the resulting interpreted option. This is used to modify a file's
3468 // source code info to account for option interpretation.
3469 std::map<std::vector<int>, std::vector<int>> interpreted_paths_;
3470
3471 // This maps the path to a repeated option field to the known number of
3472 // elements the field contains. This is used to track the compute the
3473 // index portion of the element path when interpreting a single option.
3474 std::map<std::vector<int>, int> repeated_option_counts_;
3475
3476 // Factory used to create the dynamic messages we need to parse
3477 // any aggregate option values we encounter.
3478 DynamicMessageFactory dynamic_factory_;
3479
3480 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
3481 };
3482
3483 // Work-around for broken compilers: According to the C++ standard,
3484 // OptionInterpreter should have access to the private members of any class
3485 // which has declared DescriptorBuilder as a friend. Unfortunately some old
3486 // versions of GCC and other compilers do not implement this correctly. So,
3487 // we have to have these intermediate methods to provide access. We also
3488 // redundantly declare OptionInterpreter a friend just to make things extra
3489 // clear for these bad compilers.
3490 friend class OptionInterpreter;
3491 friend class OptionInterpreter::AggregateOptionFinder;
3492
get_allow_unknown(const DescriptorPool * pool)3493 static inline bool get_allow_unknown(const DescriptorPool* pool) {
3494 return pool->allow_unknown_;
3495 }
get_enforce_weak(const DescriptorPool * pool)3496 static inline bool get_enforce_weak(const DescriptorPool* pool) {
3497 return pool->enforce_weak_;
3498 }
get_is_placeholder(const Descriptor * descriptor)3499 static inline bool get_is_placeholder(const Descriptor* descriptor) {
3500 return descriptor->is_placeholder_;
3501 }
assert_mutex_held(const DescriptorPool * pool)3502 static inline void assert_mutex_held(const DescriptorPool* pool) {
3503 if (pool->mutex_ != nullptr) {
3504 pool->mutex_->AssertHeld();
3505 }
3506 }
3507
3508 // Must be run only after options have been interpreted.
3509 //
3510 // NOTE: Validation code must only reference the options in the mutable
3511 // descriptors, which are the ones that have been interpreted. The const
3512 // proto references are passed in only so they can be provided to calls to
3513 // AddError(). Do not look at their options, which have not been interpreted.
3514 void ValidateFileOptions(FileDescriptor* file,
3515 const FileDescriptorProto& proto);
3516 void ValidateMessageOptions(Descriptor* message,
3517 const DescriptorProto& proto);
3518 void ValidateFieldOptions(FieldDescriptor* field,
3519 const FieldDescriptorProto& proto);
3520 void ValidateEnumOptions(EnumDescriptor* enm,
3521 const EnumDescriptorProto& proto);
3522 void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
3523 const EnumValueDescriptorProto& proto);
3524 void ValidateServiceOptions(ServiceDescriptor* service,
3525 const ServiceDescriptorProto& proto);
3526 void ValidateMethodOptions(MethodDescriptor* method,
3527 const MethodDescriptorProto& proto);
3528 void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto);
3529 void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto);
3530 void ValidateProto3Field(FieldDescriptor* field,
3531 const FieldDescriptorProto& proto);
3532 void ValidateProto3Enum(EnumDescriptor* enm,
3533 const EnumDescriptorProto& proto);
3534
3535 // Returns true if the map entry message is compatible with the
3536 // auto-generated entry message from map fields syntax.
3537 bool ValidateMapEntry(FieldDescriptor* field,
3538 const FieldDescriptorProto& proto);
3539
3540 // Recursively detects naming conflicts with map entry types for a
3541 // better error message.
3542 void DetectMapConflicts(const Descriptor* message,
3543 const DescriptorProto& proto);
3544
3545 void ValidateJSType(FieldDescriptor* field,
3546 const FieldDescriptorProto& proto);
3547 };
3548
BuildFile(const FileDescriptorProto & proto)3549 const FileDescriptor* DescriptorPool::BuildFile(
3550 const FileDescriptorProto& proto) {
3551 GOOGLE_CHECK(fallback_database_ == nullptr)
3552 << "Cannot call BuildFile on a DescriptorPool that uses a "
3553 "DescriptorDatabase. You must instead find a way to get your file "
3554 "into the underlying database.";
3555 GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK.
3556 tables_->known_bad_symbols_.clear();
3557 tables_->known_bad_files_.clear();
3558 return DescriptorBuilder(this, tables_.get(), nullptr).BuildFile(proto);
3559 }
3560
BuildFileCollectingErrors(const FileDescriptorProto & proto,ErrorCollector * error_collector)3561 const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
3562 const FileDescriptorProto& proto, ErrorCollector* error_collector) {
3563 GOOGLE_CHECK(fallback_database_ == nullptr)
3564 << "Cannot call BuildFile on a DescriptorPool that uses a "
3565 "DescriptorDatabase. You must instead find a way to get your file "
3566 "into the underlying database.";
3567 GOOGLE_CHECK(mutex_ == nullptr); // Implied by the above GOOGLE_CHECK.
3568 tables_->known_bad_symbols_.clear();
3569 tables_->known_bad_files_.clear();
3570 return DescriptorBuilder(this, tables_.get(), error_collector)
3571 .BuildFile(proto);
3572 }
3573
BuildFileFromDatabase(const FileDescriptorProto & proto) const3574 const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
3575 const FileDescriptorProto& proto) const {
3576 mutex_->AssertHeld();
3577 if (tables_->known_bad_files_.count(proto.name()) > 0) {
3578 return nullptr;
3579 }
3580 const FileDescriptor* result =
3581 DescriptorBuilder(this, tables_.get(), default_error_collector_)
3582 .BuildFile(proto);
3583 if (result == nullptr) {
3584 tables_->known_bad_files_.insert(proto.name());
3585 }
3586 return result;
3587 }
3588
DescriptorBuilder(const DescriptorPool * pool,DescriptorPool::Tables * tables,DescriptorPool::ErrorCollector * error_collector)3589 DescriptorBuilder::DescriptorBuilder(
3590 const DescriptorPool* pool, DescriptorPool::Tables* tables,
3591 DescriptorPool::ErrorCollector* error_collector)
3592 : pool_(pool),
3593 tables_(tables),
3594 error_collector_(error_collector),
3595 had_errors_(false),
3596 possible_undeclared_dependency_(nullptr),
3597 undefine_resolved_name_("") {}
3598
~DescriptorBuilder()3599 DescriptorBuilder::~DescriptorBuilder() {}
3600
AddError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & error)3601 void DescriptorBuilder::AddError(
3602 const std::string& element_name, const Message& descriptor,
3603 DescriptorPool::ErrorCollector::ErrorLocation location,
3604 const std::string& error) {
3605 if (error_collector_ == nullptr) {
3606 if (!had_errors_) {
3607 GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
3608 << "\":";
3609 }
3610 GOOGLE_LOG(ERROR) << " " << element_name << ": " << error;
3611 } else {
3612 error_collector_->AddError(filename_, element_name, &descriptor, location,
3613 error);
3614 }
3615 had_errors_ = true;
3616 }
3617
AddError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const char * error)3618 void DescriptorBuilder::AddError(
3619 const std::string& element_name, const Message& descriptor,
3620 DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
3621 AddError(element_name, descriptor, location, std::string(error));
3622 }
3623
AddNotDefinedError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & undefined_symbol)3624 void DescriptorBuilder::AddNotDefinedError(
3625 const std::string& element_name, const Message& descriptor,
3626 DescriptorPool::ErrorCollector::ErrorLocation location,
3627 const std::string& undefined_symbol) {
3628 if (possible_undeclared_dependency_ == nullptr &&
3629 undefine_resolved_name_.empty()) {
3630 AddError(element_name, descriptor, location,
3631 "\"" + undefined_symbol + "\" is not defined.");
3632 } else {
3633 if (possible_undeclared_dependency_ != nullptr) {
3634 AddError(element_name, descriptor, location,
3635 "\"" + possible_undeclared_dependency_name_ +
3636 "\" seems to be defined in \"" +
3637 possible_undeclared_dependency_->name() +
3638 "\", which is not "
3639 "imported by \"" +
3640 filename_ +
3641 "\". To use it here, please "
3642 "add the necessary import.");
3643 }
3644 if (!undefine_resolved_name_.empty()) {
3645 AddError(element_name, descriptor, location,
3646 "\"" + undefined_symbol + "\" is resolved to \"" +
3647 undefine_resolved_name_ +
3648 "\", which is not defined. "
3649 "The innermost scope is searched first in name resolution. "
3650 "Consider using a leading '.'(i.e., \"." +
3651 undefined_symbol + "\") to start from the outermost scope.");
3652 }
3653 }
3654 }
3655
AddWarning(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & error)3656 void DescriptorBuilder::AddWarning(
3657 const std::string& element_name, const Message& descriptor,
3658 DescriptorPool::ErrorCollector::ErrorLocation location,
3659 const std::string& error) {
3660 if (error_collector_ == nullptr) {
3661 GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
3662 } else {
3663 error_collector_->AddWarning(filename_, element_name, &descriptor, location,
3664 error);
3665 }
3666 }
3667
IsInPackage(const FileDescriptor * file,const std::string & package_name)3668 bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
3669 const std::string& package_name) {
3670 return HasPrefixString(file->package(), package_name) &&
3671 (file->package().size() == package_name.size() ||
3672 file->package()[package_name.size()] == '.');
3673 }
3674
RecordPublicDependencies(const FileDescriptor * file)3675 void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
3676 if (file == nullptr || !dependencies_.insert(file).second) return;
3677 for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
3678 RecordPublicDependencies(file->public_dependency(i));
3679 }
3680 }
3681
FindSymbolNotEnforcingDepsHelper(const DescriptorPool * pool,const std::string & name,bool build_it)3682 Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
3683 const DescriptorPool* pool, const std::string& name, bool build_it) {
3684 // If we are looking at an underlay, we must lock its mutex_, since we are
3685 // accessing the underlay's tables_ directly.
3686 MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
3687
3688 Symbol result = pool->tables_->FindSymbol(name);
3689 if (result.IsNull() && pool->underlay_ != nullptr) {
3690 // Symbol not found; check the underlay.
3691 result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
3692 }
3693
3694 if (result.IsNull()) {
3695 // With lazily_build_dependencies_, a symbol lookup at cross link time is
3696 // not guaranteed to be successful. In most cases, build_it will be false,
3697 // which intentionally prevents us from building an import until it's
3698 // actually needed. In some cases, like registering an extension, we want
3699 // to build the file containing the symbol, and build_it will be set.
3700 // Also, build_it will be true when !lazily_build_dependencies_, to provide
3701 // better error reporting of missing dependencies.
3702 if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
3703 result = pool->tables_->FindSymbol(name);
3704 }
3705 }
3706
3707 return result;
3708 }
3709
FindSymbolNotEnforcingDeps(const std::string & name,bool build_it)3710 Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
3711 bool build_it) {
3712 return FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
3713 }
3714
FindSymbol(const std::string & name,bool build_it)3715 Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
3716 Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
3717
3718 if (result.IsNull()) return result;
3719
3720 if (!pool_->enforce_dependencies_) {
3721 // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
3722 return result;
3723 }
3724
3725 // Only find symbols which were defined in this file or one of its
3726 // dependencies.
3727 const FileDescriptor* file = result.GetFile();
3728 if (file == file_ || dependencies_.count(file) > 0) {
3729 unused_dependency_.erase(file);
3730 return result;
3731 }
3732
3733 if (result.type == Symbol::PACKAGE) {
3734 // Arg, this is overcomplicated. The symbol is a package name. It could
3735 // be that the package was defined in multiple files. result.GetFile()
3736 // returns the first file we saw that used this package. We've determined
3737 // that that file is not a direct dependency of the file we are currently
3738 // building, but it could be that some other file which *is* a direct
3739 // dependency also defines the same package. We can't really rule out this
3740 // symbol unless none of the dependencies define it.
3741 if (IsInPackage(file_, name)) return result;
3742 for (std::set<const FileDescriptor*>::const_iterator it =
3743 dependencies_.begin();
3744 it != dependencies_.end(); ++it) {
3745 // Note: A dependency may be nullptr if it was not found or had errors.
3746 if (*it != nullptr && IsInPackage(*it, name)) return result;
3747 }
3748 }
3749
3750 possible_undeclared_dependency_ = file;
3751 possible_undeclared_dependency_name_ = name;
3752 return kNullSymbol;
3753 }
3754
LookupSymbolNoPlaceholder(const std::string & name,const std::string & relative_to,ResolveMode resolve_mode,bool build_it)3755 Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
3756 const std::string& name, const std::string& relative_to,
3757 ResolveMode resolve_mode, bool build_it) {
3758 possible_undeclared_dependency_ = nullptr;
3759 undefine_resolved_name_.clear();
3760
3761 if (!name.empty() && name[0] == '.') {
3762 // Fully-qualified name.
3763 return FindSymbol(name.substr(1), build_it);
3764 }
3765
3766 // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
3767 // defined in multiple parent scopes, we only want to find "Bar.baz" in the
3768 // innermost one. E.g., the following should produce an error:
3769 // message Bar { message Baz {} }
3770 // message Foo {
3771 // message Bar {
3772 // }
3773 // optional Bar.Baz baz = 1;
3774 // }
3775 // So, we look for just "Foo" first, then look for "Bar.baz" within it if
3776 // found.
3777 std::string::size_type name_dot_pos = name.find_first_of('.');
3778 std::string first_part_of_name;
3779 if (name_dot_pos == std::string::npos) {
3780 first_part_of_name = name;
3781 } else {
3782 first_part_of_name = name.substr(0, name_dot_pos);
3783 }
3784
3785 std::string scope_to_try(relative_to);
3786
3787 while (true) {
3788 // Chop off the last component of the scope.
3789 std::string::size_type dot_pos = scope_to_try.find_last_of('.');
3790 if (dot_pos == std::string::npos) {
3791 return FindSymbol(name, build_it);
3792 } else {
3793 scope_to_try.erase(dot_pos);
3794 }
3795
3796 // Append ".first_part_of_name" and try to find.
3797 std::string::size_type old_size = scope_to_try.size();
3798 scope_to_try.append(1, '.');
3799 scope_to_try.append(first_part_of_name);
3800 Symbol result = FindSymbol(scope_to_try, build_it);
3801 if (!result.IsNull()) {
3802 if (first_part_of_name.size() < name.size()) {
3803 // name is a compound symbol, of which we only found the first part.
3804 // Now try to look up the rest of it.
3805 if (result.IsAggregate()) {
3806 scope_to_try.append(name, first_part_of_name.size(),
3807 name.size() - first_part_of_name.size());
3808 result = FindSymbol(scope_to_try, build_it);
3809 if (result.IsNull()) {
3810 undefine_resolved_name_ = scope_to_try;
3811 }
3812 return result;
3813 } else {
3814 // We found a symbol but it's not an aggregate. Continue the loop.
3815 }
3816 } else {
3817 if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
3818 // We found a symbol but it's not a type. Continue the loop.
3819 } else {
3820 return result;
3821 }
3822 }
3823 }
3824
3825 // Not found. Remove the name so we can try again.
3826 scope_to_try.erase(old_size);
3827 }
3828 }
3829
LookupSymbol(const std::string & name,const std::string & relative_to,DescriptorPool::PlaceholderType placeholder_type,ResolveMode resolve_mode,bool build_it)3830 Symbol DescriptorBuilder::LookupSymbol(
3831 const std::string& name, const std::string& relative_to,
3832 DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
3833 bool build_it) {
3834 Symbol result =
3835 LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
3836 if (result.IsNull() && pool_->allow_unknown_) {
3837 // Not found, but AllowUnknownDependencies() is enabled. Return a
3838 // placeholder instead.
3839 result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
3840 }
3841 return result;
3842 }
3843
ValidateQualifiedName(const std::string & name)3844 static bool ValidateQualifiedName(const std::string& name) {
3845 bool last_was_period = false;
3846
3847 for (int i = 0; i < name.size(); i++) {
3848 // I don't trust isalnum() due to locales. :(
3849 if (('a' <= name[i] && name[i] <= 'z') ||
3850 ('A' <= name[i] && name[i] <= 'Z') ||
3851 ('0' <= name[i] && name[i] <= '9') || (name[i] == '_')) {
3852 last_was_period = false;
3853 } else if (name[i] == '.') {
3854 if (last_was_period) return false;
3855 last_was_period = true;
3856 } else {
3857 return false;
3858 }
3859 }
3860
3861 return !name.empty() && !last_was_period;
3862 }
3863
NewPlaceholder(const std::string & name,PlaceholderType placeholder_type) const3864 Symbol DescriptorPool::NewPlaceholder(const std::string& name,
3865 PlaceholderType placeholder_type) const {
3866 MutexLockMaybe lock(mutex_);
3867 return NewPlaceholderWithMutexHeld(name, placeholder_type);
3868 }
3869
NewPlaceholderWithMutexHeld(const std::string & name,PlaceholderType placeholder_type) const3870 Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
3871 const std::string& name, PlaceholderType placeholder_type) const {
3872 if (mutex_) {
3873 mutex_->AssertHeld();
3874 }
3875 // Compute names.
3876 const std::string* placeholder_full_name;
3877 const std::string* placeholder_name;
3878 const std::string* placeholder_package;
3879
3880 if (!ValidateQualifiedName(name)) return kNullSymbol;
3881 if (name[0] == '.') {
3882 // Fully-qualified.
3883 placeholder_full_name = tables_->AllocateString(name.substr(1));
3884 } else {
3885 placeholder_full_name = tables_->AllocateString(name);
3886 }
3887
3888 std::string::size_type dotpos = placeholder_full_name->find_last_of('.');
3889 if (dotpos != std::string::npos) {
3890 placeholder_package =
3891 tables_->AllocateString(placeholder_full_name->substr(0, dotpos));
3892 placeholder_name =
3893 tables_->AllocateString(placeholder_full_name->substr(dotpos + 1));
3894 } else {
3895 placeholder_package = &internal::GetEmptyString();
3896 placeholder_name = placeholder_full_name;
3897 }
3898
3899 // Create the placeholders.
3900 FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
3901 *placeholder_full_name + ".placeholder.proto");
3902 placeholder_file->package_ = placeholder_package;
3903
3904 if (placeholder_type == PLACEHOLDER_ENUM) {
3905 placeholder_file->enum_type_count_ = 1;
3906 placeholder_file->enum_types_ = tables_->AllocateArray<EnumDescriptor>(1);
3907
3908 EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
3909 memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum));
3910
3911 placeholder_enum->full_name_ = placeholder_full_name;
3912 placeholder_enum->name_ = placeholder_name;
3913 placeholder_enum->file_ = placeholder_file;
3914 placeholder_enum->options_ = &EnumOptions::default_instance();
3915 placeholder_enum->is_placeholder_ = true;
3916 placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
3917
3918 // Enums must have at least one value.
3919 placeholder_enum->value_count_ = 1;
3920 placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
3921
3922 EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
3923 memset(static_cast<void*>(placeholder_value), 0,
3924 sizeof(*placeholder_value));
3925
3926 placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
3927 // Note that enum value names are siblings of their type, not children.
3928 placeholder_value->full_name_ =
3929 placeholder_package->empty()
3930 ? placeholder_value->name_
3931 : tables_->AllocateString(*placeholder_package +
3932 ".PLACEHOLDER_VALUE");
3933
3934 placeholder_value->number_ = 0;
3935 placeholder_value->type_ = placeholder_enum;
3936 placeholder_value->options_ = &EnumValueOptions::default_instance();
3937
3938 return Symbol(placeholder_enum);
3939 } else {
3940 placeholder_file->message_type_count_ = 1;
3941 placeholder_file->message_types_ = tables_->AllocateArray<Descriptor>(1);
3942
3943 Descriptor* placeholder_message = &placeholder_file->message_types_[0];
3944 memset(static_cast<void*>(placeholder_message), 0,
3945 sizeof(*placeholder_message));
3946
3947 placeholder_message->full_name_ = placeholder_full_name;
3948 placeholder_message->name_ = placeholder_name;
3949 placeholder_message->file_ = placeholder_file;
3950 placeholder_message->options_ = &MessageOptions::default_instance();
3951 placeholder_message->is_placeholder_ = true;
3952 placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
3953
3954 if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
3955 placeholder_message->extension_range_count_ = 1;
3956 placeholder_message->extension_ranges_ =
3957 tables_->AllocateArray<Descriptor::ExtensionRange>(1);
3958 placeholder_message->extension_ranges_->start = 1;
3959 // kMaxNumber + 1 because ExtensionRange::end is exclusive.
3960 placeholder_message->extension_ranges_->end =
3961 FieldDescriptor::kMaxNumber + 1;
3962 }
3963
3964 return Symbol(placeholder_message);
3965 }
3966 }
3967
NewPlaceholderFile(const std::string & name) const3968 FileDescriptor* DescriptorPool::NewPlaceholderFile(
3969 const std::string& name) const {
3970 MutexLockMaybe lock(mutex_);
3971 return NewPlaceholderFileWithMutexHeld(name);
3972 }
3973
NewPlaceholderFileWithMutexHeld(const std::string & name) const3974 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
3975 const std::string& name) const {
3976 if (mutex_) {
3977 mutex_->AssertHeld();
3978 }
3979 FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
3980 memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder));
3981
3982 placeholder->name_ = tables_->AllocateString(name);
3983 placeholder->package_ = &internal::GetEmptyString();
3984 placeholder->pool_ = this;
3985 placeholder->options_ = &FileOptions::default_instance();
3986 placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
3987 placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
3988 placeholder->is_placeholder_ = true;
3989 placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;
3990 placeholder->finished_building_ = true;
3991 // All other fields are zero or nullptr.
3992
3993 return placeholder;
3994 }
3995
AddSymbol(const std::string & full_name,const void * parent,const std::string & name,const Message & proto,Symbol symbol)3996 bool DescriptorBuilder::AddSymbol(const std::string& full_name,
3997 const void* parent, const std::string& name,
3998 const Message& proto, Symbol symbol) {
3999 // If the caller passed nullptr for the parent, the symbol is at file scope.
4000 // Use its file as the parent instead.
4001 if (parent == nullptr) parent = file_;
4002
4003 if (tables_->AddSymbol(full_name, symbol)) {
4004 if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
4005 // This is only possible if there was already an error adding something of
4006 // the same name.
4007 if (!had_errors_) {
4008 GOOGLE_LOG(DFATAL) << "\"" << full_name
4009 << "\" not previously defined in "
4010 "symbols_by_name_, but was defined in "
4011 "symbols_by_parent_; this shouldn't be possible.";
4012 }
4013 return false;
4014 }
4015 return true;
4016 } else {
4017 const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
4018 if (other_file == file_) {
4019 std::string::size_type dot_pos = full_name.find_last_of('.');
4020 if (dot_pos == std::string::npos) {
4021 AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4022 "\"" + full_name + "\" is already defined.");
4023 } else {
4024 AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4025 "\"" + full_name.substr(dot_pos + 1) +
4026 "\" is already defined in \"" +
4027 full_name.substr(0, dot_pos) + "\".");
4028 }
4029 } else {
4030 // Symbol seems to have been defined in a different file.
4031 AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4032 "\"" + full_name + "\" is already defined in file \"" +
4033 other_file->name() + "\".");
4034 }
4035 return false;
4036 }
4037 }
4038
AddPackage(const std::string & name,const Message & proto,const FileDescriptor * file)4039 void DescriptorBuilder::AddPackage(const std::string& name,
4040 const Message& proto,
4041 const FileDescriptor* file) {
4042 if (tables_->AddSymbol(name, Symbol(file))) {
4043 // Success. Also add parent package, if any.
4044 std::string::size_type dot_pos = name.find_last_of('.');
4045 if (dot_pos == std::string::npos) {
4046 // No parents.
4047 ValidateSymbolName(name, name, proto);
4048 } else {
4049 // Has parent.
4050 std::string* parent_name =
4051 tables_->AllocateString(name.substr(0, dot_pos));
4052 AddPackage(*parent_name, proto, file);
4053 ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
4054 }
4055 } else {
4056 Symbol existing_symbol = tables_->FindSymbol(name);
4057 // It's OK to redefine a package.
4058 if (existing_symbol.type != Symbol::PACKAGE) {
4059 // Symbol seems to have been defined in a different file.
4060 AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4061 "\"" + name +
4062 "\" is already defined (as something other than "
4063 "a package) in file \"" +
4064 existing_symbol.GetFile()->name() + "\".");
4065 }
4066 }
4067 }
4068
ValidateSymbolName(const std::string & name,const std::string & full_name,const Message & proto)4069 void DescriptorBuilder::ValidateSymbolName(const std::string& name,
4070 const std::string& full_name,
4071 const Message& proto) {
4072 if (name.empty()) {
4073 AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4074 "Missing name.");
4075 } else {
4076 for (int i = 0; i < name.size(); i++) {
4077 // I don't trust isalnum() due to locales. :(
4078 if ((name[i] < 'a' || 'z' < name[i]) &&
4079 (name[i] < 'A' || 'Z' < name[i]) &&
4080 (name[i] < '0' || '9' < name[i]) && (name[i] != '_')) {
4081 AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4082 "\"" + name + "\" is not a valid identifier.");
4083 }
4084 }
4085 }
4086 }
4087
4088 // -------------------------------------------------------------------
4089
4090 // This generic implementation is good for all descriptors except
4091 // FileDescriptor.
4092 template <class DescriptorT>
AllocateOptions(const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor,int options_field_tag)4093 void DescriptorBuilder::AllocateOptions(
4094 const typename DescriptorT::OptionsType& orig_options,
4095 DescriptorT* descriptor, int options_field_tag) {
4096 std::vector<int> options_path;
4097 descriptor->GetLocationPath(&options_path);
4098 options_path.push_back(options_field_tag);
4099 AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
4100 orig_options, descriptor, options_path);
4101 }
4102
4103 // We specialize for FileDescriptor.
AllocateOptions(const FileOptions & orig_options,FileDescriptor * descriptor)4104 void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
4105 FileDescriptor* descriptor) {
4106 std::vector<int> options_path;
4107 options_path.push_back(FileDescriptorProto::kOptionsFieldNumber);
4108 // We add the dummy token so that LookupSymbol does the right thing.
4109 AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(),
4110 orig_options, descriptor, options_path);
4111 }
4112
4113 template <class DescriptorT>
AllocateOptionsImpl(const std::string & name_scope,const std::string & element_name,const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor,const std::vector<int> & options_path)4114 void DescriptorBuilder::AllocateOptionsImpl(
4115 const std::string& name_scope, const std::string& element_name,
4116 const typename DescriptorT::OptionsType& orig_options,
4117 DescriptorT* descriptor, const std::vector<int>& options_path) {
4118 // We need to use a dummy pointer to work around a bug in older versions of
4119 // GCC. Otherwise, the following two lines could be replaced with:
4120 // typename DescriptorT::OptionsType* options =
4121 // tables_->AllocateMessage<typename DescriptorT::OptionsType>();
4122 typename DescriptorT::OptionsType* const dummy = nullptr;
4123 typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
4124
4125 if (!orig_options.IsInitialized()) {
4126 AddError(name_scope + "." + element_name, orig_options,
4127 DescriptorPool::ErrorCollector::OPTION_NAME,
4128 "Uninterpreted option is missing name or value.");
4129 return;
4130 }
4131
4132 // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4133 // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4134 // reflection based method, which requires the Descriptor. However, we are in
4135 // the middle of building the descriptors, thus the deadlock.
4136 options->ParseFromString(orig_options.SerializeAsString());
4137 descriptor->options_ = options;
4138
4139 // Don't add to options_to_interpret_ unless there were uninterpreted
4140 // options. This not only avoids unnecessary work, but prevents a
4141 // bootstrapping problem when building descriptors for descriptor.proto.
4142 // descriptor.proto does not contain any uninterpreted options, but
4143 // attempting to interpret options anyway will cause
4144 // OptionsType::GetDescriptor() to be called which may then deadlock since
4145 // we're still trying to build it.
4146 if (options->uninterpreted_option_size() > 0) {
4147 options_to_interpret_.push_back(OptionsToInterpret(
4148 name_scope, element_name, options_path, &orig_options, options));
4149 }
4150 }
4151
4152 // A common pattern: We want to convert a repeated field in the descriptor
4153 // to an array of values, calling some method to build each value.
4154 #define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \
4155 OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \
4156 AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \
4157 for (int i = 0; i < INPUT.NAME##_size(); i++) { \
4158 METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \
4159 }
4160
AddRecursiveImportError(const FileDescriptorProto & proto,int from_here)4161 void DescriptorBuilder::AddRecursiveImportError(
4162 const FileDescriptorProto& proto, int from_here) {
4163 std::string error_message("File recursively imports itself: ");
4164 for (int i = from_here; i < tables_->pending_files_.size(); i++) {
4165 error_message.append(tables_->pending_files_[i]);
4166 error_message.append(" -> ");
4167 }
4168 error_message.append(proto.name());
4169
4170 if (from_here < tables_->pending_files_.size() - 1) {
4171 AddError(tables_->pending_files_[from_here + 1], proto,
4172 DescriptorPool::ErrorCollector::IMPORT, error_message);
4173 } else {
4174 AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT,
4175 error_message);
4176 }
4177 }
4178
AddTwiceListedError(const FileDescriptorProto & proto,int index)4179 void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
4180 int index) {
4181 AddError(proto.dependency(index), proto,
4182 DescriptorPool::ErrorCollector::IMPORT,
4183 "Import \"" + proto.dependency(index) + "\" was listed twice.");
4184 }
4185
AddImportError(const FileDescriptorProto & proto,int index)4186 void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
4187 int index) {
4188 std::string message;
4189 if (pool_->fallback_database_ == nullptr) {
4190 message = "Import \"" + proto.dependency(index) + "\" has not been loaded.";
4191 } else {
4192 message = "Import \"" + proto.dependency(index) +
4193 "\" was not found or had errors.";
4194 }
4195 AddError(proto.dependency(index), proto,
4196 DescriptorPool::ErrorCollector::IMPORT, message);
4197 }
4198
ExistingFileMatchesProto(const FileDescriptor * existing_file,const FileDescriptorProto & proto)4199 static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
4200 const FileDescriptorProto& proto) {
4201 FileDescriptorProto existing_proto;
4202 existing_file->CopyTo(&existing_proto);
4203 // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
4204 // syntax="proto2".
4205 if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
4206 proto.has_syntax()) {
4207 existing_proto.set_syntax(
4208 existing_file->SyntaxName(existing_file->syntax()));
4209 }
4210
4211 return existing_proto.SerializeAsString() == proto.SerializeAsString();
4212 }
4213
BuildFile(const FileDescriptorProto & proto)4214 const FileDescriptor* DescriptorBuilder::BuildFile(
4215 const FileDescriptorProto& proto) {
4216 filename_ = proto.name();
4217
4218 // Check if the file already exists and is identical to the one being built.
4219 // Note: This only works if the input is canonical -- that is, it
4220 // fully-qualifies all type names, has no UninterpretedOptions, etc.
4221 // This is fine, because this idempotency "feature" really only exists to
4222 // accommodate one hack in the proto1->proto2 migration layer.
4223 const FileDescriptor* existing_file = tables_->FindFile(filename_);
4224 if (existing_file != nullptr) {
4225 // File already in pool. Compare the existing one to the input.
4226 if (ExistingFileMatchesProto(existing_file, proto)) {
4227 // They're identical. Return the existing descriptor.
4228 return existing_file;
4229 }
4230
4231 // Not a match. The error will be detected and handled later.
4232 }
4233
4234 // Check to see if this file is already on the pending files list.
4235 // TODO(kenton): Allow recursive imports? It may not work with some
4236 // (most?) programming languages. E.g., in C++, a forward declaration
4237 // of a type is not sufficient to allow it to be used even in a
4238 // generated header file due to inlining. This could perhaps be
4239 // worked around using tricks involving inserting #include statements
4240 // mid-file, but that's pretty ugly, and I'm pretty sure there are
4241 // some languages out there that do not allow recursive dependencies
4242 // at all.
4243 for (int i = 0; i < tables_->pending_files_.size(); i++) {
4244 if (tables_->pending_files_[i] == proto.name()) {
4245 AddRecursiveImportError(proto, i);
4246 return nullptr;
4247 }
4248 }
4249
4250 // If we have a fallback_database_, and we aren't doing lazy import building,
4251 // attempt to load all dependencies now, before checkpointing tables_. This
4252 // avoids confusion with recursive checkpoints.
4253 if (!pool_->lazily_build_dependencies_) {
4254 if (pool_->fallback_database_ != nullptr) {
4255 tables_->pending_files_.push_back(proto.name());
4256 for (int i = 0; i < proto.dependency_size(); i++) {
4257 if (tables_->FindFile(proto.dependency(i)) == nullptr &&
4258 (pool_->underlay_ == nullptr ||
4259 pool_->underlay_->FindFileByName(proto.dependency(i)) ==
4260 nullptr)) {
4261 // We don't care what this returns since we'll find out below anyway.
4262 pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
4263 }
4264 }
4265 tables_->pending_files_.pop_back();
4266 }
4267 }
4268
4269 // Checkpoint the tables so that we can roll back if something goes wrong.
4270 tables_->AddCheckpoint();
4271
4272 FileDescriptor* result = BuildFileImpl(proto);
4273
4274 file_tables_->FinalizeTables();
4275 if (result) {
4276 tables_->ClearLastCheckpoint();
4277 result->finished_building_ = true;
4278 } else {
4279 tables_->RollbackToLastCheckpoint();
4280 }
4281
4282 return result;
4283 }
4284
BuildFileImpl(const FileDescriptorProto & proto)4285 FileDescriptor* DescriptorBuilder::BuildFileImpl(
4286 const FileDescriptorProto& proto) {
4287 FileDescriptor* result = tables_->Allocate<FileDescriptor>();
4288 file_ = result;
4289
4290 result->is_placeholder_ = false;
4291 result->finished_building_ = false;
4292 SourceCodeInfo* info = nullptr;
4293 if (proto.has_source_code_info()) {
4294 info = tables_->AllocateMessage<SourceCodeInfo>();
4295 info->CopyFrom(proto.source_code_info());
4296 result->source_code_info_ = info;
4297 } else {
4298 result->source_code_info_ = &SourceCodeInfo::default_instance();
4299 }
4300
4301 file_tables_ = tables_->AllocateFileTables();
4302 file_->tables_ = file_tables_;
4303
4304 if (!proto.has_name()) {
4305 AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
4306 "Missing field: FileDescriptorProto.name.");
4307 }
4308
4309 // TODO(liujisi): Report error when the syntax is empty after all the protos
4310 // have added the syntax statement.
4311 if (proto.syntax().empty() || proto.syntax() == "proto2") {
4312 file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
4313 } else if (proto.syntax() == "proto3") {
4314 file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
4315 } else {
4316 file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
4317 AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4318 "Unrecognized syntax: " + proto.syntax());
4319 }
4320
4321 result->name_ = tables_->AllocateString(proto.name());
4322 if (proto.has_package()) {
4323 result->package_ = tables_->AllocateString(proto.package());
4324 } else {
4325 // We cannot rely on proto.package() returning a valid string if
4326 // proto.has_package() is false, because we might be running at static
4327 // initialization time, in which case default values have not yet been
4328 // initialized.
4329 result->package_ = tables_->AllocateString("");
4330 }
4331 result->pool_ = pool_;
4332
4333 // Add to tables.
4334 if (!tables_->AddFile(result)) {
4335 AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4336 "A file with this name is already in the pool.");
4337 // Bail out early so that if this is actually the exact same file, we
4338 // don't end up reporting that every single symbol is already defined.
4339 return nullptr;
4340 }
4341 if (!result->package().empty()) {
4342 AddPackage(result->package(), proto, result);
4343 }
4344
4345 // Make sure all dependencies are loaded.
4346 std::set<std::string> seen_dependencies;
4347 result->dependency_count_ = proto.dependency_size();
4348 result->dependencies_ =
4349 tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
4350 if (pool_->lazily_build_dependencies_) {
4351 result->dependencies_once_ = tables_->AllocateOnceDynamic();
4352 result->dependencies_names_ =
4353 tables_->AllocateArray<const std::string*>(proto.dependency_size());
4354 if (proto.dependency_size() > 0) {
4355 memset(result->dependencies_names_, 0,
4356 sizeof(*result->dependencies_names_) * proto.dependency_size());
4357 }
4358 } else {
4359 result->dependencies_once_ = nullptr;
4360 result->dependencies_names_ = nullptr;
4361 }
4362 unused_dependency_.clear();
4363 std::set<int> weak_deps;
4364 for (int i = 0; i < proto.weak_dependency_size(); ++i) {
4365 weak_deps.insert(proto.weak_dependency(i));
4366 }
4367 for (int i = 0; i < proto.dependency_size(); i++) {
4368 if (!seen_dependencies.insert(proto.dependency(i)).second) {
4369 AddTwiceListedError(proto, i);
4370 }
4371
4372 const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
4373 if (dependency == nullptr && pool_->underlay_ != nullptr) {
4374 dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
4375 }
4376
4377 if (dependency == result) {
4378 // Recursive import. dependency/result is not fully initialized, and it's
4379 // dangerous to try to do anything with it. The recursive import error
4380 // will be detected and reported in DescriptorBuilder::BuildFile().
4381 return nullptr;
4382 }
4383
4384 if (dependency == nullptr) {
4385 if (!pool_->lazily_build_dependencies_) {
4386 if (pool_->allow_unknown_ ||
4387 (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
4388 dependency =
4389 pool_->NewPlaceholderFileWithMutexHeld(proto.dependency(i));
4390 } else {
4391 AddImportError(proto, i);
4392 }
4393 }
4394 } else {
4395 // Add to unused_dependency_ to track unused imported files.
4396 // Note: do not track unused imported files for public import.
4397 if (pool_->enforce_dependencies_ &&
4398 (pool_->unused_import_track_files_.find(proto.name()) !=
4399 pool_->unused_import_track_files_.end()) &&
4400 (dependency->public_dependency_count() == 0)) {
4401 unused_dependency_.insert(dependency);
4402 }
4403 }
4404
4405 result->dependencies_[i] = dependency;
4406 if (pool_->lazily_build_dependencies_ && !dependency) {
4407 result->dependencies_names_[i] =
4408 tables_->AllocateString(proto.dependency(i));
4409 }
4410 }
4411
4412 // Check public dependencies.
4413 int public_dependency_count = 0;
4414 result->public_dependencies_ =
4415 tables_->AllocateArray<int>(proto.public_dependency_size());
4416 for (int i = 0; i < proto.public_dependency_size(); i++) {
4417 // Only put valid public dependency indexes.
4418 int index = proto.public_dependency(i);
4419 if (index >= 0 && index < proto.dependency_size()) {
4420 result->public_dependencies_[public_dependency_count++] = index;
4421 // Do not track unused imported files for public import.
4422 // Calling dependency(i) builds that file when doing lazy imports,
4423 // need to avoid doing this. Unused dependency detection isn't done
4424 // when building lazily, anyways.
4425 if (!pool_->lazily_build_dependencies_) {
4426 unused_dependency_.erase(result->dependency(index));
4427 }
4428 } else {
4429 AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4430 "Invalid public dependency index.");
4431 }
4432 }
4433 result->public_dependency_count_ = public_dependency_count;
4434
4435 // Build dependency set
4436 dependencies_.clear();
4437 // We don't/can't do proper dependency error checking when
4438 // lazily_build_dependencies_, and calling dependency(i) will force
4439 // a dependency to be built, which we don't want.
4440 if (!pool_->lazily_build_dependencies_) {
4441 for (int i = 0; i < result->dependency_count(); i++) {
4442 RecordPublicDependencies(result->dependency(i));
4443 }
4444 }
4445
4446 // Check weak dependencies.
4447 int weak_dependency_count = 0;
4448 result->weak_dependencies_ =
4449 tables_->AllocateArray<int>(proto.weak_dependency_size());
4450 for (int i = 0; i < proto.weak_dependency_size(); i++) {
4451 int index = proto.weak_dependency(i);
4452 if (index >= 0 && index < proto.dependency_size()) {
4453 result->weak_dependencies_[weak_dependency_count++] = index;
4454 } else {
4455 AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4456 "Invalid weak dependency index.");
4457 }
4458 }
4459 result->weak_dependency_count_ = weak_dependency_count;
4460
4461 // Convert children.
4462 BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
4463 BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
4464 BUILD_ARRAY(proto, result, service, BuildService, nullptr);
4465 BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
4466
4467 // Copy options.
4468 if (!proto.has_options()) {
4469 result->options_ = nullptr; // Will set to default_instance later.
4470 } else {
4471 AllocateOptions(proto.options(), result);
4472 }
4473
4474 // Note that the following steps must occur in exactly the specified order.
4475
4476 // Cross-link.
4477 CrossLinkFile(result, proto);
4478
4479 // Interpret any remaining uninterpreted options gathered into
4480 // options_to_interpret_ during descriptor building. Cross-linking has made
4481 // extension options known, so all interpretations should now succeed.
4482 if (!had_errors_) {
4483 OptionInterpreter option_interpreter(this);
4484 for (std::vector<OptionsToInterpret>::iterator iter =
4485 options_to_interpret_.begin();
4486 iter != options_to_interpret_.end(); ++iter) {
4487 option_interpreter.InterpretOptions(&(*iter));
4488 }
4489 options_to_interpret_.clear();
4490 if (info != nullptr) {
4491 option_interpreter.UpdateSourceCodeInfo(info);
4492 }
4493 }
4494
4495 // Validate options. See comments at InternalSetLazilyBuildDependencies about
4496 // error checking and lazy import building.
4497 if (!had_errors_ && !pool_->lazily_build_dependencies_) {
4498 ValidateFileOptions(result, proto);
4499 }
4500
4501 // Additional naming conflict check for map entry types. Only need to check
4502 // this if there are already errors.
4503 if (had_errors_) {
4504 for (int i = 0; i < proto.message_type_size(); ++i) {
4505 DetectMapConflicts(result->message_type(i), proto.message_type(i));
4506 }
4507 }
4508
4509
4510 // Again, see comments at InternalSetLazilyBuildDependencies about error
4511 // checking.
4512 if (!unused_dependency_.empty() && !pool_->lazily_build_dependencies_) {
4513 LogUnusedDependency(proto, result);
4514 }
4515
4516 if (had_errors_) {
4517 return nullptr;
4518 } else {
4519 return result;
4520 }
4521 }
4522
4523
AllocateNameString(const std::string & scope,const std::string & proto_name)4524 std::string* DescriptorBuilder::AllocateNameString(
4525 const std::string& scope, const std::string& proto_name) {
4526 std::string* full_name;
4527 if (scope.empty()) {
4528 full_name = tables_->AllocateString(proto_name);
4529 } else {
4530 full_name = tables_->AllocateEmptyString();
4531 *full_name = StrCat(scope, ".", proto_name);
4532 }
4533 return full_name;
4534 }
4535
BuildMessage(const DescriptorProto & proto,const Descriptor * parent,Descriptor * result)4536 void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
4537 const Descriptor* parent,
4538 Descriptor* result) {
4539 const std::string& scope =
4540 (parent == nullptr) ? file_->package() : parent->full_name();
4541 std::string* full_name = AllocateNameString(scope, proto.name());
4542 ValidateSymbolName(proto.name(), *full_name, proto);
4543
4544 result->name_ = tables_->AllocateString(proto.name());
4545 result->full_name_ = full_name;
4546 result->file_ = file_;
4547 result->containing_type_ = parent;
4548 result->is_placeholder_ = false;
4549 result->is_unqualified_placeholder_ = false;
4550
4551 // Build oneofs first so that fields and extension ranges can refer to them.
4552 BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
4553 BUILD_ARRAY(proto, result, field, BuildField, result);
4554 BUILD_ARRAY(proto, result, nested_type, BuildMessage, result);
4555 BUILD_ARRAY(proto, result, enum_type, BuildEnum, result);
4556 BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
4557 BUILD_ARRAY(proto, result, extension, BuildExtension, result);
4558 BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
4559
4560 // Copy reserved names.
4561 int reserved_name_count = proto.reserved_name_size();
4562 result->reserved_name_count_ = reserved_name_count;
4563 result->reserved_names_ =
4564 tables_->AllocateArray<const std::string*>(reserved_name_count);
4565 for (int i = 0; i < reserved_name_count; ++i) {
4566 result->reserved_names_[i] =
4567 tables_->AllocateString(proto.reserved_name(i));
4568 }
4569
4570 // Copy options.
4571 if (!proto.has_options()) {
4572 result->options_ = nullptr; // Will set to default_instance later.
4573 } else {
4574 AllocateOptions(proto.options(), result,
4575 DescriptorProto::kOptionsFieldNumber);
4576 }
4577
4578 AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
4579
4580
4581 for (int i = 0; i < proto.reserved_range_size(); i++) {
4582 const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
4583 for (int j = i + 1; j < proto.reserved_range_size(); j++) {
4584 const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
4585 if (range1.end() > range2.start() && range2.end() > range1.start()) {
4586 AddError(result->full_name(), proto.reserved_range(i),
4587 DescriptorPool::ErrorCollector::NUMBER,
4588 strings::Substitute("Reserved range $0 to $1 overlaps with "
4589 "already-defined range $2 to $3.",
4590 range2.start(), range2.end() - 1,
4591 range1.start(), range1.end() - 1));
4592 }
4593 }
4594 }
4595
4596 HASH_SET<std::string> reserved_name_set;
4597 for (int i = 0; i < proto.reserved_name_size(); i++) {
4598 const std::string& name = proto.reserved_name(i);
4599 if (reserved_name_set.find(name) == reserved_name_set.end()) {
4600 reserved_name_set.insert(name);
4601 } else {
4602 AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4603 strings::Substitute(
4604 "Field name \"$0\" is reserved multiple times.", name));
4605 }
4606 }
4607
4608 for (int i = 0; i < result->field_count(); i++) {
4609 const FieldDescriptor* field = result->field(i);
4610 for (int j = 0; j < result->extension_range_count(); j++) {
4611 const Descriptor::ExtensionRange* range = result->extension_range(j);
4612 if (range->start <= field->number() && field->number() < range->end) {
4613 AddError(
4614 field->full_name(), proto.extension_range(j),
4615 DescriptorPool::ErrorCollector::NUMBER,
4616 strings::Substitute(
4617 "Extension range $0 to $1 includes field \"$2\" ($3).",
4618 range->start, range->end - 1, field->name(), field->number()));
4619 }
4620 }
4621 for (int j = 0; j < result->reserved_range_count(); j++) {
4622 const Descriptor::ReservedRange* range = result->reserved_range(j);
4623 if (range->start <= field->number() && field->number() < range->end) {
4624 AddError(field->full_name(), proto.reserved_range(j),
4625 DescriptorPool::ErrorCollector::NUMBER,
4626 strings::Substitute("Field \"$0\" uses reserved number $1.",
4627 field->name(), field->number()));
4628 }
4629 }
4630 if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
4631 AddError(
4632 field->full_name(), proto.field(i),
4633 DescriptorPool::ErrorCollector::NAME,
4634 strings::Substitute("Field name \"$0\" is reserved.", field->name()));
4635 }
4636 }
4637
4638 // Check that extension ranges don't overlap and don't include
4639 // reserved field numbers.
4640 for (int i = 0; i < result->extension_range_count(); i++) {
4641 const Descriptor::ExtensionRange* range1 = result->extension_range(i);
4642 for (int j = 0; j < result->reserved_range_count(); j++) {
4643 const Descriptor::ReservedRange* range2 = result->reserved_range(j);
4644 if (range1->end > range2->start && range2->end > range1->start) {
4645 AddError(result->full_name(), proto.extension_range(i),
4646 DescriptorPool::ErrorCollector::NUMBER,
4647 strings::Substitute("Extension range $0 to $1 overlaps with "
4648 "reserved range $2 to $3.",
4649 range1->start, range1->end - 1,
4650 range2->start, range2->end - 1));
4651 }
4652 }
4653 for (int j = i + 1; j < result->extension_range_count(); j++) {
4654 const Descriptor::ExtensionRange* range2 = result->extension_range(j);
4655 if (range1->end > range2->start && range2->end > range1->start) {
4656 AddError(result->full_name(), proto.extension_range(i),
4657 DescriptorPool::ErrorCollector::NUMBER,
4658 strings::Substitute("Extension range $0 to $1 overlaps with "
4659 "already-defined range $2 to $3.",
4660 range2->start, range2->end - 1,
4661 range1->start, range1->end - 1));
4662 }
4663 }
4664 }
4665 }
4666
BuildFieldOrExtension(const FieldDescriptorProto & proto,const Descriptor * parent,FieldDescriptor * result,bool is_extension)4667 void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
4668 const Descriptor* parent,
4669 FieldDescriptor* result,
4670 bool is_extension) {
4671 const std::string& scope =
4672 (parent == nullptr) ? file_->package() : parent->full_name();
4673 std::string* full_name = AllocateNameString(scope, proto.name());
4674 ValidateSymbolName(proto.name(), *full_name, proto);
4675
4676 result->name_ = tables_->AllocateString(proto.name());
4677 result->full_name_ = full_name;
4678 result->file_ = file_;
4679 result->number_ = proto.number();
4680 result->is_extension_ = is_extension;
4681
4682 // If .proto files follow the style guide then the name should already be
4683 // lower-cased. If that's the case we can just reuse the string we
4684 // already allocated rather than allocate a new one.
4685 std::string lowercase_name(proto.name());
4686 LowerString(&lowercase_name);
4687 if (lowercase_name == proto.name()) {
4688 result->lowercase_name_ = result->name_;
4689 } else {
4690 result->lowercase_name_ = tables_->AllocateString(lowercase_name);
4691 }
4692
4693 // Don't bother with the above optimization for camel-case names since
4694 // .proto files that follow the guide shouldn't be using names in this
4695 // format, so the optimization wouldn't help much.
4696 result->camelcase_name_ =
4697 tables_->AllocateString(ToCamelCase(proto.name(),
4698 /* lower_first = */ true));
4699
4700 if (proto.has_json_name()) {
4701 result->has_json_name_ = true;
4702 result->json_name_ = tables_->AllocateString(proto.json_name());
4703 } else {
4704 result->has_json_name_ = false;
4705 result->json_name_ = tables_->AllocateString(ToJsonName(proto.name()));
4706 }
4707
4708 // Some compilers do not allow static_cast directly between two enum types,
4709 // so we must cast to int first.
4710 result->type_ = static_cast<FieldDescriptor::Type>(
4711 implicit_cast<int>(proto.type()));
4712 result->label_ = static_cast<FieldDescriptor::Label>(
4713 implicit_cast<int>(proto.label()));
4714
4715 // An extension cannot have a required field (b/13365836).
4716 if (result->is_extension_ &&
4717 result->label_ == FieldDescriptor::LABEL_REQUIRED) {
4718 AddError(result->full_name(), proto,
4719 // Error location `TYPE`: we would really like to indicate
4720 // `LABEL`, but the `ErrorLocation` enum has no entry for this, and
4721 // we don't necessarily know about all implementations of the
4722 // `ErrorCollector` interface to extend them to handle the new
4723 // error location type properly.
4724 DescriptorPool::ErrorCollector::TYPE,
4725 "Message extensions cannot have required fields.");
4726 }
4727
4728 // Some of these may be filled in when cross-linking.
4729 result->containing_type_ = nullptr;
4730 result->extension_scope_ = nullptr;
4731 result->message_type_ = nullptr;
4732 result->enum_type_ = nullptr;
4733 result->type_name_ = nullptr;
4734 result->type_once_ = nullptr;
4735 result->default_value_enum_ = nullptr;
4736 result->default_value_enum_name_ = nullptr;
4737
4738 result->has_default_value_ = proto.has_default_value();
4739 if (proto.has_default_value() && result->is_repeated()) {
4740 AddError(result->full_name(), proto,
4741 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4742 "Repeated fields can't have default values.");
4743 }
4744
4745 if (proto.has_type()) {
4746 if (proto.has_default_value()) {
4747 char* end_pos = nullptr;
4748 switch (result->cpp_type()) {
4749 case FieldDescriptor::CPPTYPE_INT32:
4750 result->default_value_int32_ =
4751 strtol(proto.default_value().c_str(), &end_pos, 0);
4752 break;
4753 case FieldDescriptor::CPPTYPE_INT64:
4754 result->default_value_int64_ =
4755 strto64(proto.default_value().c_str(), &end_pos, 0);
4756 break;
4757 case FieldDescriptor::CPPTYPE_UINT32:
4758 result->default_value_uint32_ =
4759 strtoul(proto.default_value().c_str(), &end_pos, 0);
4760 break;
4761 case FieldDescriptor::CPPTYPE_UINT64:
4762 result->default_value_uint64_ =
4763 strtou64(proto.default_value().c_str(), &end_pos, 0);
4764 break;
4765 case FieldDescriptor::CPPTYPE_FLOAT:
4766 if (proto.default_value() == "inf") {
4767 result->default_value_float_ =
4768 std::numeric_limits<float>::infinity();
4769 } else if (proto.default_value() == "-inf") {
4770 result->default_value_float_ =
4771 -std::numeric_limits<float>::infinity();
4772 } else if (proto.default_value() == "nan") {
4773 result->default_value_float_ =
4774 std::numeric_limits<float>::quiet_NaN();
4775 } else {
4776 result->default_value_float_ = io::SafeDoubleToFloat(
4777 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
4778 }
4779 break;
4780 case FieldDescriptor::CPPTYPE_DOUBLE:
4781 if (proto.default_value() == "inf") {
4782 result->default_value_double_ =
4783 std::numeric_limits<double>::infinity();
4784 } else if (proto.default_value() == "-inf") {
4785 result->default_value_double_ =
4786 -std::numeric_limits<double>::infinity();
4787 } else if (proto.default_value() == "nan") {
4788 result->default_value_double_ =
4789 std::numeric_limits<double>::quiet_NaN();
4790 } else {
4791 result->default_value_double_ =
4792 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
4793 }
4794 break;
4795 case FieldDescriptor::CPPTYPE_BOOL:
4796 if (proto.default_value() == "true") {
4797 result->default_value_bool_ = true;
4798 } else if (proto.default_value() == "false") {
4799 result->default_value_bool_ = false;
4800 } else {
4801 AddError(result->full_name(), proto,
4802 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4803 "Boolean default must be true or false.");
4804 }
4805 break;
4806 case FieldDescriptor::CPPTYPE_ENUM:
4807 // This will be filled in when cross-linking.
4808 result->default_value_enum_ = nullptr;
4809 break;
4810 case FieldDescriptor::CPPTYPE_STRING:
4811 if (result->type() == FieldDescriptor::TYPE_BYTES) {
4812 result->default_value_string_ = tables_->AllocateString(
4813 UnescapeCEscapeString(proto.default_value()));
4814 } else {
4815 result->default_value_string_ =
4816 tables_->AllocateString(proto.default_value());
4817 }
4818 break;
4819 case FieldDescriptor::CPPTYPE_MESSAGE:
4820 AddError(result->full_name(), proto,
4821 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4822 "Messages can't have default values.");
4823 result->has_default_value_ = false;
4824 break;
4825 }
4826
4827 if (end_pos != nullptr) {
4828 // end_pos is only set non-null by the parsers for numeric types,
4829 // above. This checks that the default was non-empty and had no extra
4830 // junk after the end of the number.
4831 if (proto.default_value().empty() || *end_pos != '\0') {
4832 AddError(result->full_name(), proto,
4833 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4834 "Couldn't parse default value \"" + proto.default_value() +
4835 "\".");
4836 }
4837 }
4838 } else {
4839 // No explicit default value
4840 switch (result->cpp_type()) {
4841 case FieldDescriptor::CPPTYPE_INT32:
4842 result->default_value_int32_ = 0;
4843 break;
4844 case FieldDescriptor::CPPTYPE_INT64:
4845 result->default_value_int64_ = 0;
4846 break;
4847 case FieldDescriptor::CPPTYPE_UINT32:
4848 result->default_value_uint32_ = 0;
4849 break;
4850 case FieldDescriptor::CPPTYPE_UINT64:
4851 result->default_value_uint64_ = 0;
4852 break;
4853 case FieldDescriptor::CPPTYPE_FLOAT:
4854 result->default_value_float_ = 0.0f;
4855 break;
4856 case FieldDescriptor::CPPTYPE_DOUBLE:
4857 result->default_value_double_ = 0.0;
4858 break;
4859 case FieldDescriptor::CPPTYPE_BOOL:
4860 result->default_value_bool_ = false;
4861 break;
4862 case FieldDescriptor::CPPTYPE_ENUM:
4863 // This will be filled in when cross-linking.
4864 result->default_value_enum_ = nullptr;
4865 break;
4866 case FieldDescriptor::CPPTYPE_STRING:
4867 result->default_value_string_ = &internal::GetEmptyString();
4868 break;
4869 case FieldDescriptor::CPPTYPE_MESSAGE:
4870 break;
4871 }
4872 }
4873 }
4874
4875 if (result->number() <= 0) {
4876 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4877 "Field numbers must be positive integers.");
4878 } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
4879 // Only validate that the number is within the valid field range if it is
4880 // not an extension. Since extension numbers are validated with the
4881 // extendee's valid set of extension numbers, and those are in turn
4882 // validated against the max allowed number, the check is unnecessary for
4883 // extension fields.
4884 // This avoids cross-linking issues that arise when attempting to check if
4885 // the extendee is a message_set_wire_format message, which has a higher max
4886 // on extension numbers.
4887 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4888 strings::Substitute("Field numbers cannot be greater than $0.",
4889 FieldDescriptor::kMaxNumber));
4890 } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
4891 result->number() <= FieldDescriptor::kLastReservedNumber) {
4892 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4893 strings::Substitute(
4894 "Field numbers $0 through $1 are reserved for the protocol "
4895 "buffer library implementation.",
4896 FieldDescriptor::kFirstReservedNumber,
4897 FieldDescriptor::kLastReservedNumber));
4898 }
4899
4900 if (is_extension) {
4901 if (!proto.has_extendee()) {
4902 AddError(result->full_name(), proto,
4903 DescriptorPool::ErrorCollector::EXTENDEE,
4904 "FieldDescriptorProto.extendee not set for extension field.");
4905 }
4906
4907 result->extension_scope_ = parent;
4908
4909 if (proto.has_oneof_index()) {
4910 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
4911 "FieldDescriptorProto.oneof_index should not be set for "
4912 "extensions.");
4913 }
4914
4915 // Fill in later (maybe).
4916 result->containing_oneof_ = nullptr;
4917 } else {
4918 if (proto.has_extendee()) {
4919 AddError(result->full_name(), proto,
4920 DescriptorPool::ErrorCollector::EXTENDEE,
4921 "FieldDescriptorProto.extendee set for non-extension field.");
4922 }
4923
4924 result->containing_type_ = parent;
4925
4926 if (proto.has_oneof_index()) {
4927 if (proto.oneof_index() < 0 ||
4928 proto.oneof_index() >= parent->oneof_decl_count()) {
4929 AddError(result->full_name(), proto,
4930 DescriptorPool::ErrorCollector::TYPE,
4931 strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
4932 "out of range for type \"$1\".",
4933 proto.oneof_index(), parent->name()));
4934 result->containing_oneof_ = nullptr;
4935 } else {
4936 result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
4937 }
4938 } else {
4939 result->containing_oneof_ = nullptr;
4940 }
4941 }
4942
4943 // Copy options.
4944 if (!proto.has_options()) {
4945 result->options_ = nullptr; // Will set to default_instance later.
4946 } else {
4947 AllocateOptions(proto.options(), result,
4948 FieldDescriptorProto::kOptionsFieldNumber);
4949 }
4950
4951
4952 AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
4953 }
4954
BuildExtensionRange(const DescriptorProto::ExtensionRange & proto,const Descriptor * parent,Descriptor::ExtensionRange * result)4955 void DescriptorBuilder::BuildExtensionRange(
4956 const DescriptorProto::ExtensionRange& proto, const Descriptor* parent,
4957 Descriptor::ExtensionRange* result) {
4958 result->start = proto.start();
4959 result->end = proto.end();
4960 if (result->start <= 0) {
4961 AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4962 "Extension numbers must be positive integers.");
4963 }
4964
4965 // Checking of the upper bound of the extension range is deferred until after
4966 // options interpreting. This allows messages with message_set_wire_format to
4967 // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
4968 // numbers are actually used as int32s in the message_set_wire_format.
4969
4970 if (result->start >= result->end) {
4971 AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4972 "Extension range end number must be greater than start number.");
4973 }
4974
4975 if (!proto.has_options()) {
4976 result->options_ = nullptr; // Will set to default_instance later.
4977 } else {
4978 std::vector<int> options_path;
4979 parent->GetLocationPath(&options_path);
4980 options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber);
4981 // find index of this extension range in order to compute path
4982 int index;
4983 for (index = 0; parent->extension_ranges_ + index != result; index++) {
4984 }
4985 options_path.push_back(index);
4986 options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber);
4987 AllocateOptionsImpl(parent->full_name(), parent->full_name(),
4988 proto.options(), result, options_path);
4989 }
4990 }
4991
BuildReservedRange(const DescriptorProto::ReservedRange & proto,const Descriptor * parent,Descriptor::ReservedRange * result)4992 void DescriptorBuilder::BuildReservedRange(
4993 const DescriptorProto::ReservedRange& proto, const Descriptor* parent,
4994 Descriptor::ReservedRange* result) {
4995 result->start = proto.start();
4996 result->end = proto.end();
4997 if (result->start <= 0) {
4998 AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4999 "Reserved numbers must be positive integers.");
5000 }
5001 }
5002
BuildReservedRange(const EnumDescriptorProto::EnumReservedRange & proto,const EnumDescriptor * parent,EnumDescriptor::ReservedRange * result)5003 void DescriptorBuilder::BuildReservedRange(
5004 const EnumDescriptorProto::EnumReservedRange& proto,
5005 const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result) {
5006 result->start = proto.start();
5007 result->end = proto.end();
5008
5009 if (result->start > result->end) {
5010 AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5011 "Reserved range end number must be greater than start number.");
5012 }
5013 }
5014
BuildOneof(const OneofDescriptorProto & proto,Descriptor * parent,OneofDescriptor * result)5015 void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
5016 Descriptor* parent,
5017 OneofDescriptor* result) {
5018 std::string* full_name =
5019 AllocateNameString(parent->full_name(), proto.name());
5020 ValidateSymbolName(proto.name(), *full_name, proto);
5021
5022 result->name_ = tables_->AllocateString(proto.name());
5023 result->full_name_ = full_name;
5024
5025 result->containing_type_ = parent;
5026
5027 // We need to fill these in later.
5028 result->field_count_ = 0;
5029 result->fields_ = nullptr;
5030
5031 // Copy options.
5032 if (!proto.has_options()) {
5033 result->options_ = nullptr; // Will set to default_instance later.
5034 } else {
5035 AllocateOptions(proto.options(), result,
5036 OneofDescriptorProto::kOptionsFieldNumber);
5037 }
5038
5039 AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5040 }
5041
CheckEnumValueUniqueness(const EnumDescriptorProto & proto,const EnumDescriptor * result)5042 void DescriptorBuilder::CheckEnumValueUniqueness(
5043 const EnumDescriptorProto& proto, const EnumDescriptor* result) {
5044
5045 // Check that enum labels are still unique when we remove the enum prefix from
5046 // values that have it.
5047 //
5048 // This will fail for something like:
5049 //
5050 // enum MyEnum {
5051 // MY_ENUM_FOO = 0;
5052 // FOO = 1;
5053 // }
5054 //
5055 // By enforcing this reasonable constraint, we allow code generators to strip
5056 // the prefix and/or PascalCase it without creating conflicts. This can lead
5057 // to much nicer language-specific enums like:
5058 //
5059 // enum NameType {
5060 // FirstName = 1,
5061 // LastName = 2,
5062 // }
5063 //
5064 // Instead of:
5065 //
5066 // enum NameType {
5067 // NAME_TYPE_FIRST_NAME = 1,
5068 // NAME_TYPE_LAST_NAME = 2,
5069 // }
5070 PrefixRemover remover(result->name());
5071 std::map<std::string, const EnumValueDescriptor*> values;
5072 for (int i = 0; i < result->value_count(); i++) {
5073 const EnumValueDescriptor* value = result->value(i);
5074 std::string stripped =
5075 EnumValueToPascalCase(remover.MaybeRemove(value->name()));
5076 std::pair<std::map<std::string, const EnumValueDescriptor*>::iterator, bool>
5077 insert_result = values.insert(std::make_pair(stripped, value));
5078 bool inserted = insert_result.second;
5079
5080 // We don't throw the error if the two conflicting symbols are identical, or
5081 // if they map to the same number. In the former case, the normal symbol
5082 // duplication error will fire so we don't need to (and its error message
5083 // will make more sense). We allow the latter case so users can create
5084 // aliases which add or remove the prefix (code generators that do prefix
5085 // stripping should de-dup the labels in this case).
5086 if (!inserted && insert_result.first->second->name() != value->name() &&
5087 insert_result.first->second->number() != value->number()) {
5088 std::string error_message =
5089 "Enum name " + value->name() + " has the same name as " +
5090 values[stripped]->name() +
5091 " if you ignore case and strip out the enum name prefix (if any). "
5092 "This is error-prone and can lead to undefined behavior. "
5093 "Please avoid doing this. If you are using allow_alias, please "
5094 "assign the same numeric value to both enums.";
5095 // There are proto2 enums out there with conflicting names, so to preserve
5096 // compatibility we issue only a warning for proto2.
5097 if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
5098 AddWarning(value->full_name(), proto.value(i),
5099 DescriptorPool::ErrorCollector::NAME, error_message);
5100 } else {
5101 AddError(value->full_name(), proto.value(i),
5102 DescriptorPool::ErrorCollector::NAME, error_message);
5103 }
5104 }
5105 }
5106 }
5107
BuildEnum(const EnumDescriptorProto & proto,const Descriptor * parent,EnumDescriptor * result)5108 void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
5109 const Descriptor* parent,
5110 EnumDescriptor* result) {
5111 const std::string& scope =
5112 (parent == nullptr) ? file_->package() : parent->full_name();
5113 std::string* full_name = AllocateNameString(scope, proto.name());
5114 ValidateSymbolName(proto.name(), *full_name, proto);
5115
5116 result->name_ = tables_->AllocateString(proto.name());
5117 result->full_name_ = full_name;
5118 result->file_ = file_;
5119 result->containing_type_ = parent;
5120 result->is_placeholder_ = false;
5121 result->is_unqualified_placeholder_ = false;
5122
5123 if (proto.value_size() == 0) {
5124 // We cannot allow enums with no values because this would mean there
5125 // would be no valid default value for fields of this type.
5126 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5127 "Enums must contain at least one value.");
5128 }
5129
5130 BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
5131 BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
5132
5133 // Copy reserved names.
5134 int reserved_name_count = proto.reserved_name_size();
5135 result->reserved_name_count_ = reserved_name_count;
5136 result->reserved_names_ =
5137 tables_->AllocateArray<const std::string*>(reserved_name_count);
5138 for (int i = 0; i < reserved_name_count; ++i) {
5139 result->reserved_names_[i] =
5140 tables_->AllocateString(proto.reserved_name(i));
5141 }
5142
5143 CheckEnumValueUniqueness(proto, result);
5144
5145 // Copy options.
5146 if (!proto.has_options()) {
5147 result->options_ = nullptr; // Will set to default_instance later.
5148 } else {
5149 AllocateOptions(proto.options(), result,
5150 EnumDescriptorProto::kOptionsFieldNumber);
5151 }
5152
5153 AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5154
5155 for (int i = 0; i < proto.reserved_range_size(); i++) {
5156 const EnumDescriptorProto_EnumReservedRange& range1 =
5157 proto.reserved_range(i);
5158 for (int j = i + 1; j < proto.reserved_range_size(); j++) {
5159 const EnumDescriptorProto_EnumReservedRange& range2 =
5160 proto.reserved_range(j);
5161 if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
5162 AddError(result->full_name(), proto.reserved_range(i),
5163 DescriptorPool::ErrorCollector::NUMBER,
5164 strings::Substitute("Reserved range $0 to $1 overlaps with "
5165 "already-defined range $2 to $3.",
5166 range2.start(), range2.end(),
5167 range1.start(), range1.end()));
5168 }
5169 }
5170 }
5171
5172 HASH_SET<std::string> reserved_name_set;
5173 for (int i = 0; i < proto.reserved_name_size(); i++) {
5174 const std::string& name = proto.reserved_name(i);
5175 if (reserved_name_set.find(name) == reserved_name_set.end()) {
5176 reserved_name_set.insert(name);
5177 } else {
5178 AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
5179 strings::Substitute(
5180 "Enum value \"$0\" is reserved multiple times.", name));
5181 }
5182 }
5183
5184 for (int i = 0; i < result->value_count(); i++) {
5185 const EnumValueDescriptor* value = result->value(i);
5186 for (int j = 0; j < result->reserved_range_count(); j++) {
5187 const EnumDescriptor::ReservedRange* range = result->reserved_range(j);
5188 if (range->start <= value->number() && value->number() <= range->end) {
5189 AddError(
5190 value->full_name(), proto.reserved_range(j),
5191 DescriptorPool::ErrorCollector::NUMBER,
5192 strings::Substitute("Enum value \"$0\" uses reserved number $1.",
5193 value->name(), value->number()));
5194 }
5195 }
5196 if (reserved_name_set.find(value->name()) != reserved_name_set.end()) {
5197 AddError(
5198 value->full_name(), proto.value(i),
5199 DescriptorPool::ErrorCollector::NAME,
5200 strings::Substitute("Enum value \"$0\" is reserved.", value->name()));
5201 }
5202 }
5203 }
5204
BuildEnumValue(const EnumValueDescriptorProto & proto,const EnumDescriptor * parent,EnumValueDescriptor * result)5205 void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
5206 const EnumDescriptor* parent,
5207 EnumValueDescriptor* result) {
5208 result->name_ = tables_->AllocateString(proto.name());
5209 result->number_ = proto.number();
5210 result->type_ = parent;
5211
5212 // Note: full_name for enum values is a sibling to the parent's name, not a
5213 // child of it.
5214 std::string* full_name = tables_->AllocateEmptyString();
5215 size_t scope_len = parent->full_name_->size() - parent->name_->size();
5216 full_name->reserve(scope_len + result->name_->size());
5217 full_name->append(parent->full_name_->data(), scope_len);
5218 full_name->append(*result->name_);
5219 result->full_name_ = full_name;
5220
5221 ValidateSymbolName(proto.name(), *full_name, proto);
5222
5223 // Copy options.
5224 if (!proto.has_options()) {
5225 result->options_ = nullptr; // Will set to default_instance later.
5226 } else {
5227 AllocateOptions(proto.options(), result,
5228 EnumValueDescriptorProto::kOptionsFieldNumber);
5229 }
5230
5231 // Again, enum values are weird because we makes them appear as siblings
5232 // of the enum type instead of children of it. So, we use
5233 // parent->containing_type() as the value's parent.
5234 bool added_to_outer_scope =
5235 AddSymbol(result->full_name(), parent->containing_type(), result->name(),
5236 proto, Symbol(result));
5237
5238 // However, we also want to be able to search for values within a single
5239 // enum type, so we add it as a child of the enum type itself, too.
5240 // Note: This could fail, but if it does, the error has already been
5241 // reported by the above AddSymbol() call, so we ignore the return code.
5242 bool added_to_inner_scope =
5243 file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
5244
5245 if (added_to_inner_scope && !added_to_outer_scope) {
5246 // This value did not conflict with any values defined in the same enum,
5247 // but it did conflict with some other symbol defined in the enum type's
5248 // scope. Let's print an additional error to explain this.
5249 std::string outer_scope;
5250 if (parent->containing_type() == nullptr) {
5251 outer_scope = file_->package();
5252 } else {
5253 outer_scope = parent->containing_type()->full_name();
5254 }
5255
5256 if (outer_scope.empty()) {
5257 outer_scope = "the global scope";
5258 } else {
5259 outer_scope = "\"" + outer_scope + "\"";
5260 }
5261
5262 AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5263 "Note that enum values use C++ scoping rules, meaning that "
5264 "enum values are siblings of their type, not children of it. "
5265 "Therefore, \"" +
5266 result->name() + "\" must be unique within " + outer_scope +
5267 ", not just within \"" + parent->name() + "\".");
5268 }
5269
5270 // An enum is allowed to define two numbers that refer to the same value.
5271 // FindValueByNumber() should return the first such value, so we simply
5272 // ignore AddEnumValueByNumber()'s return code.
5273 file_tables_->AddEnumValueByNumber(result);
5274 }
5275
BuildService(const ServiceDescriptorProto & proto,const void *,ServiceDescriptor * result)5276 void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
5277 const void* /* dummy */,
5278 ServiceDescriptor* result) {
5279 std::string* full_name = AllocateNameString(file_->package(), proto.name());
5280 ValidateSymbolName(proto.name(), *full_name, proto);
5281
5282 result->name_ = tables_->AllocateString(proto.name());
5283 result->full_name_ = full_name;
5284 result->file_ = file_;
5285
5286 BUILD_ARRAY(proto, result, method, BuildMethod, result);
5287
5288 // Copy options.
5289 if (!proto.has_options()) {
5290 result->options_ = nullptr; // Will set to default_instance later.
5291 } else {
5292 AllocateOptions(proto.options(), result,
5293 ServiceDescriptorProto::kOptionsFieldNumber);
5294 }
5295
5296 AddSymbol(result->full_name(), nullptr, result->name(), proto,
5297 Symbol(result));
5298 }
5299
BuildMethod(const MethodDescriptorProto & proto,const ServiceDescriptor * parent,MethodDescriptor * result)5300 void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
5301 const ServiceDescriptor* parent,
5302 MethodDescriptor* result) {
5303 result->name_ = tables_->AllocateString(proto.name());
5304 result->service_ = parent;
5305
5306 std::string* full_name =
5307 AllocateNameString(parent->full_name(), *result->name_);
5308 result->full_name_ = full_name;
5309
5310 ValidateSymbolName(proto.name(), *full_name, proto);
5311
5312 // These will be filled in when cross-linking.
5313 result->input_type_.Init();
5314 result->output_type_.Init();
5315
5316 // Copy options.
5317 if (!proto.has_options()) {
5318 result->options_ = nullptr; // Will set to default_instance later.
5319 } else {
5320 AllocateOptions(proto.options(), result,
5321 MethodDescriptorProto::kOptionsFieldNumber);
5322 }
5323
5324 result->client_streaming_ = proto.client_streaming();
5325 result->server_streaming_ = proto.server_streaming();
5326
5327 AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5328 }
5329
5330 #undef BUILD_ARRAY
5331
5332 // -------------------------------------------------------------------
5333
CrossLinkFile(FileDescriptor * file,const FileDescriptorProto & proto)5334 void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
5335 const FileDescriptorProto& proto) {
5336 if (file->options_ == nullptr) {
5337 file->options_ = &FileOptions::default_instance();
5338 }
5339
5340 for (int i = 0; i < file->message_type_count(); i++) {
5341 CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
5342 }
5343
5344 for (int i = 0; i < file->extension_count(); i++) {
5345 CrossLinkField(&file->extensions_[i], proto.extension(i));
5346 }
5347
5348 for (int i = 0; i < file->enum_type_count(); i++) {
5349 CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
5350 }
5351
5352 for (int i = 0; i < file->service_count(); i++) {
5353 CrossLinkService(&file->services_[i], proto.service(i));
5354 }
5355 }
5356
CrossLinkMessage(Descriptor * message,const DescriptorProto & proto)5357 void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
5358 const DescriptorProto& proto) {
5359 if (message->options_ == nullptr) {
5360 message->options_ = &MessageOptions::default_instance();
5361 }
5362
5363 for (int i = 0; i < message->nested_type_count(); i++) {
5364 CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
5365 }
5366
5367 for (int i = 0; i < message->enum_type_count(); i++) {
5368 CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
5369 }
5370
5371 for (int i = 0; i < message->field_count(); i++) {
5372 CrossLinkField(&message->fields_[i], proto.field(i));
5373 }
5374
5375 for (int i = 0; i < message->extension_count(); i++) {
5376 CrossLinkField(&message->extensions_[i], proto.extension(i));
5377 }
5378
5379 for (int i = 0; i < message->extension_range_count(); i++) {
5380 CrossLinkExtensionRange(&message->extension_ranges_[i],
5381 proto.extension_range(i));
5382 }
5383
5384 // Set up field array for each oneof.
5385
5386 // First count the number of fields per oneof.
5387 for (int i = 0; i < message->field_count(); i++) {
5388 const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5389 if (oneof_decl != nullptr) {
5390 // Make sure fields belonging to the same oneof are defined consecutively.
5391 // This enables optimizations in codegens and reflection libraries to
5392 // skip fields in the oneof group, as only one of the field can be set.
5393 // Note that field_count() returns how many fields in this oneof we have
5394 // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
5395 // safe.
5396 if (oneof_decl->field_count() > 0 &&
5397 message->field(i - 1)->containing_oneof() != oneof_decl) {
5398 AddError(message->full_name() + "." + message->field(i - 1)->name(),
5399 proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE,
5400 strings::Substitute(
5401 "Fields in the same oneof must be defined consecutively. "
5402 "\"$0\" cannot be defined before the completion of the "
5403 "\"$1\" oneof definition.",
5404 message->field(i - 1)->name(), oneof_decl->name()));
5405 }
5406 // Must go through oneof_decls_ array to get a non-const version of the
5407 // OneofDescriptor.
5408 ++message->oneof_decls_[oneof_decl->index()].field_count_;
5409 }
5410 }
5411
5412 // Then allocate the arrays.
5413 for (int i = 0; i < message->oneof_decl_count(); i++) {
5414 OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
5415
5416 if (oneof_decl->field_count() == 0) {
5417 AddError(message->full_name() + "." + oneof_decl->name(),
5418 proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME,
5419 "Oneof must have at least one field.");
5420 }
5421
5422 oneof_decl->fields_ = tables_->AllocateArray<const FieldDescriptor*>(
5423 oneof_decl->field_count_);
5424 oneof_decl->field_count_ = 0;
5425
5426 if (oneof_decl->options_ == nullptr) {
5427 oneof_decl->options_ = &OneofOptions::default_instance();
5428 }
5429 }
5430
5431 // Then fill them in.
5432 for (int i = 0; i < message->field_count(); i++) {
5433 const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5434 if (oneof_decl != nullptr) {
5435 OneofDescriptor* mutable_oneof_decl =
5436 &message->oneof_decls_[oneof_decl->index()];
5437 message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
5438 mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] =
5439 message->field(i);
5440 }
5441 }
5442 }
5443
CrossLinkExtensionRange(Descriptor::ExtensionRange * range,const DescriptorProto::ExtensionRange & proto)5444 void DescriptorBuilder::CrossLinkExtensionRange(
5445 Descriptor::ExtensionRange* range,
5446 const DescriptorProto::ExtensionRange& proto) {
5447 if (range->options_ == nullptr) {
5448 range->options_ = &ExtensionRangeOptions::default_instance();
5449 }
5450 }
5451
CrossLinkField(FieldDescriptor * field,const FieldDescriptorProto & proto)5452 void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
5453 const FieldDescriptorProto& proto) {
5454 if (field->options_ == nullptr) {
5455 field->options_ = &FieldOptions::default_instance();
5456 }
5457
5458 // Add the field to the lowercase-name and camelcase-name tables.
5459 file_tables_->AddFieldByStylizedNames(field);
5460
5461 if (proto.has_extendee()) {
5462 Symbol extendee =
5463 LookupSymbol(proto.extendee(), field->full_name(),
5464 DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
5465 if (extendee.IsNull()) {
5466 AddNotDefinedError(field->full_name(), proto,
5467 DescriptorPool::ErrorCollector::EXTENDEE,
5468 proto.extendee());
5469 return;
5470 } else if (extendee.type != Symbol::MESSAGE) {
5471 AddError(field->full_name(), proto,
5472 DescriptorPool::ErrorCollector::EXTENDEE,
5473 "\"" + proto.extendee() + "\" is not a message type.");
5474 return;
5475 }
5476 field->containing_type_ = extendee.descriptor;
5477
5478 const Descriptor::ExtensionRange* extension_range =
5479 field->containing_type()->FindExtensionRangeContainingNumber(
5480 field->number());
5481
5482 if (extension_range == nullptr) {
5483 AddError(field->full_name(), proto,
5484 DescriptorPool::ErrorCollector::NUMBER,
5485 strings::Substitute("\"$0\" does not declare $1 as an "
5486 "extension number.",
5487 field->containing_type()->full_name(),
5488 field->number()));
5489 }
5490 }
5491
5492 if (field->containing_oneof() != nullptr) {
5493 if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
5494 // Note that this error will never happen when parsing .proto files.
5495 // It can only happen if you manually construct a FileDescriptorProto
5496 // that is incorrect.
5497 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5498 "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
5499 }
5500 }
5501
5502 if (proto.has_type_name()) {
5503 // Assume we are expecting a message type unless the proto contains some
5504 // evidence that it expects an enum type. This only makes a difference if
5505 // we end up creating a placeholder.
5506 bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
5507 proto.has_default_value();
5508
5509 // In case of weak fields we force building the dependency. We need to know
5510 // if the type exist or not. If it doesnt exist we substitute Empty which
5511 // should only be done if the type can't be found in the generated pool.
5512 // TODO(gerbens) Ideally we should query the database directly to check
5513 // if weak fields exist or not so that we don't need to force building
5514 // weak dependencies. However the name lookup rules for symbols are
5515 // somewhat complicated, so I defer it too another CL.
5516 bool is_weak = !pool_->enforce_weak_ && proto.options().weak();
5517 bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak;
5518
5519 Symbol type =
5520 LookupSymbol(proto.type_name(), field->full_name(),
5521 expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
5522 : DescriptorPool::PLACEHOLDER_MESSAGE,
5523 LOOKUP_TYPES, !is_lazy);
5524
5525 if (type.IsNull()) {
5526 if (is_lazy) {
5527 // Save the symbol names for later for lookup, and allocate the once
5528 // object needed for the accessors.
5529 std::string name = proto.type_name();
5530 field->type_once_ = tables_->AllocateOnceDynamic();
5531 field->type_name_ = tables_->AllocateString(name);
5532 if (proto.has_default_value()) {
5533 field->default_value_enum_name_ =
5534 tables_->AllocateString(proto.default_value());
5535 }
5536 // AddFieldByNumber and AddExtension are done later in this function,
5537 // and can/must be done if the field type was not found. The related
5538 // error checking is not necessary when in lazily_build_dependencies_
5539 // mode, and can't be done without building the type's descriptor,
5540 // which we don't want to do.
5541 file_tables_->AddFieldByNumber(field);
5542 if (field->is_extension()) {
5543 tables_->AddExtension(field);
5544 }
5545 return;
5546 } else {
5547 // If the type is a weak type, we change the type to a google.protobuf.Empty
5548 // field.
5549 if (is_weak) {
5550 type = FindSymbol(kNonLinkedWeakMessageReplacementName);
5551 }
5552 if (type.IsNull()) {
5553 AddNotDefinedError(field->full_name(), proto,
5554 DescriptorPool::ErrorCollector::TYPE,
5555 proto.type_name());
5556 return;
5557 }
5558 }
5559 }
5560
5561 if (!proto.has_type()) {
5562 // Choose field type based on symbol.
5563 if (type.type == Symbol::MESSAGE) {
5564 field->type_ = FieldDescriptor::TYPE_MESSAGE;
5565 } else if (type.type == Symbol::ENUM) {
5566 field->type_ = FieldDescriptor::TYPE_ENUM;
5567 } else {
5568 AddError(field->full_name(), proto,
5569 DescriptorPool::ErrorCollector::TYPE,
5570 "\"" + proto.type_name() + "\" is not a type.");
5571 return;
5572 }
5573 }
5574
5575 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
5576 if (type.type != Symbol::MESSAGE) {
5577 AddError(field->full_name(), proto,
5578 DescriptorPool::ErrorCollector::TYPE,
5579 "\"" + proto.type_name() + "\" is not a message type.");
5580 return;
5581 }
5582 field->message_type_ = type.descriptor;
5583
5584 if (field->has_default_value()) {
5585 AddError(field->full_name(), proto,
5586 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5587 "Messages can't have default values.");
5588 }
5589 } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5590 if (type.type != Symbol::ENUM) {
5591 AddError(field->full_name(), proto,
5592 DescriptorPool::ErrorCollector::TYPE,
5593 "\"" + proto.type_name() + "\" is not an enum type.");
5594 return;
5595 }
5596 field->enum_type_ = type.enum_descriptor;
5597
5598 if (field->enum_type()->is_placeholder_) {
5599 // We can't look up default values for placeholder types. We'll have
5600 // to just drop them.
5601 field->has_default_value_ = false;
5602 }
5603
5604 if (field->has_default_value()) {
5605 // Ensure that the default value is an identifier. Parser cannot always
5606 // verify this because it does not have complete type information.
5607 // N.B. that this check yields better error messages but is not
5608 // necessary for correctness (an enum symbol must be a valid identifier
5609 // anyway), only for better errors.
5610 if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
5611 AddError(field->full_name(), proto,
5612 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5613 "Default value for an enum field must be an identifier.");
5614 } else {
5615 // We can't just use field->enum_type()->FindValueByName() here
5616 // because that locks the pool's mutex, which we have already locked
5617 // at this point.
5618 Symbol default_value = LookupSymbolNoPlaceholder(
5619 proto.default_value(), field->enum_type()->full_name());
5620
5621 if (default_value.type == Symbol::ENUM_VALUE &&
5622 default_value.enum_value_descriptor->type() ==
5623 field->enum_type()) {
5624 field->default_value_enum_ = default_value.enum_value_descriptor;
5625 } else {
5626 AddError(field->full_name(), proto,
5627 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5628 "Enum type \"" + field->enum_type()->full_name() +
5629 "\" has no value named \"" + proto.default_value() +
5630 "\".");
5631 }
5632 }
5633 } else if (field->enum_type()->value_count() > 0) {
5634 // All enums must have at least one value, or we would have reported
5635 // an error elsewhere. We use the first defined value as the default
5636 // if a default is not explicitly defined.
5637 field->default_value_enum_ = field->enum_type()->value(0);
5638 }
5639 } else {
5640 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5641 "Field with primitive type has type_name.");
5642 }
5643 } else {
5644 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
5645 field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5646 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5647 "Field with message or enum type missing type_name.");
5648 }
5649 }
5650
5651 // Add the field to the fields-by-number table.
5652 // Note: We have to do this *after* cross-linking because extensions do not
5653 // know their containing type until now. If we're in
5654 // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
5655 // risk to calling containing_type() or other accessors that will build
5656 // dependencies.
5657 if (!file_tables_->AddFieldByNumber(field)) {
5658 const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
5659 field->containing_type(), field->number());
5660 std::string containing_type_name =
5661 field->containing_type() == nullptr
5662 ? "unknown"
5663 : field->containing_type()->full_name();
5664 if (field->is_extension()) {
5665 AddError(field->full_name(), proto,
5666 DescriptorPool::ErrorCollector::NUMBER,
5667 strings::Substitute("Extension number $0 has already been used "
5668 "in \"$1\" by extension \"$2\".",
5669 field->number(), containing_type_name,
5670 conflicting_field->full_name()));
5671 } else {
5672 AddError(field->full_name(), proto,
5673 DescriptorPool::ErrorCollector::NUMBER,
5674 strings::Substitute("Field number $0 has already been used in "
5675 "\"$1\" by field \"$2\".",
5676 field->number(), containing_type_name,
5677 conflicting_field->name()));
5678 }
5679 } else {
5680 if (field->is_extension()) {
5681 if (!tables_->AddExtension(field)) {
5682 const FieldDescriptor* conflicting_field =
5683 tables_->FindExtension(field->containing_type(), field->number());
5684 std::string containing_type_name =
5685 field->containing_type() == nullptr
5686 ? "unknown"
5687 : field->containing_type()->full_name();
5688 std::string error_msg = strings::Substitute(
5689 "Extension number $0 has already been used in \"$1\" by extension "
5690 "\"$2\" defined in $3.",
5691 field->number(), containing_type_name,
5692 conflicting_field->full_name(), conflicting_field->file()->name());
5693 // Conflicting extension numbers should be an error. However, before
5694 // turning this into an error we need to fix all existing broken
5695 // protos first.
5696 // TODO(xiaofeng): Change this to an error.
5697 AddWarning(field->full_name(), proto,
5698 DescriptorPool::ErrorCollector::NUMBER, error_msg);
5699 }
5700 }
5701 }
5702 }
5703
CrossLinkEnum(EnumDescriptor * enum_type,const EnumDescriptorProto & proto)5704 void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
5705 const EnumDescriptorProto& proto) {
5706 if (enum_type->options_ == nullptr) {
5707 enum_type->options_ = &EnumOptions::default_instance();
5708 }
5709
5710 for (int i = 0; i < enum_type->value_count(); i++) {
5711 CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
5712 }
5713 }
5714
CrossLinkEnumValue(EnumValueDescriptor * enum_value,const EnumValueDescriptorProto &)5715 void DescriptorBuilder::CrossLinkEnumValue(
5716 EnumValueDescriptor* enum_value,
5717 const EnumValueDescriptorProto& /* proto */) {
5718 if (enum_value->options_ == nullptr) {
5719 enum_value->options_ = &EnumValueOptions::default_instance();
5720 }
5721 }
5722
CrossLinkService(ServiceDescriptor * service,const ServiceDescriptorProto & proto)5723 void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
5724 const ServiceDescriptorProto& proto) {
5725 if (service->options_ == nullptr) {
5726 service->options_ = &ServiceOptions::default_instance();
5727 }
5728
5729 for (int i = 0; i < service->method_count(); i++) {
5730 CrossLinkMethod(&service->methods_[i], proto.method(i));
5731 }
5732 }
5733
CrossLinkMethod(MethodDescriptor * method,const MethodDescriptorProto & proto)5734 void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
5735 const MethodDescriptorProto& proto) {
5736 if (method->options_ == nullptr) {
5737 method->options_ = &MethodOptions::default_instance();
5738 }
5739
5740 Symbol input_type =
5741 LookupSymbol(proto.input_type(), method->full_name(),
5742 DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5743 !pool_->lazily_build_dependencies_);
5744 if (input_type.IsNull()) {
5745 if (!pool_->lazily_build_dependencies_) {
5746 AddNotDefinedError(method->full_name(), proto,
5747 DescriptorPool::ErrorCollector::INPUT_TYPE,
5748 proto.input_type());
5749 } else {
5750 method->input_type_.SetLazy(proto.input_type(), file_);
5751 }
5752 } else if (input_type.type != Symbol::MESSAGE) {
5753 AddError(method->full_name(), proto,
5754 DescriptorPool::ErrorCollector::INPUT_TYPE,
5755 "\"" + proto.input_type() + "\" is not a message type.");
5756 } else {
5757 method->input_type_.Set(input_type.descriptor);
5758 }
5759
5760 Symbol output_type =
5761 LookupSymbol(proto.output_type(), method->full_name(),
5762 DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5763 !pool_->lazily_build_dependencies_);
5764 if (output_type.IsNull()) {
5765 if (!pool_->lazily_build_dependencies_) {
5766 AddNotDefinedError(method->full_name(), proto,
5767 DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5768 proto.output_type());
5769 } else {
5770 method->output_type_.SetLazy(proto.output_type(), file_);
5771 }
5772 } else if (output_type.type != Symbol::MESSAGE) {
5773 AddError(method->full_name(), proto,
5774 DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5775 "\"" + proto.output_type() + "\" is not a message type.");
5776 } else {
5777 method->output_type_.Set(output_type.descriptor);
5778 }
5779 }
5780
5781 // -------------------------------------------------------------------
5782
5783 #define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \
5784 for (int i = 0; i < descriptor->array_name##_count(); ++i) { \
5785 Validate##type##Options(descriptor->array_name##s_ + i, \
5786 proto.array_name(i)); \
5787 }
5788
5789 // Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
5790 // avoid problems that exist at init time.
IsLite(const FileDescriptor * file)5791 static bool IsLite(const FileDescriptor* file) {
5792 // TODO(kenton): I don't even remember how many of these conditions are
5793 // actually possible. I'm just being super-safe.
5794 return file != nullptr &&
5795 &file->options() != &FileOptions::default_instance() &&
5796 file->options().optimize_for() == FileOptions::LITE_RUNTIME;
5797 }
5798
ValidateFileOptions(FileDescriptor * file,const FileDescriptorProto & proto)5799 void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
5800 const FileDescriptorProto& proto) {
5801 VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
5802 VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
5803 VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
5804 VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
5805
5806 // Lite files can only be imported by other Lite files.
5807 if (!IsLite(file)) {
5808 for (int i = 0; i < file->dependency_count(); i++) {
5809 if (IsLite(file->dependency(i))) {
5810 AddError(
5811 file->dependency(i)->name(), proto,
5812 DescriptorPool::ErrorCollector::IMPORT,
5813 "Files that do not use optimize_for = LITE_RUNTIME cannot import "
5814 "files which do use this option. This file is not lite, but it "
5815 "imports \"" +
5816 file->dependency(i)->name() + "\" which is.");
5817 break;
5818 }
5819 }
5820 }
5821 if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
5822 ValidateProto3(file, proto);
5823 }
5824 }
5825
ValidateProto3(FileDescriptor * file,const FileDescriptorProto & proto)5826 void DescriptorBuilder::ValidateProto3(FileDescriptor* file,
5827 const FileDescriptorProto& proto) {
5828 for (int i = 0; i < file->extension_count(); ++i) {
5829 ValidateProto3Field(file->extensions_ + i, proto.extension(i));
5830 }
5831 for (int i = 0; i < file->message_type_count(); ++i) {
5832 ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
5833 }
5834 for (int i = 0; i < file->enum_type_count(); ++i) {
5835 ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
5836 }
5837 }
5838
ToLowercaseWithoutUnderscores(const std::string & name)5839 static std::string ToLowercaseWithoutUnderscores(const std::string& name) {
5840 std::string result;
5841 for (int i = 0; i < name.size(); ++i) {
5842 if (name[i] != '_') {
5843 if (name[i] >= 'A' && name[i] <= 'Z') {
5844 result.push_back(name[i] - 'A' + 'a');
5845 } else {
5846 result.push_back(name[i]);
5847 }
5848 }
5849 }
5850 return result;
5851 }
5852
ValidateProto3Message(Descriptor * message,const DescriptorProto & proto)5853 void DescriptorBuilder::ValidateProto3Message(Descriptor* message,
5854 const DescriptorProto& proto) {
5855 for (int i = 0; i < message->nested_type_count(); ++i) {
5856 ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i));
5857 }
5858 for (int i = 0; i < message->enum_type_count(); ++i) {
5859 ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i));
5860 }
5861 for (int i = 0; i < message->field_count(); ++i) {
5862 ValidateProto3Field(message->fields_ + i, proto.field(i));
5863 }
5864 for (int i = 0; i < message->extension_count(); ++i) {
5865 ValidateProto3Field(message->extensions_ + i, proto.extension(i));
5866 }
5867 if (message->extension_range_count() > 0) {
5868 AddError(message->full_name(), proto.extension_range(0),
5869 DescriptorPool::ErrorCollector::NUMBER,
5870 "Extension ranges are not allowed in proto3.");
5871 }
5872 if (message->options().message_set_wire_format()) {
5873 // Using MessageSet doesn't make sense since we disallow extensions.
5874 AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5875 "MessageSet is not supported in proto3.");
5876 }
5877
5878 // In proto3, we reject field names if they conflict in camelCase.
5879 // Note that we currently enforce a stricter rule: Field names must be
5880 // unique after being converted to lowercase with underscores removed.
5881 std::map<std::string, const FieldDescriptor*> name_to_field;
5882 for (int i = 0; i < message->field_count(); ++i) {
5883 std::string lowercase_name =
5884 ToLowercaseWithoutUnderscores(message->field(i)->name());
5885 if (name_to_field.find(lowercase_name) != name_to_field.end()) {
5886 AddError(message->full_name(), proto.field(i),
5887 DescriptorPool::ErrorCollector::NAME,
5888 "The JSON camel-case name of field \"" +
5889 message->field(i)->name() + "\" conflicts with field \"" +
5890 name_to_field[lowercase_name]->name() + "\". This is not " +
5891 "allowed in proto3.");
5892 } else {
5893 name_to_field[lowercase_name] = message->field(i);
5894 }
5895 }
5896 }
5897
ValidateProto3Field(FieldDescriptor * field,const FieldDescriptorProto & proto)5898 void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field,
5899 const FieldDescriptorProto& proto) {
5900 if (field->is_extension() &&
5901 !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
5902 AddError(field->full_name(), proto,
5903 DescriptorPool::ErrorCollector::EXTENDEE,
5904 "Extensions in proto3 are only allowed for defining options.");
5905 }
5906 if (field->is_required()) {
5907 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5908 "Required fields are not allowed in proto3.");
5909 }
5910 if (field->has_default_value()) {
5911 AddError(field->full_name(), proto,
5912 DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5913 "Explicit default values are not allowed in proto3.");
5914 }
5915 if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
5916 field->enum_type() &&
5917 field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3) {
5918 // Proto3 messages can only use Proto3 enum types; otherwise we can't
5919 // guarantee that the default value is zero.
5920 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5921 "Enum type \"" + field->enum_type()->full_name() +
5922 "\" is not a proto3 enum, but is used in \"" +
5923 field->containing_type()->full_name() +
5924 "\" which is a proto3 message type.");
5925 }
5926 if (field->type() == FieldDescriptor::TYPE_GROUP) {
5927 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5928 "Groups are not supported in proto3 syntax.");
5929 }
5930 }
5931
ValidateProto3Enum(EnumDescriptor * enm,const EnumDescriptorProto & proto)5932 void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm,
5933 const EnumDescriptorProto& proto) {
5934 if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
5935 AddError(enm->full_name(), proto.value(0),
5936 DescriptorPool::ErrorCollector::NUMBER,
5937 "The first enum value must be zero in proto3.");
5938 }
5939 }
5940
ValidateMessageOptions(Descriptor * message,const DescriptorProto & proto)5941 void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
5942 const DescriptorProto& proto) {
5943 VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
5944 VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
5945 VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
5946 VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
5947
5948 const int64 max_extension_range =
5949 static_cast<int64>(message->options().message_set_wire_format()
5950 ? kint32max
5951 : FieldDescriptor::kMaxNumber);
5952 for (int i = 0; i < message->extension_range_count(); ++i) {
5953 if (message->extension_range(i)->end > max_extension_range + 1) {
5954 AddError(
5955 message->full_name(), proto.extension_range(i),
5956 DescriptorPool::ErrorCollector::NUMBER,
5957 strings::Substitute("Extension numbers cannot be greater than $0.",
5958 max_extension_range));
5959 }
5960 }
5961 }
5962
5963
ValidateFieldOptions(FieldDescriptor * field,const FieldDescriptorProto & proto)5964 void DescriptorBuilder::ValidateFieldOptions(
5965 FieldDescriptor* field, const FieldDescriptorProto& proto) {
5966 if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
5967 return;
5968 }
5969 // Only message type fields may be lazy.
5970 if (field->options().lazy()) {
5971 if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
5972 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5973 "[lazy = true] can only be specified for submessage fields.");
5974 }
5975 }
5976
5977 // Only repeated primitive fields may be packed.
5978 if (field->options().packed() && !field->is_packable()) {
5979 AddError(
5980 field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5981 "[packed = true] can only be specified for repeated primitive fields.");
5982 }
5983
5984 // Note: Default instance may not yet be initialized here, so we have to
5985 // avoid reading from it.
5986 if (field->containing_type_ != nullptr &&
5987 &field->containing_type()->options() !=
5988 &MessageOptions::default_instance() &&
5989 field->containing_type()->options().message_set_wire_format()) {
5990 if (field->is_extension()) {
5991 if (!field->is_optional() ||
5992 field->type() != FieldDescriptor::TYPE_MESSAGE) {
5993 AddError(field->full_name(), proto,
5994 DescriptorPool::ErrorCollector::TYPE,
5995 "Extensions of MessageSets must be optional messages.");
5996 }
5997 } else {
5998 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5999 "MessageSets cannot have fields, only extensions.");
6000 }
6001 }
6002
6003 // Lite extensions can only be of Lite types.
6004 if (IsLite(field->file()) && field->containing_type_ != nullptr &&
6005 !IsLite(field->containing_type()->file())) {
6006 AddError(field->full_name(), proto,
6007 DescriptorPool::ErrorCollector::EXTENDEE,
6008 "Extensions to non-lite types can only be declared in non-lite "
6009 "files. Note that you cannot extend a non-lite type to contain "
6010 "a lite type, but the reverse is allowed.");
6011 }
6012
6013 // Validate map types.
6014 if (field->is_map()) {
6015 if (!ValidateMapEntry(field, proto)) {
6016 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6017 "map_entry should not be set explicitly. Use map<KeyType, "
6018 "ValueType> instead.");
6019 }
6020 }
6021
6022 ValidateJSType(field, proto);
6023
6024 // json_name option is not allowed on extension fields. Note that the
6025 // json_name field in FieldDescriptorProto is always populated by protoc
6026 // when it sends descriptor data to plugins (caculated from field name if
6027 // the option is not explicitly set) so we can't rely on its presence to
6028 // determine whether the json_name option is set on the field. Here we
6029 // compare it against the default calculated json_name value and consider
6030 // the option set if they are different. This won't catch the case when
6031 // an user explicitly sets json_name to the default value, but should be
6032 // good enough to catch common misuses.
6033 if (field->is_extension() &&
6034 (field->has_json_name() &&
6035 field->json_name() != ToJsonName(field->name()))) {
6036 AddError(field->full_name(), proto,
6037 DescriptorPool::ErrorCollector::OPTION_NAME,
6038 "option json_name is not allowed on extension fields.");
6039 }
6040
6041 }
6042
ValidateEnumOptions(EnumDescriptor * enm,const EnumDescriptorProto & proto)6043 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
6044 const EnumDescriptorProto& proto) {
6045 VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
6046 if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
6047 std::map<int, std::string> used_values;
6048 for (int i = 0; i < enm->value_count(); ++i) {
6049 const EnumValueDescriptor* enum_value = enm->value(i);
6050 if (used_values.find(enum_value->number()) != used_values.end()) {
6051 std::string error =
6052 "\"" + enum_value->full_name() +
6053 "\" uses the same enum value as \"" +
6054 used_values[enum_value->number()] +
6055 "\". If this is intended, set "
6056 "'option allow_alias = true;' to the enum definition.";
6057 if (!enm->options().allow_alias()) {
6058 // Generate error if duplicated enum values are explicitly disallowed.
6059 AddError(enm->full_name(), proto.value(i),
6060 DescriptorPool::ErrorCollector::NUMBER, error);
6061 }
6062 } else {
6063 used_values[enum_value->number()] = enum_value->full_name();
6064 }
6065 }
6066 }
6067 }
6068
ValidateEnumValueOptions(EnumValueDescriptor *,const EnumValueDescriptorProto &)6069 void DescriptorBuilder::ValidateEnumValueOptions(
6070 EnumValueDescriptor* /* enum_value */,
6071 const EnumValueDescriptorProto& /* proto */) {
6072 // Nothing to do so far.
6073 }
ValidateServiceOptions(ServiceDescriptor * service,const ServiceDescriptorProto & proto)6074 void DescriptorBuilder::ValidateServiceOptions(
6075 ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
6076 if (IsLite(service->file()) &&
6077 (service->file()->options().cc_generic_services() ||
6078 service->file()->options().java_generic_services())) {
6079 AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6080 "Files with optimize_for = LITE_RUNTIME cannot define services "
6081 "unless you set both options cc_generic_services and "
6082 "java_generic_services to false.");
6083 }
6084
6085 VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
6086 }
6087
ValidateMethodOptions(MethodDescriptor *,const MethodDescriptorProto &)6088 void DescriptorBuilder::ValidateMethodOptions(
6089 MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) {
6090 // Nothing to do so far.
6091 }
6092
ValidateMapEntry(FieldDescriptor * field,const FieldDescriptorProto & proto)6093 bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
6094 const FieldDescriptorProto& proto) {
6095 const Descriptor* message = field->message_type();
6096 if ( // Must not contain extensions, extension range or nested message or
6097 // enums
6098 message->extension_count() != 0 ||
6099 field->label() != FieldDescriptor::LABEL_REPEATED ||
6100 message->extension_range_count() != 0 ||
6101 message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
6102 // Must contain exactly two fields
6103 message->field_count() != 2 ||
6104 // Field name and message name must match
6105 message->name() != ToCamelCase(field->name(), false) + "Entry" ||
6106 // Entry message must be in the same containing type of the field.
6107 field->containing_type() != message->containing_type()) {
6108 return false;
6109 }
6110
6111 const FieldDescriptor* key = message->field(0);
6112 const FieldDescriptor* value = message->field(1);
6113 if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
6114 key->name() != "key") {
6115 return false;
6116 }
6117 if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
6118 value->number() != 2 || value->name() != "value") {
6119 return false;
6120 }
6121
6122 // Check key types are legal.
6123 switch (key->type()) {
6124 case FieldDescriptor::TYPE_ENUM:
6125 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6126 "Key in map fields cannot be enum types.");
6127 break;
6128 case FieldDescriptor::TYPE_FLOAT:
6129 case FieldDescriptor::TYPE_DOUBLE:
6130 case FieldDescriptor::TYPE_MESSAGE:
6131 case FieldDescriptor::TYPE_GROUP:
6132 case FieldDescriptor::TYPE_BYTES:
6133 AddError(
6134 field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6135 "Key in map fields cannot be float/double, bytes or message types.");
6136 break;
6137 case FieldDescriptor::TYPE_BOOL:
6138 case FieldDescriptor::TYPE_INT32:
6139 case FieldDescriptor::TYPE_INT64:
6140 case FieldDescriptor::TYPE_SINT32:
6141 case FieldDescriptor::TYPE_SINT64:
6142 case FieldDescriptor::TYPE_STRING:
6143 case FieldDescriptor::TYPE_UINT32:
6144 case FieldDescriptor::TYPE_UINT64:
6145 case FieldDescriptor::TYPE_FIXED32:
6146 case FieldDescriptor::TYPE_FIXED64:
6147 case FieldDescriptor::TYPE_SFIXED32:
6148 case FieldDescriptor::TYPE_SFIXED64:
6149 // Legal cases
6150 break;
6151 // Do not add a default, so that the compiler will complain when new types
6152 // are added.
6153 }
6154
6155 if (value->type() == FieldDescriptor::TYPE_ENUM) {
6156 if (value->enum_type()->value(0)->number() != 0) {
6157 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6158 "Enum value in map must define 0 as the first value.");
6159 }
6160 }
6161
6162 return true;
6163 }
6164
DetectMapConflicts(const Descriptor * message,const DescriptorProto & proto)6165 void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
6166 const DescriptorProto& proto) {
6167 std::map<std::string, const Descriptor*> seen_types;
6168 for (int i = 0; i < message->nested_type_count(); ++i) {
6169 const Descriptor* nested = message->nested_type(i);
6170 std::pair<std::map<std::string, const Descriptor*>::iterator, bool> result =
6171 seen_types.insert(std::make_pair(nested->name(), nested));
6172 if (!result.second) {
6173 if (result.first->second->options().map_entry() ||
6174 nested->options().map_entry()) {
6175 AddError(message->full_name(), proto,
6176 DescriptorPool::ErrorCollector::NAME,
6177 "Expanded map entry type " + nested->name() +
6178 " conflicts with an existing nested message type.");
6179 }
6180 }
6181 // Recursively test on the nested types.
6182 DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
6183 }
6184 // Check for conflicted field names.
6185 for (int i = 0; i < message->field_count(); ++i) {
6186 const FieldDescriptor* field = message->field(i);
6187 std::map<std::string, const Descriptor*>::iterator iter =
6188 seen_types.find(field->name());
6189 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6190 AddError(message->full_name(), proto,
6191 DescriptorPool::ErrorCollector::NAME,
6192 "Expanded map entry type " + iter->second->name() +
6193 " conflicts with an existing field.");
6194 }
6195 }
6196 // Check for conflicted enum names.
6197 for (int i = 0; i < message->enum_type_count(); ++i) {
6198 const EnumDescriptor* enum_desc = message->enum_type(i);
6199 std::map<std::string, const Descriptor*>::iterator iter =
6200 seen_types.find(enum_desc->name());
6201 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6202 AddError(message->full_name(), proto,
6203 DescriptorPool::ErrorCollector::NAME,
6204 "Expanded map entry type " + iter->second->name() +
6205 " conflicts with an existing enum type.");
6206 }
6207 }
6208 // Check for conflicted oneof names.
6209 for (int i = 0; i < message->oneof_decl_count(); ++i) {
6210 const OneofDescriptor* oneof_desc = message->oneof_decl(i);
6211 std::map<std::string, const Descriptor*>::iterator iter =
6212 seen_types.find(oneof_desc->name());
6213 if (iter != seen_types.end() && iter->second->options().map_entry()) {
6214 AddError(message->full_name(), proto,
6215 DescriptorPool::ErrorCollector::NAME,
6216 "Expanded map entry type " + iter->second->name() +
6217 " conflicts with an existing oneof type.");
6218 }
6219 }
6220 }
6221
ValidateJSType(FieldDescriptor * field,const FieldDescriptorProto & proto)6222 void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
6223 const FieldDescriptorProto& proto) {
6224 FieldOptions::JSType jstype = field->options().jstype();
6225 // The default is always acceptable.
6226 if (jstype == FieldOptions::JS_NORMAL) {
6227 return;
6228 }
6229
6230 switch (field->type()) {
6231 // Integral 64-bit types may be represented as JavaScript numbers or
6232 // strings.
6233 case FieldDescriptor::TYPE_UINT64:
6234 case FieldDescriptor::TYPE_INT64:
6235 case FieldDescriptor::TYPE_SINT64:
6236 case FieldDescriptor::TYPE_FIXED64:
6237 case FieldDescriptor::TYPE_SFIXED64:
6238 if (jstype == FieldOptions::JS_STRING ||
6239 jstype == FieldOptions::JS_NUMBER) {
6240 return;
6241 }
6242 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6243 "Illegal jstype for int64, uint64, sint64, fixed64 "
6244 "or sfixed64 field: " +
6245 FieldOptions_JSType_descriptor()->value(jstype)->name());
6246 break;
6247
6248 // No other types permit a jstype option.
6249 default:
6250 AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6251 "jstype is only allowed on int64, uint64, sint64, fixed64 "
6252 "or sfixed64 fields.");
6253 break;
6254 }
6255 }
6256
6257 #undef VALIDATE_OPTIONS_FROM_ARRAY
6258
6259 // -------------------------------------------------------------------
6260
OptionInterpreter(DescriptorBuilder * builder)6261 DescriptorBuilder::OptionInterpreter::OptionInterpreter(
6262 DescriptorBuilder* builder)
6263 : builder_(builder) {
6264 GOOGLE_CHECK(builder_);
6265 }
6266
~OptionInterpreter()6267 DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
6268
InterpretOptions(OptionsToInterpret * options_to_interpret)6269 bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
6270 OptionsToInterpret* options_to_interpret) {
6271 // Note that these may be in different pools, so we can't use the same
6272 // descriptor and reflection objects on both.
6273 Message* options = options_to_interpret->options;
6274 const Message* original_options = options_to_interpret->original_options;
6275
6276 bool failed = false;
6277 options_to_interpret_ = options_to_interpret;
6278
6279 // Find the uninterpreted_option field in the mutable copy of the options
6280 // and clear them, since we're about to interpret them.
6281 const FieldDescriptor* uninterpreted_options_field =
6282 options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6283 GOOGLE_CHECK(uninterpreted_options_field != nullptr)
6284 << "No field named \"uninterpreted_option\" in the Options proto.";
6285 options->GetReflection()->ClearField(options, uninterpreted_options_field);
6286
6287 std::vector<int> src_path = options_to_interpret->element_path;
6288 src_path.push_back(uninterpreted_options_field->number());
6289
6290 // Find the uninterpreted_option field in the original options.
6291 const FieldDescriptor* original_uninterpreted_options_field =
6292 original_options->GetDescriptor()->FindFieldByName(
6293 "uninterpreted_option");
6294 GOOGLE_CHECK(original_uninterpreted_options_field != nullptr)
6295 << "No field named \"uninterpreted_option\" in the Options proto.";
6296
6297 const int num_uninterpreted_options =
6298 original_options->GetReflection()->FieldSize(
6299 *original_options, original_uninterpreted_options_field);
6300 for (int i = 0; i < num_uninterpreted_options; ++i) {
6301 src_path.push_back(i);
6302 uninterpreted_option_ = down_cast<const UninterpretedOption*>(
6303 &original_options->GetReflection()->GetRepeatedMessage(
6304 *original_options, original_uninterpreted_options_field, i));
6305 if (!InterpretSingleOption(options, src_path,
6306 options_to_interpret->element_path)) {
6307 // Error already added by InterpretSingleOption().
6308 failed = true;
6309 break;
6310 }
6311 src_path.pop_back();
6312 }
6313 // Reset these, so we don't have any dangling pointers.
6314 uninterpreted_option_ = nullptr;
6315 options_to_interpret_ = nullptr;
6316
6317 if (!failed) {
6318 // InterpretSingleOption() added the interpreted options in the
6319 // UnknownFieldSet, in case the option isn't yet known to us. Now we
6320 // serialize the options message and deserialize it back. That way, any
6321 // option fields that we do happen to know about will get moved from the
6322 // UnknownFieldSet into the real fields, and thus be available right away.
6323 // If they are not known, that's OK too. They will get reparsed into the
6324 // UnknownFieldSet and wait there until the message is parsed by something
6325 // that does know about the options.
6326
6327 // Keep the unparsed options around in case the reparsing fails.
6328 std::unique_ptr<Message> unparsed_options(options->New());
6329 options->GetReflection()->Swap(unparsed_options.get(), options);
6330
6331 std::string buf;
6332 if (!unparsed_options->AppendToString(&buf) ||
6333 !options->ParseFromString(buf)) {
6334 builder_->AddError(
6335 options_to_interpret->element_name, *original_options,
6336 DescriptorPool::ErrorCollector::OTHER,
6337 "Some options could not be correctly parsed using the proto "
6338 "descriptors compiled into this binary.\n"
6339 "Unparsed options: " +
6340 unparsed_options->ShortDebugString() +
6341 "\n"
6342 "Parsing attempt: " +
6343 options->ShortDebugString());
6344 // Restore the unparsed options.
6345 options->GetReflection()->Swap(unparsed_options.get(), options);
6346 }
6347 }
6348 return !failed;
6349 }
6350
InterpretSingleOption(Message * options,const std::vector<int> & src_path,const std::vector<int> & options_path)6351 bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
6352 Message* options, const std::vector<int>& src_path,
6353 const std::vector<int>& options_path) {
6354 // First do some basic validation.
6355 if (uninterpreted_option_->name_size() == 0) {
6356 // This should never happen unless the parser has gone seriously awry or
6357 // someone has manually created the uninterpreted option badly.
6358 return AddNameError("Option must have a name.");
6359 }
6360 if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
6361 return AddNameError(
6362 "Option must not use reserved name "
6363 "\"uninterpreted_option\".");
6364 }
6365
6366 const Descriptor* options_descriptor = nullptr;
6367 // Get the options message's descriptor from the builder's pool, so that we
6368 // get the version that knows about any extension options declared in the file
6369 // we're currently building. The descriptor should be there as long as the
6370 // file we're building imported descriptor.proto.
6371
6372 // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
6373 // DescriptorPool::FindMessageTypeByName() because we're already holding the
6374 // pool's mutex, and the latter method locks it again. We don't use
6375 // FindSymbol() because files that use custom options only need to depend on
6376 // the file that defines the option, not descriptor.proto itself.
6377 Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
6378 options->GetDescriptor()->full_name());
6379 if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
6380 options_descriptor = symbol.descriptor;
6381 } else {
6382 // The options message's descriptor was not in the builder's pool, so use
6383 // the standard version from the generated pool. We're not holding the
6384 // generated pool's mutex, so we can search it the straightforward way.
6385 options_descriptor = options->GetDescriptor();
6386 }
6387 GOOGLE_CHECK(options_descriptor);
6388
6389 // We iterate over the name parts to drill into the submessages until we find
6390 // the leaf field for the option. As we drill down we remember the current
6391 // submessage's descriptor in |descriptor| and the next field in that
6392 // submessage in |field|. We also track the fields we're drilling down
6393 // through in |intermediate_fields|. As we go, we reconstruct the full option
6394 // name in |debug_msg_name|, for use in error messages.
6395 const Descriptor* descriptor = options_descriptor;
6396 const FieldDescriptor* field = nullptr;
6397 std::vector<const FieldDescriptor*> intermediate_fields;
6398 std::string debug_msg_name = "";
6399
6400 std::vector<int> dest_path = options_path;
6401
6402 for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
6403 const std::string& name_part = uninterpreted_option_->name(i).name_part();
6404 if (debug_msg_name.size() > 0) {
6405 debug_msg_name += ".";
6406 }
6407 if (uninterpreted_option_->name(i).is_extension()) {
6408 debug_msg_name += "(" + name_part + ")";
6409 // Search for the extension's descriptor as an extension in the builder's
6410 // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
6411 // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
6412 // relative lookups, and 2) because we're already holding the pool's
6413 // mutex, and the latter method locks it again.
6414 symbol =
6415 builder_->LookupSymbol(name_part, options_to_interpret_->name_scope);
6416 if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
6417 field = symbol.field_descriptor;
6418 }
6419 // If we don't find the field then the field's descriptor was not in the
6420 // builder's pool, but there's no point in looking in the generated
6421 // pool. We require that you import the file that defines any extensions
6422 // you use, so they must be present in the builder's pool.
6423 } else {
6424 debug_msg_name += name_part;
6425 // Search for the field's descriptor as a regular field.
6426 field = descriptor->FindFieldByName(name_part);
6427 }
6428
6429 if (field == nullptr) {
6430 if (get_allow_unknown(builder_->pool_)) {
6431 // We can't find the option, but AllowUnknownDependencies() is enabled,
6432 // so we will just leave it as uninterpreted.
6433 AddWithoutInterpreting(*uninterpreted_option_, options);
6434 return true;
6435 } else if (!(builder_->undefine_resolved_name_).empty()) {
6436 // Option is resolved to a name which is not defined.
6437 return AddNameError(
6438 "Option \"" + debug_msg_name + "\" is resolved to \"(" +
6439 builder_->undefine_resolved_name_ +
6440 ")\", which is not defined. The innermost scope is searched first "
6441 "in name resolution. Consider using a leading '.'(i.e., \"(." +
6442 debug_msg_name.substr(1) +
6443 "\") to start from the outermost scope.");
6444 } else {
6445 return AddNameError(
6446 "Option \"" + debug_msg_name +
6447 "\" unknown. Ensure that your proto" +
6448 " definition file imports the proto which defines the option.");
6449 }
6450 } else if (field->containing_type() != descriptor) {
6451 if (get_is_placeholder(field->containing_type())) {
6452 // The field is an extension of a placeholder type, so we can't
6453 // reliably verify whether it is a valid extension to use here (e.g.
6454 // we don't know if it is an extension of the correct *Options message,
6455 // or if it has a valid field number, etc.). Just leave it as
6456 // uninterpreted instead.
6457 AddWithoutInterpreting(*uninterpreted_option_, options);
6458 return true;
6459 } else {
6460 // This can only happen if, due to some insane misconfiguration of the
6461 // pools, we find the options message in one pool but the field in
6462 // another. This would probably imply a hefty bug somewhere.
6463 return AddNameError("Option field \"" + debug_msg_name +
6464 "\" is not a field or extension of message \"" +
6465 descriptor->name() + "\".");
6466 }
6467 } else {
6468 // accumulate field numbers to form path to interpreted option
6469 dest_path.push_back(field->number());
6470
6471 if (i < uninterpreted_option_->name_size() - 1) {
6472 if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
6473 return AddNameError("Option \"" + debug_msg_name +
6474 "\" is an atomic type, not a message.");
6475 } else if (field->is_repeated()) {
6476 return AddNameError("Option field \"" + debug_msg_name +
6477 "\" is a repeated message. Repeated message "
6478 "options must be initialized using an "
6479 "aggregate value.");
6480 } else {
6481 // Drill down into the submessage.
6482 intermediate_fields.push_back(field);
6483 descriptor = field->message_type();
6484 }
6485 }
6486 }
6487 }
6488
6489 // We've found the leaf field. Now we use UnknownFieldSets to set its value
6490 // on the options message. We do so because the message may not yet know
6491 // about its extension fields, so we may not be able to set the fields
6492 // directly. But the UnknownFieldSets will serialize to the same wire-format
6493 // message, so reading that message back in once the extension fields are
6494 // known will populate them correctly.
6495
6496 // First see if the option is already set.
6497 if (!field->is_repeated() &&
6498 !ExamineIfOptionIsSet(
6499 intermediate_fields.begin(), intermediate_fields.end(), field,
6500 debug_msg_name,
6501 options->GetReflection()->GetUnknownFields(*options))) {
6502 return false; // ExamineIfOptionIsSet() already added the error.
6503 }
6504
6505 // First set the value on the UnknownFieldSet corresponding to the
6506 // innermost message.
6507 std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
6508 if (!SetOptionValue(field, unknown_fields.get())) {
6509 return false; // SetOptionValue() already added the error.
6510 }
6511
6512 // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
6513 // the intermediate messages.
6514 for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
6515 intermediate_fields.rbegin();
6516 iter != intermediate_fields.rend(); ++iter) {
6517 std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
6518 new UnknownFieldSet());
6519 switch ((*iter)->type()) {
6520 case FieldDescriptor::TYPE_MESSAGE: {
6521 io::StringOutputStream outstr(
6522 parent_unknown_fields->AddLengthDelimited((*iter)->number()));
6523 io::CodedOutputStream out(&outstr);
6524 internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out);
6525 GOOGLE_CHECK(!out.HadError())
6526 << "Unexpected failure while serializing option submessage "
6527 << debug_msg_name << "\".";
6528 break;
6529 }
6530
6531 case FieldDescriptor::TYPE_GROUP: {
6532 parent_unknown_fields->AddGroup((*iter)->number())
6533 ->MergeFrom(*unknown_fields);
6534 break;
6535 }
6536
6537 default:
6538 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
6539 << (*iter)->type();
6540 return false;
6541 }
6542 unknown_fields.reset(parent_unknown_fields.release());
6543 }
6544
6545 // Now merge the UnknownFieldSet corresponding to the top-level message into
6546 // the options message.
6547 options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
6548 *unknown_fields);
6549
6550 // record the element path of the interpreted option
6551 if (field->is_repeated()) {
6552 int index = repeated_option_counts_[dest_path]++;
6553 dest_path.push_back(index);
6554 }
6555 interpreted_paths_[src_path] = dest_path;
6556
6557 return true;
6558 }
6559
UpdateSourceCodeInfo(SourceCodeInfo * info)6560 void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
6561 SourceCodeInfo* info) {
6562 if (interpreted_paths_.empty()) {
6563 // nothing to do!
6564 return;
6565 }
6566
6567 // We find locations that match keys in interpreted_paths_ and
6568 // 1) replace the path with the corresponding value in interpreted_paths_
6569 // 2) remove any subsequent sub-locations (sub-location is one whose path
6570 // has the parent path as a prefix)
6571 //
6572 // To avoid quadratic behavior of removing interior rows as we go,
6573 // we keep a copy. But we don't actually copy anything until we've
6574 // found the first match (so if the source code info has no locations
6575 // that need to be changed, there is zero copy overhead).
6576
6577 RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location();
6578 RepeatedPtrField<SourceCodeInfo_Location> new_locs;
6579 bool copying = false;
6580
6581 std::vector<int> pathv;
6582 bool matched = false;
6583
6584 for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin();
6585 loc != locs->end(); loc++) {
6586 if (matched) {
6587 // see if this location is in the range to remove
6588 bool loc_matches = true;
6589 if (loc->path_size() < pathv.size()) {
6590 loc_matches = false;
6591 } else {
6592 for (int j = 0; j < pathv.size(); j++) {
6593 if (loc->path(j) != pathv[j]) {
6594 loc_matches = false;
6595 break;
6596 }
6597 }
6598 }
6599
6600 if (loc_matches) {
6601 // don't copy this row since it is a sub-location that we're removing
6602 continue;
6603 }
6604
6605 matched = false;
6606 }
6607
6608 pathv.clear();
6609 for (int j = 0; j < loc->path_size(); j++) {
6610 pathv.push_back(loc->path(j));
6611 }
6612
6613 std::map<std::vector<int>, std::vector<int>>::iterator entry =
6614 interpreted_paths_.find(pathv);
6615
6616 if (entry == interpreted_paths_.end()) {
6617 // not a match
6618 if (copying) {
6619 *new_locs.Add() = *loc;
6620 }
6621 continue;
6622 }
6623
6624 matched = true;
6625
6626 if (!copying) {
6627 // initialize the copy we are building
6628 copying = true;
6629 new_locs.Reserve(locs->size());
6630 for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it =
6631 locs->begin();
6632 it != loc; it++) {
6633 *new_locs.Add() = *it;
6634 }
6635 }
6636
6637 // add replacement and update its path
6638 SourceCodeInfo_Location* replacement = new_locs.Add();
6639 *replacement = *loc;
6640 replacement->clear_path();
6641 for (std::vector<int>::iterator rit = entry->second.begin();
6642 rit != entry->second.end(); rit++) {
6643 replacement->add_path(*rit);
6644 }
6645 }
6646
6647 // if we made a changed copy, put it in place
6648 if (copying) {
6649 *locs = new_locs;
6650 }
6651 }
6652
AddWithoutInterpreting(const UninterpretedOption & uninterpreted_option,Message * options)6653 void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
6654 const UninterpretedOption& uninterpreted_option, Message* options) {
6655 const FieldDescriptor* field =
6656 options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6657 GOOGLE_CHECK(field != nullptr);
6658
6659 options->GetReflection()
6660 ->AddMessage(options, field)
6661 ->CopyFrom(uninterpreted_option);
6662 }
6663
ExamineIfOptionIsSet(std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_iter,std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_end,const FieldDescriptor * innermost_field,const std::string & debug_msg_name,const UnknownFieldSet & unknown_fields)6664 bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
6665 std::vector<const FieldDescriptor*>::const_iterator
6666 intermediate_fields_iter,
6667 std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
6668 const FieldDescriptor* innermost_field, const std::string& debug_msg_name,
6669 const UnknownFieldSet& unknown_fields) {
6670 // We do linear searches of the UnknownFieldSet and its sub-groups. This
6671 // should be fine since it's unlikely that any one options structure will
6672 // contain more than a handful of options.
6673
6674 if (intermediate_fields_iter == intermediate_fields_end) {
6675 // We're at the innermost submessage.
6676 for (int i = 0; i < unknown_fields.field_count(); i++) {
6677 if (unknown_fields.field(i).number() == innermost_field->number()) {
6678 return AddNameError("Option \"" + debug_msg_name +
6679 "\" was already set.");
6680 }
6681 }
6682 return true;
6683 }
6684
6685 for (int i = 0; i < unknown_fields.field_count(); i++) {
6686 if (unknown_fields.field(i).number() ==
6687 (*intermediate_fields_iter)->number()) {
6688 const UnknownField* unknown_field = &unknown_fields.field(i);
6689 FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
6690 // Recurse into the next submessage.
6691 switch (type) {
6692 case FieldDescriptor::TYPE_MESSAGE:
6693 if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
6694 UnknownFieldSet intermediate_unknown_fields;
6695 if (intermediate_unknown_fields.ParseFromString(
6696 unknown_field->length_delimited()) &&
6697 !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6698 intermediate_fields_end, innermost_field,
6699 debug_msg_name,
6700 intermediate_unknown_fields)) {
6701 return false; // Error already added.
6702 }
6703 }
6704 break;
6705
6706 case FieldDescriptor::TYPE_GROUP:
6707 if (unknown_field->type() == UnknownField::TYPE_GROUP) {
6708 if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6709 intermediate_fields_end, innermost_field,
6710 debug_msg_name, unknown_field->group())) {
6711 return false; // Error already added.
6712 }
6713 }
6714 break;
6715
6716 default:
6717 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
6718 return false;
6719 }
6720 }
6721 }
6722 return true;
6723 }
6724
SetOptionValue(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)6725 bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
6726 const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
6727 // We switch on the CppType to validate.
6728 switch (option_field->cpp_type()) {
6729 case FieldDescriptor::CPPTYPE_INT32:
6730 if (uninterpreted_option_->has_positive_int_value()) {
6731 if (uninterpreted_option_->positive_int_value() >
6732 static_cast<uint64>(kint32max)) {
6733 return AddValueError("Value out of range for int32 option \"" +
6734 option_field->full_name() + "\".");
6735 } else {
6736 SetInt32(option_field->number(),
6737 uninterpreted_option_->positive_int_value(),
6738 option_field->type(), unknown_fields);
6739 }
6740 } else if (uninterpreted_option_->has_negative_int_value()) {
6741 if (uninterpreted_option_->negative_int_value() <
6742 static_cast<int64>(kint32min)) {
6743 return AddValueError("Value out of range for int32 option \"" +
6744 option_field->full_name() + "\".");
6745 } else {
6746 SetInt32(option_field->number(),
6747 uninterpreted_option_->negative_int_value(),
6748 option_field->type(), unknown_fields);
6749 }
6750 } else {
6751 return AddValueError("Value must be integer for int32 option \"" +
6752 option_field->full_name() + "\".");
6753 }
6754 break;
6755
6756 case FieldDescriptor::CPPTYPE_INT64:
6757 if (uninterpreted_option_->has_positive_int_value()) {
6758 if (uninterpreted_option_->positive_int_value() >
6759 static_cast<uint64>(kint64max)) {
6760 return AddValueError("Value out of range for int64 option \"" +
6761 option_field->full_name() + "\".");
6762 } else {
6763 SetInt64(option_field->number(),
6764 uninterpreted_option_->positive_int_value(),
6765 option_field->type(), unknown_fields);
6766 }
6767 } else if (uninterpreted_option_->has_negative_int_value()) {
6768 SetInt64(option_field->number(),
6769 uninterpreted_option_->negative_int_value(),
6770 option_field->type(), unknown_fields);
6771 } else {
6772 return AddValueError("Value must be integer for int64 option \"" +
6773 option_field->full_name() + "\".");
6774 }
6775 break;
6776
6777 case FieldDescriptor::CPPTYPE_UINT32:
6778 if (uninterpreted_option_->has_positive_int_value()) {
6779 if (uninterpreted_option_->positive_int_value() > kuint32max) {
6780 return AddValueError("Value out of range for uint32 option \"" +
6781 option_field->name() + "\".");
6782 } else {
6783 SetUInt32(option_field->number(),
6784 uninterpreted_option_->positive_int_value(),
6785 option_field->type(), unknown_fields);
6786 }
6787 } else {
6788 return AddValueError(
6789 "Value must be non-negative integer for uint32 "
6790 "option \"" +
6791 option_field->full_name() + "\".");
6792 }
6793 break;
6794
6795 case FieldDescriptor::CPPTYPE_UINT64:
6796 if (uninterpreted_option_->has_positive_int_value()) {
6797 SetUInt64(option_field->number(),
6798 uninterpreted_option_->positive_int_value(),
6799 option_field->type(), unknown_fields);
6800 } else {
6801 return AddValueError(
6802 "Value must be non-negative integer for uint64 "
6803 "option \"" +
6804 option_field->full_name() + "\".");
6805 }
6806 break;
6807
6808 case FieldDescriptor::CPPTYPE_FLOAT: {
6809 float value;
6810 if (uninterpreted_option_->has_double_value()) {
6811 value = uninterpreted_option_->double_value();
6812 } else if (uninterpreted_option_->has_positive_int_value()) {
6813 value = uninterpreted_option_->positive_int_value();
6814 } else if (uninterpreted_option_->has_negative_int_value()) {
6815 value = uninterpreted_option_->negative_int_value();
6816 } else {
6817 return AddValueError("Value must be number for float option \"" +
6818 option_field->full_name() + "\".");
6819 }
6820 unknown_fields->AddFixed32(option_field->number(),
6821 internal::WireFormatLite::EncodeFloat(value));
6822 break;
6823 }
6824
6825 case FieldDescriptor::CPPTYPE_DOUBLE: {
6826 double value;
6827 if (uninterpreted_option_->has_double_value()) {
6828 value = uninterpreted_option_->double_value();
6829 } else if (uninterpreted_option_->has_positive_int_value()) {
6830 value = uninterpreted_option_->positive_int_value();
6831 } else if (uninterpreted_option_->has_negative_int_value()) {
6832 value = uninterpreted_option_->negative_int_value();
6833 } else {
6834 return AddValueError("Value must be number for double option \"" +
6835 option_field->full_name() + "\".");
6836 }
6837 unknown_fields->AddFixed64(option_field->number(),
6838 internal::WireFormatLite::EncodeDouble(value));
6839 break;
6840 }
6841
6842 case FieldDescriptor::CPPTYPE_BOOL:
6843 uint64 value;
6844 if (!uninterpreted_option_->has_identifier_value()) {
6845 return AddValueError(
6846 "Value must be identifier for boolean option "
6847 "\"" +
6848 option_field->full_name() + "\".");
6849 }
6850 if (uninterpreted_option_->identifier_value() == "true") {
6851 value = 1;
6852 } else if (uninterpreted_option_->identifier_value() == "false") {
6853 value = 0;
6854 } else {
6855 return AddValueError(
6856 "Value must be \"true\" or \"false\" for boolean "
6857 "option \"" +
6858 option_field->full_name() + "\".");
6859 }
6860 unknown_fields->AddVarint(option_field->number(), value);
6861 break;
6862
6863 case FieldDescriptor::CPPTYPE_ENUM: {
6864 if (!uninterpreted_option_->has_identifier_value()) {
6865 return AddValueError(
6866 "Value must be identifier for enum-valued option "
6867 "\"" +
6868 option_field->full_name() + "\".");
6869 }
6870 const EnumDescriptor* enum_type = option_field->enum_type();
6871 const std::string& value_name = uninterpreted_option_->identifier_value();
6872 const EnumValueDescriptor* enum_value = nullptr;
6873
6874 if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
6875 // Note that the enum value's fully-qualified name is a sibling of the
6876 // enum's name, not a child of it.
6877 std::string fully_qualified_name = enum_type->full_name();
6878 fully_qualified_name.resize(fully_qualified_name.size() -
6879 enum_type->name().size());
6880 fully_qualified_name += value_name;
6881
6882 // Search for the enum value's descriptor in the builder's pool. Note
6883 // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
6884 // DescriptorPool::FindEnumValueByName() because we're already holding
6885 // the pool's mutex, and the latter method locks it again.
6886 Symbol symbol =
6887 builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
6888 if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) {
6889 if (symbol.enum_value_descriptor->type() != enum_type) {
6890 return AddValueError(
6891 "Enum type \"" + enum_type->full_name() +
6892 "\" has no value named \"" + value_name + "\" for option \"" +
6893 option_field->full_name() +
6894 "\". This appears to be a value from a sibling type.");
6895 } else {
6896 enum_value = symbol.enum_value_descriptor;
6897 }
6898 }
6899 } else {
6900 // The enum type is in the generated pool, so we can search for the
6901 // value there.
6902 enum_value = enum_type->FindValueByName(value_name);
6903 }
6904
6905 if (enum_value == nullptr) {
6906 return AddValueError("Enum type \"" +
6907 option_field->enum_type()->full_name() +
6908 "\" has no value named \"" + value_name +
6909 "\" for "
6910 "option \"" +
6911 option_field->full_name() + "\".");
6912 } else {
6913 // Sign-extension is not a problem, since we cast directly from int32 to
6914 // uint64, without first going through uint32.
6915 unknown_fields->AddVarint(
6916 option_field->number(),
6917 static_cast<uint64>(static_cast<int64>(enum_value->number())));
6918 }
6919 break;
6920 }
6921
6922 case FieldDescriptor::CPPTYPE_STRING:
6923 if (!uninterpreted_option_->has_string_value()) {
6924 return AddValueError(
6925 "Value must be quoted string for string option "
6926 "\"" +
6927 option_field->full_name() + "\".");
6928 }
6929 // The string has already been unquoted and unescaped by the parser.
6930 unknown_fields->AddLengthDelimited(option_field->number(),
6931 uninterpreted_option_->string_value());
6932 break;
6933
6934 case FieldDescriptor::CPPTYPE_MESSAGE:
6935 if (!SetAggregateOption(option_field, unknown_fields)) {
6936 return false;
6937 }
6938 break;
6939 }
6940
6941 return true;
6942 }
6943
6944 class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
6945 : public TextFormat::Finder {
6946 public:
6947 DescriptorBuilder* builder_;
6948
FindExtension(Message * message,const std::string & name) const6949 const FieldDescriptor* FindExtension(Message* message,
6950 const std::string& name) const override {
6951 assert_mutex_held(builder_->pool_);
6952 const Descriptor* descriptor = message->GetDescriptor();
6953 Symbol result =
6954 builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name());
6955 if (result.type == Symbol::FIELD &&
6956 result.field_descriptor->is_extension()) {
6957 return result.field_descriptor;
6958 } else if (result.type == Symbol::MESSAGE &&
6959 descriptor->options().message_set_wire_format()) {
6960 const Descriptor* foreign_type = result.descriptor;
6961 // The text format allows MessageSet items to be specified using
6962 // the type name, rather than the extension identifier. If the symbol
6963 // lookup returned a Message, and the enclosing Message has
6964 // message_set_wire_format = true, then return the message set
6965 // extension, if one exists.
6966 for (int i = 0; i < foreign_type->extension_count(); i++) {
6967 const FieldDescriptor* extension = foreign_type->extension(i);
6968 if (extension->containing_type() == descriptor &&
6969 extension->type() == FieldDescriptor::TYPE_MESSAGE &&
6970 extension->is_optional() &&
6971 extension->message_type() == foreign_type) {
6972 // Found it.
6973 return extension;
6974 }
6975 }
6976 }
6977 return nullptr;
6978 }
6979 };
6980
6981 // A custom error collector to record any text-format parsing errors
6982 namespace {
6983 class AggregateErrorCollector : public io::ErrorCollector {
6984 public:
6985 std::string error_;
6986
AddError(int,int,const std::string & message)6987 void AddError(int /* line */, int /* column */,
6988 const std::string& message) override {
6989 if (!error_.empty()) {
6990 error_ += "; ";
6991 }
6992 error_ += message;
6993 }
6994
AddWarning(int,int,const std::string &)6995 void AddWarning(int /* line */, int /* column */,
6996 const std::string& /* message */) override {
6997 // Ignore warnings
6998 }
6999 };
7000 } // namespace
7001
7002 // We construct a dynamic message of the type corresponding to
7003 // option_field, parse the supplied text-format string into this
7004 // message, and serialize the resulting message to produce the value.
SetAggregateOption(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)7005 bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
7006 const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
7007 if (!uninterpreted_option_->has_aggregate_value()) {
7008 return AddValueError("Option \"" + option_field->full_name() +
7009 "\" is a message. To set the entire message, use "
7010 "syntax like \"" +
7011 option_field->name() +
7012 " = { <proto text format> }\". "
7013 "To set fields within it, use "
7014 "syntax like \"" +
7015 option_field->name() + ".foo = value\".");
7016 }
7017
7018 const Descriptor* type = option_field->message_type();
7019 std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
7020 GOOGLE_CHECK(dynamic.get() != nullptr)
7021 << "Could not create an instance of " << option_field->DebugString();
7022
7023 AggregateErrorCollector collector;
7024 AggregateOptionFinder finder;
7025 finder.builder_ = builder_;
7026 TextFormat::Parser parser;
7027 parser.RecordErrorsTo(&collector);
7028 parser.SetFinder(&finder);
7029 if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
7030 dynamic.get())) {
7031 AddValueError("Error while parsing option value for \"" +
7032 option_field->name() + "\": " + collector.error_);
7033 return false;
7034 } else {
7035 std::string serial;
7036 dynamic->SerializeToString(&serial); // Never fails
7037 if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
7038 unknown_fields->AddLengthDelimited(option_field->number(), serial);
7039 } else {
7040 GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
7041 UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
7042 group->ParseFromString(serial);
7043 }
7044 return true;
7045 }
7046 }
7047
SetInt32(int number,int32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7048 void DescriptorBuilder::OptionInterpreter::SetInt32(
7049 int number, int32 value, FieldDescriptor::Type type,
7050 UnknownFieldSet* unknown_fields) {
7051 switch (type) {
7052 case FieldDescriptor::TYPE_INT32:
7053 unknown_fields->AddVarint(number,
7054 static_cast<uint64>(static_cast<int64>(value)));
7055 break;
7056
7057 case FieldDescriptor::TYPE_SFIXED32:
7058 unknown_fields->AddFixed32(number, static_cast<uint32>(value));
7059 break;
7060
7061 case FieldDescriptor::TYPE_SINT32:
7062 unknown_fields->AddVarint(
7063 number, internal::WireFormatLite::ZigZagEncode32(value));
7064 break;
7065
7066 default:
7067 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
7068 break;
7069 }
7070 }
7071
SetInt64(int number,int64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7072 void DescriptorBuilder::OptionInterpreter::SetInt64(
7073 int number, int64 value, FieldDescriptor::Type type,
7074 UnknownFieldSet* unknown_fields) {
7075 switch (type) {
7076 case FieldDescriptor::TYPE_INT64:
7077 unknown_fields->AddVarint(number, static_cast<uint64>(value));
7078 break;
7079
7080 case FieldDescriptor::TYPE_SFIXED64:
7081 unknown_fields->AddFixed64(number, static_cast<uint64>(value));
7082 break;
7083
7084 case FieldDescriptor::TYPE_SINT64:
7085 unknown_fields->AddVarint(
7086 number, internal::WireFormatLite::ZigZagEncode64(value));
7087 break;
7088
7089 default:
7090 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
7091 break;
7092 }
7093 }
7094
SetUInt32(int number,uint32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7095 void DescriptorBuilder::OptionInterpreter::SetUInt32(
7096 int number, uint32 value, FieldDescriptor::Type type,
7097 UnknownFieldSet* unknown_fields) {
7098 switch (type) {
7099 case FieldDescriptor::TYPE_UINT32:
7100 unknown_fields->AddVarint(number, static_cast<uint64>(value));
7101 break;
7102
7103 case FieldDescriptor::TYPE_FIXED32:
7104 unknown_fields->AddFixed32(number, static_cast<uint32>(value));
7105 break;
7106
7107 default:
7108 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
7109 break;
7110 }
7111 }
7112
SetUInt64(int number,uint64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7113 void DescriptorBuilder::OptionInterpreter::SetUInt64(
7114 int number, uint64 value, FieldDescriptor::Type type,
7115 UnknownFieldSet* unknown_fields) {
7116 switch (type) {
7117 case FieldDescriptor::TYPE_UINT64:
7118 unknown_fields->AddVarint(number, value);
7119 break;
7120
7121 case FieldDescriptor::TYPE_FIXED64:
7122 unknown_fields->AddFixed64(number, value);
7123 break;
7124
7125 default:
7126 GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
7127 break;
7128 }
7129 }
7130
LogUnusedDependency(const FileDescriptorProto & proto,const FileDescriptor * result)7131 void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
7132 const FileDescriptor* result) {
7133
7134 if (!unused_dependency_.empty()) {
7135 std::set<std::string> annotation_extensions;
7136 annotation_extensions.insert("google.protobuf.MessageOptions");
7137 annotation_extensions.insert("google.protobuf.FileOptions");
7138 annotation_extensions.insert("google.protobuf.FieldOptions");
7139 annotation_extensions.insert("google.protobuf.EnumOptions");
7140 annotation_extensions.insert("google.protobuf.EnumValueOptions");
7141 annotation_extensions.insert("google.protobuf.EnumValueOptions");
7142 annotation_extensions.insert("google.protobuf.ServiceOptions");
7143 annotation_extensions.insert("google.protobuf.MethodOptions");
7144 annotation_extensions.insert("google.protobuf.StreamOptions");
7145 for (std::set<const FileDescriptor*>::const_iterator it =
7146 unused_dependency_.begin();
7147 it != unused_dependency_.end(); ++it) {
7148 // Do not log warnings for proto files which extend annotations.
7149 int i;
7150 for (i = 0; i < (*it)->extension_count(); ++i) {
7151 if (annotation_extensions.find(
7152 (*it)->extension(i)->containing_type()->full_name()) !=
7153 annotation_extensions.end()) {
7154 break;
7155 }
7156 }
7157 // Log warnings for unused imported files.
7158 if (i == (*it)->extension_count()) {
7159 std::string error_message =
7160 "Import " + (*it)->name() + " but not used.";
7161 AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
7162 error_message);
7163 }
7164 }
7165 }
7166 }
7167
CrossLinkOnDemandHelper(const std::string & name,bool expecting_enum) const7168 Symbol DescriptorPool::CrossLinkOnDemandHelper(const std::string& name,
7169 bool expecting_enum) const {
7170 std::string lookup_name = name;
7171 if (!lookup_name.empty() && lookup_name[0] == '.') {
7172 lookup_name = lookup_name.substr(1);
7173 }
7174 Symbol result = tables_->FindByNameHelper(this, lookup_name);
7175 return result;
7176 }
7177
7178 // Handle the lazy import building for a message field whose type wasn't built
7179 // at cross link time. If that was the case, we saved the name of the type to
7180 // be looked up when the accessor for the type was called. Set type_,
7181 // enum_type_, message_type_, and default_value_enum_ appropriately.
InternalTypeOnceInit() const7182 void FieldDescriptor::InternalTypeOnceInit() const {
7183 GOOGLE_CHECK(file()->finished_building_ == true);
7184 if (type_name_) {
7185 Symbol result = file()->pool()->CrossLinkOnDemandHelper(
7186 *type_name_, type_ == FieldDescriptor::TYPE_ENUM);
7187 if (result.type == Symbol::MESSAGE) {
7188 type_ = FieldDescriptor::TYPE_MESSAGE;
7189 message_type_ = result.descriptor;
7190 } else if (result.type == Symbol::ENUM) {
7191 type_ = FieldDescriptor::TYPE_ENUM;
7192 enum_type_ = result.enum_descriptor;
7193 }
7194 }
7195 if (enum_type_ && !default_value_enum_) {
7196 if (default_value_enum_name_) {
7197 // Have to build the full name now instead of at CrossLink time,
7198 // because enum_type_ may not be known at the time.
7199 std::string name = enum_type_->full_name();
7200 // Enum values reside in the same scope as the enum type.
7201 std::string::size_type last_dot = name.find_last_of('.');
7202 if (last_dot != std::string::npos) {
7203 name = name.substr(0, last_dot) + "." + *default_value_enum_name_;
7204 } else {
7205 name = *default_value_enum_name_;
7206 }
7207 Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
7208 if (result.type == Symbol::ENUM_VALUE) {
7209 default_value_enum_ = result.enum_value_descriptor;
7210 }
7211 }
7212 if (!default_value_enum_) {
7213 // We use the first defined value as the default
7214 // if a default is not explicitly defined.
7215 GOOGLE_CHECK(enum_type_->value_count());
7216 default_value_enum_ = enum_type_->value(0);
7217 }
7218 }
7219 }
7220
TypeOnceInit(const FieldDescriptor * to_init)7221 void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
7222 to_init->InternalTypeOnceInit();
7223 }
7224
7225 // message_type(), enum_type(), default_value_enum(), and type()
7226 // all share the same internal::call_once init path to do lazy
7227 // import building and cross linking of a field of a message.
message_type() const7228 const Descriptor* FieldDescriptor::message_type() const {
7229 if (type_once_) {
7230 internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7231 }
7232 return message_type_;
7233 }
7234
enum_type() const7235 const EnumDescriptor* FieldDescriptor::enum_type() const {
7236 if (type_once_) {
7237 internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7238 }
7239 return enum_type_;
7240 }
7241
default_value_enum() const7242 const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
7243 if (type_once_) {
7244 internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7245 }
7246 return default_value_enum_;
7247 }
7248
PrintableNameForExtension() const7249 const std::string& FieldDescriptor::PrintableNameForExtension() const {
7250 const bool is_message_set_extension =
7251 is_extension() &&
7252 containing_type()->options().message_set_wire_format() &&
7253 type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
7254 extension_scope() == message_type();
7255 return is_message_set_extension ? message_type()->full_name() : full_name();
7256 }
7257
InternalDependenciesOnceInit() const7258 void FileDescriptor::InternalDependenciesOnceInit() const {
7259 GOOGLE_CHECK(finished_building_ == true);
7260 for (int i = 0; i < dependency_count(); i++) {
7261 if (dependencies_names_[i]) {
7262 dependencies_[i] = pool_->FindFileByName(*dependencies_names_[i]);
7263 }
7264 }
7265 }
7266
DependenciesOnceInit(const FileDescriptor * to_init)7267 void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
7268 to_init->InternalDependenciesOnceInit();
7269 }
7270
dependency(int index) const7271 const FileDescriptor* FileDescriptor::dependency(int index) const {
7272 if (dependencies_once_) {
7273 // Do once init for all indices, as it's unlikely only a single index would
7274 // be called, and saves on internal::call_once allocations.
7275 internal::call_once(*dependencies_once_,
7276 FileDescriptor::DependenciesOnceInit, this);
7277 }
7278 return dependencies_[index];
7279 }
7280
input_type() const7281 const Descriptor* MethodDescriptor::input_type() const {
7282 return input_type_.Get();
7283 }
7284
output_type() const7285 const Descriptor* MethodDescriptor::output_type() const {
7286 return output_type_.Get();
7287 }
7288
7289
7290 namespace internal {
Set(const Descriptor * descriptor)7291 void LazyDescriptor::Set(const Descriptor* descriptor) {
7292 GOOGLE_CHECK(!name_);
7293 GOOGLE_CHECK(!once_);
7294 GOOGLE_CHECK(!file_);
7295 descriptor_ = descriptor;
7296 }
7297
SetLazy(const std::string & name,const FileDescriptor * file)7298 void LazyDescriptor::SetLazy(const std::string& name,
7299 const FileDescriptor* file) {
7300 // verify Init() has been called and Set hasn't been called yet.
7301 GOOGLE_CHECK(!descriptor_);
7302 GOOGLE_CHECK(!file_);
7303 GOOGLE_CHECK(!name_);
7304 GOOGLE_CHECK(!once_);
7305 GOOGLE_CHECK(file && file->pool_);
7306 GOOGLE_CHECK(file->pool_->lazily_build_dependencies_);
7307 GOOGLE_CHECK(!file->finished_building_);
7308 file_ = file;
7309 name_ = file->pool_->tables_->AllocateString(name);
7310 once_ = file->pool_->tables_->AllocateOnceDynamic();
7311 }
7312
Once()7313 void LazyDescriptor::Once() {
7314 if (once_) {
7315 internal::call_once(*once_, LazyDescriptor::OnceStatic, this);
7316 }
7317 }
7318
OnceStatic(LazyDescriptor * lazy)7319 void LazyDescriptor::OnceStatic(LazyDescriptor* lazy) { lazy->OnceInternal(); }
7320
OnceInternal()7321 void LazyDescriptor::OnceInternal() {
7322 GOOGLE_CHECK(file_->finished_building_);
7323 if (!descriptor_ && name_) {
7324 Symbol result = file_->pool_->CrossLinkOnDemandHelper(*name_, false);
7325 if (!result.IsNull() && result.type == Symbol::MESSAGE) {
7326 descriptor_ = result.descriptor;
7327 }
7328 }
7329 }
7330 } // namespace internal
7331
7332 } // namespace protobuf
7333 } // namespace google
7334