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