| 
					
				 | 
			
			
				@@ -32,6 +32,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //  Based on original Protocol Buffers design by 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 //  Sanjay Ghemawat, Jeff Dean, and others. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <functional> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <limits> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <map> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <queue> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -75,7 +76,7 @@ string DotsToColons(const string& name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return StringReplace(name, ".", "::", true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const char* const kKeywordList[] = {  // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const char* const kKeywordList[] = {  // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "NULL", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "alignas", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "alignof", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -160,15 +161,15 @@ const char* const kKeywordList[] = {  // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "xor", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "xor_eq"}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-std::unordered_set<string> MakeKeywordsMap() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  std::unordered_set<string> result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    result.insert(kKeywordList[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static std::unordered_set<string>* MakeKeywordsMap() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  auto* result = new std::unordered_set<string>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (const auto keyword : kKeywordList) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result->emplace(keyword); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-std::unordered_set<string> kKeywords = MakeKeywordsMap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static std::unordered_set<string>& kKeywords = *MakeKeywordsMap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Returns whether the provided descriptor has an extension. This includes its 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // nested types. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -255,6 +256,7 @@ void SetCommonVars(const Options& options, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "ECK"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  SetIntVar(options, "int8", variables); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SetIntVar(options, "uint8", variables); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SetIntVar(options, "uint32", variables); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SetIntVar(options, "uint64", variables); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -910,11 +912,7 @@ FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 bool IsAnyMessage(const FileDescriptor* descriptor, const Options& options) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // For now we do not support Any in lite mode, so if we're building for lite 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // then we just treat Any as if it's an ordinary message with no special 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // behavior. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return descriptor->name() == kAnyProtoFile && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         GetOptimizeFor(descriptor, options) != FileOptions::LITE_RUNTIME; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return descriptor->name() == kAnyProtoFile; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 bool IsAnyMessage(const Descriptor* descriptor, const Options& options) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1302,14 +1300,20 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void GenerateParserLoop(const Descriptor* descriptor) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Set("classname", ClassName(descriptor)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    format_.Set("proto_ns", ProtobufNamespace(options_)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    format_.Set("p_ns", "::" + ProtobufNamespace(options_)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    format_.Set("pi_ns", StrCat("::", ProtobufNamespace(options_), "::internal")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Set("GOOGLE_PROTOBUF", MacroPrefix(options_)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    format_.Set("kSlopBytes", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                static_cast<int>(internal::ParseContext::kSlopBytes)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::map<string, string> vars; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     SetCommonVars(options_, &vars); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.AddMap(vars); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::vector<const FieldDescriptor*> ordered_fields; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (auto field : FieldRange(descriptor)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (IsProto1(descriptor->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (field->number() >= (1 << 14)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       ordered_fields.push_back(field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     std::sort(ordered_fields.begin(), ordered_fields.end(), 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1318,19 +1322,11 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "const char* $classname$::_InternalParse(const char* begin, const " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "char* " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "end, void* object,\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "                  ::$proto_ns$::internal::ParseContext* ctx) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  auto msg = static_cast<$classname$*>(object);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  $int32$ size; (void)size;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  int depth; (void)depth;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  $uint32$ tag;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  ::$proto_ns$::internal::ParseFunc parser_till_end; " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "(void)parser_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  auto ptr = begin;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  while (ptr < end) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "    ptr = ::$proto_ns$::io::Parse32(ptr, &tag);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "const char* $classname$::_InternalParse(const char* ptr, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "$pi_ns$::ParseContext* ctx) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "  while (!ctx->Done(&ptr)) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    $uint32$ tag;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    ptr = $pi_ns$::ReadTag(ptr, &tag);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "    $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "    switch (tag >> 3) {\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1338,11 +1334,7 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Indent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Indent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    bool use_handle_unusual = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for (const auto* field : ordered_fields) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (IsProto1(descriptor->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (field->number() >= (1 << 14)) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // Print the field's (or oneof's) proto-syntax definition as a comment. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // We don't want to print group bodies so we cut off after the first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // line. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1359,22 +1351,21 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           "case $2$: {\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           def, field->number()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_.Indent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      use_handle_unusual = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       GenerateCaseBody(field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_.Outdent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_("}\n");  // case 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }                  // for fields 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Default case 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_("default: {\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (use_handle_unusual) format_("handle_unusual:\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!ordered_fields.empty()) format_("handle_unusual:\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "  if ((tag & 7) == 4 || tag == 0) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "    ctx->EndGroup(tag);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "    ctx->SetLastTag(tag);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "    return ptr;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "  }\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (IsMapEntryMessage(descriptor)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  break;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "}\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      format_("  break;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (descriptor->extension_range_count() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         format_("if ("); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1396,113 +1387,59 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         format_(") {\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "  auto res = msg->_extensions_.ParseField(tag, {_InternalParse, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "msg}, ptr, end,\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "      internal_default_instance(), &msg->_internal_metadata_, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "  ptr = _extensions_.ParseField(tag, ptr, \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "      internal_default_instance(), &_internal_metadata_, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "ctx);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "  ptr = res.first;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr != nullptr);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "  if (res.second) return ptr;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "  continue;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "  break;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "}\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  auto res = UnknownFieldParse(tag, {_InternalParse, msg},\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "    ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "ctx);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  ptr = res.first;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "  ptr = UnknownFieldParse(tag,\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "    _internal_metadata_.mutable_unknown_fields(), ptr, ctx);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr != nullptr);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  if (res.second) return ptr;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "}\n");  // default case 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "  break;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    format_("}\n");  // default case 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Outdent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Outdent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_.Outdent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "    }  // switch\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         "  }  // while\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  return ptr;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (use_string_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "string_till_end:\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  static_cast<$string$*>(object)->clear();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // TODO(gerbens) evaluate security 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  static_cast<$string$*>(object)->reserve(size);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  goto len_delim_till_end;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (use_arena_string_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "arena_string_till_end:\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  object = " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "static_cast<::$proto_ns$::internal::ArenaStringPtr*>(object)->" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "msg->GetArenaNoVirtual());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  static_cast<$string$*>(object)->clear();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          // TODO(gerbens) evaluate security 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  static_cast<$string$*>(object)->reserve(size);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  goto len_delim_till_end;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (use_length_delimited_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "len_delim_till_end:\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "                               {parser_till_end, object}, size);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (use_group_) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // Group crossed end and must be continued. Either this a parse failure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // or we need to resume on the next chunk and thus save the state. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "group_continues:\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  $DCHK$(ptr >= end);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  $GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->StoreGroup(\n   " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "   {_InternalParse, msg}, {parser_till_end, object}, depth, tag));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "  return ptr;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    format_("}\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "  return ptr;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "}\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  private: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageSCCAnalyzer* scc_analyzer_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const Options& options_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Formatter format_; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool use_length_delimited_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool use_group_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool use_string_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool use_arena_string_ = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   using WireFormat = internal::WireFormat; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   using WireFormatLite = internal::WireFormatLite; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void GenerateArenaString(const FieldDescriptor* field, const string& utf8) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    use_arena_string_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  void GenerateArenaString(const FieldDescriptor* field, const string& utf8, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           const string& field_name) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (HasFieldPresence(field->file())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_("HasBitSetters::set_has_$1$(msg);\n", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      format_("HasBitSetters::set_has_$1$(this);\n", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "if (size > end - ptr + " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "::$proto_ns$::internal::ParseContext::kSlopBytes) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  object = &msg->$1$_;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  parser_till_end = ::$proto_ns$::internal::GreedyStringParser$2$;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  goto arena_string_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "}\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(::$proto_ns$::internal::StringCheck$2$" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "(ptr, size, ctx));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "::$proto_ns$::internal::CopyIntoArenaString(ptr, size, &msg->$1$_, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "msg->GetArenaNoVirtual());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "ptr += size;\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        FieldName(field), utf8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "ptr = $pi_ns$::InlineCopyIntoArenaString$1$(&$2$_, ptr, ctx, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "GetArenaNoVirtual()$3$);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        utf8, FieldName(field), field_name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void GenerateStrings(const FieldDescriptor* field, bool check_utf8) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     string utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    string field_name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (check_utf8) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       utf8 = GetUtf8Suffix(field, options_); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (!utf8.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        string name = "nullptr"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        field_name = ", nullptr"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (HasDescriptorMethods(field->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          name = "\"" + field->full_name() + "\""; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          field_name = StrCat(", \"", field->full_name(), "\""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_("ctx->extra_parse_data().SetFieldName($1$);\n", name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     FieldOptions::CType ctype = FieldOptions::STRING; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1523,73 +1460,40 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         !IsProto1(field->file(), options_) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         !IsStringInlined(field, options_) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         field->containing_oneof() == nullptr && ctype == FieldOptions::STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      GenerateArenaString(field, utf8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      GenerateArenaString(field, utf8, field_name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "object = msg->$1$_$2$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "if (size > end - ptr + " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "::$proto_ns$::internal::ParseContext::kSlopBytes) {\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        field->is_repeated() && !field->is_packable() ? "add" : "mutable", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     string name; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    string label = "len_delim_till_end"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch (ctype) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case FieldOptions::STRING: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name = "GreedyStringParser"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        use_string_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        label = "string_till_end"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        name = "GreedyStringParser" + utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case FieldOptions::CORD: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name = "CordParser"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_("  static_cast<::Cord*>(object)->Clear();\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        name = "CordParser" + utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case FieldOptions::STRING_PIECE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name = "StringPieceParser"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "  " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "static_cast<::$proto_ns$::internal::StringPieceField*>(object)->" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "Clear();\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        name = "StringPieceParser" + utf8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  parser_till_end = ::$proto_ns$::internal::$1$$2$;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "  goto $3$;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "}\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(::$proto_ns$::internal::StringCheck$2$" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "(ptr, size, ctx));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "::$proto_ns$::internal::Inline$1$(object, ptr, size, ctx);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "ptr += size;\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name, utf8, label); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "ptr = $pi_ns$::Inline$1$($2$_$3$(), ptr, ctx$4$);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        name, field->is_repeated() && !field->is_packable() ? "add" : "mutable", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        FieldName(field), field_name); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void GenerateLengthDelim(const FieldDescriptor* field) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "ptr = ::$proto_ns$::io::ReadSize(ptr, &size);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!IsProto1(field->file(), options_) && field->is_packable()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      string enum_validator; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (!HasPreservingUnknownEnumSemantics(field->file()) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           field->type() == FieldDescriptor::TYPE_ENUM) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "ctx->extra_parse_data().SetEnumValidator($1$_IsValid, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "msg->mutable_unknown_fields(), $2$);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "parser_till_end = " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "::$proto_ns$::internal::PackedValidEnumParser$3$;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "object = msg->mutable_$4$();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            QualifiedClassName(field->enum_type()), field->number(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            UseUnknownFieldSet(field->file(), options_) ? "" : "Lite", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "parser_till_end = ::$proto_ns$::internal::Packed$1$Parser;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "object = msg->mutable_$2$();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            DeclaredTypeMethodName(field->type()), FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        enum_validator = StrCat( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ", ", QualifiedClassName(field->enum_type()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "_IsValid, mutable_unknown_fields(), ", field->number()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "if (size > end - ptr) goto len_delim_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "auto newend = ptr + size;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "if (size) ptr = parser_till_end(ptr, newend, object, ctx);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr == newend);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "ptr = $pi_ns$::Packed$1$Parser(mutable_$2$(), ptr, ctx$3$);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          DeclaredTypeMethodName(field->type()), FieldName(field), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          enum_validator); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       auto field_type = field->type(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (IsProto1(field->file(), options_)) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1610,106 +1514,62 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           GenerateStrings(field, false /* utf8 */); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case FieldDescriptor::TYPE_MESSAGE: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          GOOGLE_CHECK(field->message_type()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if (!IsProto1(field->file(), options_) && field->is_map()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            const FieldDescriptor* val = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                field->message_type()->FindFieldByName("value"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            GOOGLE_CHECK(val); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (HasFieldPresence(field->file()) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val->type() == FieldDescriptor::TYPE_ENUM) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "ctx->extra_parse_data().field_number = $1$;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "ctx->extra_parse_data().unknown_fields = " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "&msg->_internal_metadata_;\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  field->number()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "parser_till_end = " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "::$proto_ns$::internal::SlowMapEntryParser;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "auto parse_map = $1$::_ParseMap;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "ctx->extra_parse_data().payload.clear();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "ctx->extra_parse_data().parse_map = parse_map;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object = &msg->$2$_;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "if (size > end - ptr) goto len_delim_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "auto newend = ptr + size;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "$GOOGLE_PROTOBUF$_PARSER_ASSERT(parse_map(ptr, newend, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object, ctx));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "ptr = newend;\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                QualifiedClassName(field->message_type()), FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (!IsProto1(field->file(), options_) && IsLazy(field, options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            format_("ptr = ctx->ParseMessage(&$1$_, ptr);\n", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else if (!IsProto1(field->file(), options_) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                     IsLazy(field, options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (field->containing_oneof() != nullptr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "if (!msg->has_$1$()) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "  msg->clear_$1$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "  msg->$2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "      ::$proto_ns$::internal::LazyField>(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "msg->GetArenaNoVirtual());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "  msg->set_has_$1$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "if (!has_$1$()) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "  clear_$1$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "  $2$_.$1$_ = ::$proto_ns$::Arena::CreateMessage<\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "      $pi_ns$::LazyField>(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "GetArenaNoVirtual());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "  set_has_$1$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   "}\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "auto parse_closure = msg->$2$_.$1$_->_ParseClosure();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage($2$_.$1$_, ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   FieldName(field), field->containing_oneof()->name()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else if (HasFieldPresence(field->file())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "HasBitSetters::set_has_$1$(msg);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "auto parse_closure = msg->$1$_._ParseClosure();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "HasBitSetters::set_has_$1$(this);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(&$1$_, ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              format_("auto parse_closure = msg->$1$_._ParseClosure();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                      FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(&$1$_, ptr);\n", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "parser_till_end = parse_closure.func;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object = parse_closure.object;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "if (size > end - ptr) goto len_delim_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "auto newend = ptr + size;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->ParseExactRange(\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "    parse_closure, ptr, newend));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "ptr = newend;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (IsImplicitWeakField(field, options_, scc_analyzer_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else if (IsImplicitWeakField(field, options_, scc_analyzer_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!field->is_repeated()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              format_("object = HasBitSetters::mutable_$1$(msg);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                      FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(HasBitSetters::mutable_$1$(this), " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "object = " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "CastToBase(&msg->$1$_)->AddWeak(reinterpret_cast<const " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "::$proto_ns$::MessageLite*>(&$2$::_$3$_default_instance_));" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "CastToBase(&$1$_)->AddWeak(reinterpret_cast<const " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "::$proto_ns$::MessageLite*>(&$2$::_$3$_default_instance_)), " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   FieldName(field), Namespace(field->message_type()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   ClassName(field->message_type())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "parser_till_end = static_cast<::$proto_ns$::MessageLite*>(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object)->_ParseFunc();\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else if (IsWeak(field, options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (IsProto1(field->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              format_("object = msg->internal_mutable_$1$();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                      FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "reinterpret_cast<$p_ns$::MessageLite*>(internal_mutable_$1$(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  ")), ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "object = msg->_weak_field_map_.MutableMessage($1$, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  "_$classname$_default_instance_.$2$_);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  "ptr = ctx->ParseMessage(_weak_field_map_.MutableMessage($1$," 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  " _$classname$_default_instance_.$2$_), ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   field->number(), FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "parser_till_end = static_cast<::$proto_ns$::MessageLite*>(" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object)->_ParseFunc();\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "parser_till_end = $1$::_InternalParse;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "object = msg->$2$_$3$();\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                QualifiedClassName(field->message_type()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                field->is_repeated() ? "add" : "mutable", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            format_("ptr = ctx->ParseMessage($1$_$2$(), ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    field->is_repeated() ? "add" : "mutable", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              "if (size > end - ptr) goto len_delim_till_end;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              "ptr += size;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ctx->ParseExactRange(\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              "    {parser_till_end, object}, ptr - size, ptr));\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         default: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1731,31 +1591,33 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         string prefix = field->is_repeated() ? "add" : "set"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (field->type() == FieldDescriptor::TYPE_ENUM && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             !IsProto1(field->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          format_("$uint64$ val = ::$proto_ns$::internal::ReadVarint(&ptr);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              "$uint64$ val = $pi_ns$::ReadVarint(&ptr);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if (!HasPreservingUnknownEnumSemantics(field->file())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "if (!$1$_IsValid(val)) {\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "  ::$proto_ns$::internal::WriteVarint($2$, val, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "msg->mutable_unknown_fields());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "  $pi_ns$::WriteVarint($2$, val, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                "mutable_unknown_fields());\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "  break;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 "}\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 QualifiedClassName(field->enum_type()), field->number()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          format_("msg->$1$_$2$(static_cast<$3$>(val));\n", prefix, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  FieldName(field), QualifiedClassName(field->enum_type())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          format_("$1$_$2$(static_cast<$3$>(val));\n", prefix, FieldName(field), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  QualifiedClassName(field->enum_type())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          int size = field->type() == FieldDescriptor::TYPE_SINT32 ? 32 : 64; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           string zigzag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if ((field->type() == FieldDescriptor::TYPE_SINT32 || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                field->type() == FieldDescriptor::TYPE_SINT64) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               !IsProto1(field->file(), options_)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int size = field->type() == FieldDescriptor::TYPE_SINT32 ? 32 : 64; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             zigzag = StrCat("ZigZag", size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              "msg->$1$_$2$(::$proto_ns$::internal::ReadVarint$3$(&ptr));\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              "$1$_$2$($pi_ns$::ReadVarint$3$(&ptr));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               prefix, FieldName(field), zigzag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        format_("$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case WireFormatLite::WIRETYPE_FIXED32: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1763,28 +1625,20 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         string prefix = field->is_repeated() ? "add" : "set"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         string type = PrimitiveTypeName(options_, field->cpp_type()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "msg->$1$_$2$(::$proto_ns$::io::UnalignedLoad<$3$>(ptr));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "$1$_$2$($pi_ns$::UnalignedLoad<$3$>(ptr));\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             "ptr += sizeof($3$);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             prefix, FieldName(field), type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        use_length_delimited_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         GenerateLengthDelim(field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        format_("$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case WireFormatLite::WIRETYPE_START_GROUP: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        use_group_ = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "parser_till_end = $1$::_InternalParse;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "object = msg->$2$_$3$();\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "auto res = ctx->ParseGroup(tag, {parser_till_end, object}, ptr, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "end, " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "&depth);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "ptr = res.first;\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "if (res.second) goto group_continues;\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            QualifiedClassName(field->message_type()), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "ptr = ctx->ParseGroup($1$_$2$(), ptr, tag);\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             field->is_repeated() ? "add" : "mutable", FieldName(field)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1795,7 +1649,6 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }  // switch (wire_type) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (ShouldRepeat(field, wiretype)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      format_("if (ptr >= end) break;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       uint32 x = field->number() * 8 + wiretype; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       uint64 y = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       int cnt = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1805,10 +1658,11 @@ class ParseLoopGenerator { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         x >>= 7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } while (x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       uint64 mask = (1ull << (cnt * 8)) - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      format_("if (ctx->Done(&ptr)) return ptr;\n"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_.Outdent(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       format_( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "} while ((::$proto_ns$::io::UnalignedLoad<$uint64$>(ptr) & $1$) == " 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "$2$ && (ptr += $3$));\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "} while (($pi_ns$::UnalignedLoad<$uint64$>(ptr)" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          " & $1$) == $2$ && (ptr += $3$));\n", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           mask, y, cnt); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     format_("break;\n"); 
			 |