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