| 
					
				 | 
			
			
				@@ -117,18 +117,18 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t ofs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int32_t hasbit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const upb_msgdef *md; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE subklass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } submsg_handlerdata_t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Creates a handlerdata that contains offset and submessage type information. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static const void *newsubmsghandlerdata(upb_handlers* h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         uint32_t ofs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                         int32_t hasbit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                        const upb_fielddef* f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        VALUE subklass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->ofs = ofs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->hasbit = hasbit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  hd->md = upb_fielddef_msgsubdef(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hd->subklass = subklass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_addcleanup(h, hd, xfree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -137,13 +137,14 @@ typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t ofs;              // union data slot 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t case_ofs;         // oneof_case field 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uint32_t oneof_case_num; // oneof-case number to place in oneof_case field 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const upb_msgdef *md;    // msgdef, for oneof submessage handler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE subklass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } oneof_handlerdata_t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static const void *newoneofhandlerdata(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                        uint32_t ofs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                        uint32_t case_ofs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                       const upb_fielddef *f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       const upb_fielddef *f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->ofs = ofs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->case_ofs = case_ofs; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -154,11 +155,7 @@ static const void *newoneofhandlerdata(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // create a separate ID space. In addition, using the field tag number here 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // lets us easily look up the field in the oneof accessor. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->oneof_case_num = upb_fielddef_number(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    hd->md = upb_fielddef_msgsubdef(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    hd->md = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hd->subklass = field_type_class(desc->layout, f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_addcleanup(h, hd, xfree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -254,13 +251,13 @@ static size_t stringdata_handler(void* closure, const void* hd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool stringdata_end_handler(void* closure, const void* hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE rb_str = closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE rb_str = (VALUE)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rb_obj_freeze(rb_str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool appendstring_end_handler(void* closure, const void* hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE rb_str = closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE rb_str = (VALUE)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rb_obj_freeze(rb_str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -269,12 +266,9 @@ static bool appendstring_end_handler(void* closure, const void* hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void *appendsubmsg_handler(void *closure, const void *hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   VALUE ary = (VALUE)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const submsg_handlerdata_t *submsgdata = hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subdesc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      get_def_obj((void*)submsgdata->md); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subklass = Descriptor_msgclass(subdesc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* submsg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE submsg_rb = rb_class_new_instance(0, NULL, submsgdata->subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   RepeatedField_push(ary, submsg_rb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -285,15 +279,12 @@ static void *appendsubmsg_handler(void *closure, const void *hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void *submsg_handler(void *closure, const void *hd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* msg = closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const submsg_handlerdata_t* submsgdata = hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subdesc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      get_def_obj((void*)submsgdata->md); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subklass = Descriptor_msgclass(subdesc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   VALUE submsg_rb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* submsg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DEREF(msg, submsgdata->ofs, VALUE) = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rb_class_new_instance(0, NULL, subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rb_class_new_instance(0, NULL, submsgdata->subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   set_hasbit(closure, submsgdata->hasbit); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -309,11 +300,7 @@ typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t ofs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_fieldtype_t key_field_type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_fieldtype_t value_field_type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // We know that we can hold this reference because the handlerdata has the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // same lifetime as the upb_handlers struct, and the upb_handlers struct holds 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // a reference to the upb_msgdef, which in turn has references to its subdefs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const upb_def* value_field_subdef; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE subklass; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } map_handlerdata_t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Temporary frame for map parsing: at the beginning of a map entry message, a 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -383,19 +370,8 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       mapdata->key_field_type, Qnil, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       &frame->key_storage); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE value_field_typeclass = Qnil; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (mapdata->value_field_type == UPB_TYPE_MESSAGE || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      mapdata->value_field_type == UPB_TYPE_ENUM) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    value_field_typeclass = get_def_obj(mapdata->value_field_subdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (mapdata->value_field_type == UPB_TYPE_ENUM) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      value_field_typeclass = EnumDescriptor_enummodule(value_field_typeclass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  value = native_slot_get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      mapdata->value_field_type, value_field_typeclass, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VALUE value = native_slot_get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      mapdata->value_field_type, mapdata->subklass, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       &frame->value_storage); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Map_index_set(frame->map, key, value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -414,7 +390,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static map_handlerdata_t* new_map_handlerdata( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     size_t ofs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const upb_msgdef* mapentry_def, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* key_field; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* value_field; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   map_handlerdata_t* hd = ALLOC(map_handlerdata_t); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -425,7 +401,7 @@ static map_handlerdata_t* new_map_handlerdata( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert(value_field != NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hd->value_field_type = upb_fielddef_type(value_field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  hd->value_field_subdef = upb_fielddef_subdef(value_field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hd->subklass = field_type_class(desc->layout, value_field); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -491,16 +467,13 @@ static void *oneofsubmsg_handler(void *closure, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const oneof_handlerdata_t *oneofdata = hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subdesc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      get_def_obj((void*)oneofdata->md); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  VALUE subklass = Descriptor_msgclass(subdesc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   VALUE submsg_rb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* submsg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (oldcase != oneofdata->oneof_case_num || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       DEREF(msg, oneofdata->ofs, VALUE) == Qnil) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DEREF(msg, oneofdata->ofs, VALUE) = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        rb_class_new_instance(0, NULL, subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        rb_class_new_instance(0, NULL, oneofdata->subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Set the oneof case *after* allocating the new class instance -- otherwise, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // if the Ruby GC is invoked as part of a call into the VM, it might invoke 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -518,12 +491,12 @@ static void *oneofsubmsg_handler(void *closure, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Set up handlers for a repeated field. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void add_handlers_for_repeated_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                             const upb_fielddef *f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                             size_t offset) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, -1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  attr.handler_data = newhandlerdata(h, offset, -1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_setstartseq(h, f, startseq_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   switch (upb_fielddef_type(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -554,20 +527,20 @@ static void add_handlers_for_repeated_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case UPB_TYPE_MESSAGE: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, -1, f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      VALUE subklass = field_type_class(desc->layout, f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      attr.handler_data = newsubmsghandlerdata(h, 0, -1, subklass); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Set up handlers for a singular field. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void add_handlers_for_singular_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                            const upb_fielddef *f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                            size_t offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                            size_t hasbit_off) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void add_handlers_for_singular_field(const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            upb_handlers* h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            const upb_fielddef* f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            size_t offset, size_t hasbit_off) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // The offset we pass to UPB points to the start of the Message, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // rather than the start of where our data is stored. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int32_t hasbit = -1; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -589,23 +562,20 @@ static void add_handlers_for_singular_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case UPB_TYPE_STRING: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case UPB_TYPE_BYTES: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset, hasbit)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      attr.handler_data = newhandlerdata(h, offset, hasbit); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_handlers_setstartstr(h, f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                is_bytes ? bytes_handler : str_handler, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_handlers_setstring(h, f, stringdata_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_handlers_setendstr(h, f, stringdata_end_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case UPB_TYPE_MESSAGE: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_sethandlerdata(&attr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				     newsubmsghandlerdata(h, offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							  hasbit, f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      attr.handler_data = newsubmsghandlerdata( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          h, offset, hasbit, field_type_class(desc->layout, f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -615,36 +585,34 @@ static void add_handlers_for_singular_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void add_handlers_for_mapfield(upb_handlers* h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                       const upb_fielddef* fielddef, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                       size_t offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                      Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                      const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_addcleanup(h, hd, xfree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_sethandlerdata(&attr, hd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  attr.handler_data = hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Adds handlers to a map-entry msgdef. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void add_handlers_for_mapentry(const upb_msgdef* msgdef, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                      upb_handlers* h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                      Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                      const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* key_field = map_entry_key(msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* value_field = map_entry_value(msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_addcleanup(h, hd, xfree); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_sethandlerdata(&attr, hd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  attr.handler_data = hd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_setendmsg(h, endmap_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   add_handlers_for_singular_field( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      h, key_field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      desc, h, key_field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       offsetof(map_parse_frame_t, key_storage), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       MESSAGE_FIELD_NO_HASBIT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   add_handlers_for_singular_field( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      h, value_field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      desc, h, value_field, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       offsetof(map_parse_frame_t, value_storage), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       MESSAGE_FIELD_NO_HASBIT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -653,11 +621,11 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void add_handlers_for_oneof_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                          const upb_fielddef *f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                          size_t offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                         size_t oneof_case_offset) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_sethandlerdata( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &attr, newoneofhandlerdata(h, offset, oneof_case_offset, f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         size_t oneof_case_offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  attr.handler_data = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      newoneofhandlerdata(h, offset, oneof_case_offset, f, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   switch (upb_fielddef_type(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -692,15 +660,13 @@ static void add_handlers_for_oneof_field(upb_handlers *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr_uninit(&attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool unknown_field_handler(void* closure, const void* hd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                   const char* buf, size_t size) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  MessageHeader* msg = (MessageHeader*)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   UPB_UNUSED(hd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  MessageHeader* msg = (MessageHeader*)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (msg->unknown_fields == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     msg->unknown_fields = malloc(sizeof(stringsink)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     stringsink_init(msg->unknown_fields); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -711,27 +677,29 @@ static bool unknown_field_handler(void* closure, const void* hd, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void add_handlers_for_message(const void *closure, upb_handlers *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void add_handlers_for_message(const void *closure, upb_handlers *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const VALUE descriptor_pool = (VALUE)closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_msgdef* msgdef = upb_handlers_msgdef(h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Descriptor* desc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_msg_field_iter i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // If this is a mapentry message type, set up a special set of handlers and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // bail out of the normal (user-defined) message type handling. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (upb_msgdef_mapentry(msgdef)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    add_handlers_for_mapentry(msgdef, h, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_handlerattr attr = UPB_HANDLERATTR_INIT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // Ensure layout exists. We may be invoked to create handlers for a given 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // message if we are included as a submsg of another message type before our 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // class is actually built, so to work around this, we just create the layout 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // (and handlers, in the class-building function) on-demand. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (desc->layout == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    desc->layout = create_layout(desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    desc->layout = create_layout(desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // If this is a mapentry message type, set up a special set of handlers and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // bail out of the normal (user-defined) message type handling. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (upb_msgdef_mapentry(msgdef)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    add_handlers_for_mapentry(msgdef, h, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_handlers_setunknown(h, unknown_field_handler, &attr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (upb_msg_field_begin(&i, desc->msgdef); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -745,64 +713,51 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       size_t oneof_case_offset = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           desc->layout->fields[upb_fielddef_index(f)].case_offset + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           sizeof(MessageHeader); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else if (is_map_field(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       add_handlers_for_mapfield(h, f, offset, desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else if (upb_fielddef_isseq(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      add_handlers_for_repeated_field(h, f, offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      add_handlers_for_repeated_field(h, desc, f, offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       add_handlers_for_singular_field( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          h, f, offset, desc->layout->fields[upb_fielddef_index(f)].hasbit); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          desc, h, f, offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          desc->layout->fields[upb_fielddef_index(f)].hasbit); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Creates upb handlers for populating a message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const upb_handlers *new_fill_handlers(Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                             const void* owner) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // TODO(cfallin, haberman): once upb gets a caching/memoization layer for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // handlers, reuse subdef handlers so that e.g. if we already parse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // parse A-with-field-of-type-B-with-field-of-type-C. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return upb_handlers_newfrozen(desc->msgdef, owner, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                add_handlers_for_message, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Constructs the handlers for filling a message's data into an in-memory 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // object. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const upb_handlers* get_fill_handlers(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!desc->fill_handlers) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    desc->fill_handlers = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        new_fill_handlers(desc, &desc->fill_handlers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return desc->fill_handlers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Constructs the upb decoder method for parsing messages of this type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// This is called from the message class creation code. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                     const void* owner) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const upb_handlers* handlers = get_fill_handlers(desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_pbdecodermethodopts opts; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_pbdecodermethodopts_init(&opts, handlers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return upb_pbdecodermethod_new(&opts, owner); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (desc->fill_method == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    desc->fill_method = new_fillmsg_decodermethod( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        desc, &desc->fill_method); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return desc->fill_method; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (desc->json_fill_method == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    desc->json_fill_method = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        upb_json_parsermethod_new(desc->msgdef, &desc->json_fill_method); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const upb_handlers* msgdef_json_serialize_handlers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Descriptor* desc, bool preserve_proto_fieldnames) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (preserve_proto_fieldnames) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return upb_handlercache_get(pool->json_serialize_handler_preserve_cache, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return upb_handlercache_get(pool->json_serialize_handler_cache, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                desc->msgdef); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return desc->json_fill_method; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -812,7 +767,8 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // if any error occurs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define STACK_ENV_STACKBYTES 4096 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_env env; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_arena *arena; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_status status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const char* ruby_error_template; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   char allocbuf[STACK_ENV_STACKBYTES]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } stackenv; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -820,29 +776,22 @@ typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void stackenv_init(stackenv* se, const char* errmsg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void stackenv_uninit(stackenv* se); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// Callback invoked by upb if any error occurs during parsing or serialization. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static bool env_error_func(void* ud, const upb_status* status) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  stackenv* se = ud; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Free the env -- rb_raise will longjmp up the stack past the encode/decode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // function so it would not otherwise have been freed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  stackenv_uninit(se); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // TODO(haberman): have a way to verify that this is actually a parse error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // instead of just throwing "parse error" unconditionally. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // Never reached: rb_raise() always longjmp()s up the stack, past all of our 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // code, back to Ruby. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void stackenv_init(stackenv* se, const char* errmsg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   se->ruby_error_template = errmsg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_env_seterrorfunc(&se->env, env_error_func, se); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  se->arena = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_status_clear(&se->status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void stackenv_uninit(stackenv* se) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_env_uninit(&se->env); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_arena_free(se->arena); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!upb_ok(&se->status)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // TODO(haberman): have a way to verify that this is actually a parse error, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // instead of just throwing "parse error" unconditionally. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rb_raise(cParseError, se->ruby_error_template, errmsg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -873,10 +822,10 @@ VALUE Message_decode(VALUE klass, VALUE data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     stackenv se; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_sink sink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_pbdecoder* decoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stackenv_init(&se, "Error occurred during parsing: %s"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_sink_reset(&sink, h, msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    decoder = upb_pbdecoder_create(&se.env, method, &sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       upb_pbdecoder_input(decoder)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -894,8 +843,9 @@ VALUE Message_decode(VALUE klass, VALUE data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * format) under the interpretration given by this message class's definition 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * and returns a message object with the corresponding field values. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * @param options [Hash] options for the decoder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- *   ignore_unknown_fields: set true to ignore unknown fields (default is to raise an error) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  @param options [Hash] options for the decoder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   ignore_unknown_fields: set true to ignore unknown fields (default is to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   raise an error) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -923,6 +873,7 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (TYPE(data) != T_STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rb_raise(rb_eArgError, "Expected string for JSON data."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // convert, because string handlers pass data directly to message string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   // fields. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -936,11 +887,11 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_sink sink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_json_parser* parser; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stackenv_init(&se, "Error occurred during parsing: %s"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_sink_reset(&sink, get_fill_handlers(desc), msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    parser = upb_json_parser_create(&se.env, method, pool->symtab, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    &sink, ignore_unknown_fields); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    parser = upb_json_parser_create(se.arena, method, pool->symtab, sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    &se.status, RTEST(ignore_unknown_fields)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       upb_json_parser_input(parser)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -956,9 +907,8 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* msgvisitor *****************************************************************/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putmsg(VALUE msg, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   upb_sink *sink, int depth, bool emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   bool is_json, bool open_msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   bool emit_defaults, bool is_json, bool open_msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_selector_t ret; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -967,7 +917,7 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink subsink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (str == Qnil) return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -984,12 +934,12 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     &subsink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                      RSTRING_LEN(str), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       int depth, bool emit_defaults, bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink subsink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   VALUE descriptor; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1001,16 +951,17 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   subdesc = ruby_to_Descriptor(descriptor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  putmsg(submsg, subdesc, &subsink, depth + 1, emit_defaults, is_json, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   int depth, bool emit_defaults, bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   bool emit_defaults, bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink subsink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_fieldtype_t type = upb_fielddef_type(f); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_selector_t sel = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (ary == Qnil) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1024,12 +975,12 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (int i = 0; i < size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     void* memory = RepeatedField_index_native(ary, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch (type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define T(upbtypeconst, upbtype, ctype)                         \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  case upbtypeconst:                                            \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory));   \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define T(upbtypeconst, upbtype, ctype)                     \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case upbtypeconst:                                        \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       T(UPB_TYPE_FLOAT,  float,  float) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1043,11 +994,10 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case UPB_TYPE_STRING: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case UPB_TYPE_BYTES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        putstr(*((VALUE *)memory), f, &subsink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        putstr(*((VALUE *)memory), f, subsink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case UPB_TYPE_MESSAGE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        putsubmsg(*((VALUE *)memory), f, &subsink, depth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  emit_defaults, is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        putsubmsg(*((VALUE*)memory), f, subsink, depth, emit_defaults, is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #undef T 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1057,19 +1007,16 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void put_ruby_value(VALUE value, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           const upb_fielddef *f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           VALUE type_class, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           int depth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                           bool emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                           int depth, upb_sink sink, bool emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  upb_selector_t sel = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (depth > ENCODE_MAX_NESTING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rb_raise(rb_eRuntimeError, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              "Maximum recursion depth exceeded during encoding."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  upb_selector_t sel = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (upb_fielddef_isprimitive(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1112,8 +1059,8 @@ static void put_ruby_value(VALUE value, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   int depth, bool emit_defaults, bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   bool emit_defaults, bool is_json) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   Map* self; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink subsink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* key_field; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1137,17 +1084,17 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_status status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_sink entry_sink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                          &entry_sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_startmsg(&entry_sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink_startmsg(entry_sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   emit_defaults, is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     put_ruby_value(value, value_field, self->value_type_class, depth + 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   &entry_sink, emit_defaults, is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   entry_sink, emit_defaults, is_json); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_endmsg(&entry_sink, &status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink_endmsg(entry_sink, &status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink_endsubmsg(subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1156,8 +1103,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static const upb_handlers* msgdef_json_serialize_handlers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     Descriptor* desc, bool preserve_proto_fieldnames); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void putjsonany(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                       upb_sink* sink, int depth, bool emit_defaults) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                       int depth, bool emit_defaults) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_status status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* msg = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1204,16 +1151,14 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     uint32_t value_offset; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     VALUE value_str_rb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const char* value_str; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     size_t value_len; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     value_str_rb = DEREF(Message_data(msg), value_offset, VALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    value_str = RSTRING_PTR(value_str_rb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     value_len = RSTRING_LEN(value_str_rb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (value_len > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      VALUE payload_desc_rb = get_def_obj(payload_type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       VALUE payload_class = Descriptor_msgclass(payload_desc_rb); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_sink subsink; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1231,8 +1176,8 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       subsink.handlers = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           msgdef_json_serialize_handlers(payload_desc, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      subsink.closure = sink->closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      putmsg(payload_msg_rb, payload_desc, &subsink, depth, emit_defaults, true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      subsink.closure = sink.closure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				              is_wellknown); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1242,7 +1187,7 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void putjsonlistvalue( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink* sink, int depth, bool emit_defaults) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    upb_sink sink, int depth, bool emit_defaults) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_status status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_sink subsink; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* msg = NULL; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1269,7 +1214,7 @@ static void putjsonlistvalue( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void putmsg(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                   upb_sink *sink, int depth, bool emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   upb_sink sink, int depth, bool emit_defaults, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                    bool is_json, bool open_msg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   MessageHeader* msg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   upb_msg_field_iter i; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1360,20 +1305,19 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#define T(upbtypeconst, upbtype, ctype, default_value)                          \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  case upbtypeconst: {                                                          \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      ctype value = DEREF(msg, offset, ctype);                                  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      bool is_default = false;                                                  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (upb_fielddef_haspresence(f)) {                                        \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse;  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {        \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        is_default = default_value == value;                                    \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      }                                                                         \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (is_matching_oneof || emit_defaults || !is_default) {                  \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        upb_sink_put##upbtype(sink, sel, value);                                \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      }                                                                         \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }                                                                           \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define T(upbtypeconst, upbtype, ctype, default_value)                       \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case upbtypeconst: {                                                       \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctype value = DEREF(msg, offset, ctype);                                 \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool is_default = false;                                                 \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (upb_fielddef_haspresence(f)) {                                       \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) {       \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      is_default = default_value == value;                                   \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }                                                                        \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (is_matching_oneof || emit_defaults || !is_default) {                 \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_sink_put##upbtype(sink, sel, value);                               \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }                                                                        \ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       switch (upb_fielddef_type(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         T(UPB_TYPE_FLOAT,  float,  float, 0.0) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1395,9 +1339,11 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  stringsink* unknown = msg->unknown_fields; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (unknown != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    upb_sink_putunknown(sink, unknown->ptr, unknown->len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stringsink* unknown = msg->unknown_fields; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (unknown != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      upb_sink_putunknown(sink, unknown->ptr, unknown->len); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (open_msg) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1405,33 +1351,6 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (desc->pb_serialize_handlers == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    desc->pb_serialize_handlers = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return desc->pb_serialize_handlers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static const upb_handlers* msgdef_json_serialize_handlers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    Descriptor* desc, bool preserve_proto_fieldnames) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (preserve_proto_fieldnames) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (desc->json_serialize_handlers == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      desc->json_serialize_handlers = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          upb_json_printer_newhandlers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              desc->msgdef, true, &desc->json_serialize_handlers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return desc->json_serialize_handlers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (desc->json_serialize_handlers_preserve == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      desc->json_serialize_handlers_preserve = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          upb_json_printer_newhandlers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              desc->msgdef, false, &desc->json_serialize_handlers_preserve); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return desc->json_serialize_handlers_preserve; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * call-seq: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  *     MessageClass.encode(msg) => bytes 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1454,8 +1373,8 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     upb_pb_encoder* encoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     VALUE ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stackenv_init(&se, "Error occurred during encoding: %s"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1512,8 +1431,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     stackenv se; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     VALUE ret; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stackenv_init(&se, "Error occurred during encoding: %s"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    printer = upb_json_printer_create(&se.env, serialize_handlers, &sink.sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     putmsg(msg_rb, desc, upb_json_printer_input(printer), 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            RTEST(emit_defaults), true, true); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1533,10 +1452,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  stringsink* unknown = msg->unknown_fields; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (unknown != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    stringsink_uninit(unknown); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    msg->unknown_fields = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    stringsink* unknown = msg->unknown_fields; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (unknown != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      stringsink_uninit(unknown); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      msg->unknown_fields = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (upb_msg_field_begin(&it, desc->msgdef); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1566,10 +1487,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (is_map_field(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      VALUE map; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      Map_iter map_it; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (!upb_fielddef_issubmsg(map_field_value(f))) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      VALUE map = DEREF(msg, offset, VALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      map = DEREF(msg, offset, VALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (map == Qnil) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      Map_iter map_it; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         VALUE submsg = Map_iter_value(&map_it); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1578,9 +1501,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else if (upb_fielddef_isseq(f)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       VALUE ary = DEREF(msg, offset, VALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      int size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      int i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (ary == Qnil) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      int size = NUM2INT(RepeatedField_length(ary)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      for (int i = 0; i < size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      size = NUM2INT(RepeatedField_length(ary)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (i = 0; i < size; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         void* memory = RepeatedField_index_native(ary, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         VALUE submsg = *((VALUE *)memory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1589,9 +1515,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       VALUE submsg = DEREF(msg, offset, VALUE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      VALUE descriptor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const Descriptor* subdesc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (submsg == Qnil) continue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      const Descriptor* subdesc = ruby_to_Descriptor(descriptor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      subdesc = ruby_to_Descriptor(descriptor); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       discard_unknown(submsg, subdesc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 |