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