void layout_deep_copy(MessageLayout* layout, void* to, void* from) { upb_msg_field_iter it; for (upb_msg_field_begin(&it, layout->msgdef); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* field = upb_msg_iter_field(&it); void* to_memory = slot_memory(layout, to, field); uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); void* from_memory = slot_memory(layout, from, field); uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); if (upb_fielddef_containingoneof(field)) { if (*from_oneof_case == upb_fielddef_number(field)) { *to_oneof_case = *from_oneof_case; native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); } } else if (is_map_field(field)) { DEREF(to_memory, VALUE) = Map_deep_copy(DEREF(from_memory, VALUE)); } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { DEREF(to_memory, VALUE) = RepeatedField_deep_copy(DEREF(from_memory, VALUE)); } else { if (field_contains_hasbit(layout, field)) { if (!slot_is_hasbit_set(layout, from, field)) continue; slot_set_hasbit(layout, to, field); } native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); } } }
// Used by Google::Protobuf.deep_copy but not exposed directly. VALUE Map_deep_copy(VALUE _self) { Map* self = ruby_to_Map(_self); VALUE new_map = Map_new_this_type(_self); Map* new_self = ruby_to_Map(new_map); upb_strtable_iter it; for (upb_strtable_begin(&it, &self->table); !upb_strtable_done(&it); upb_strtable_next(&it)) { upb_value v = upb_strtable_iter_value(&it); void* mem = value_memory(&v); upb_value dup; void* dup_mem = value_memory(&dup); native_slot_deep_copy(self->value_type, dup_mem, mem); if (!upb_strtable_insert2(&new_self->table, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it), dup)) { rb_raise(rb_eRuntimeError, "Error inserting value into new table"); } } return new_map; }
// Internal only: used by Google::Protobuf.deep_copy. VALUE RepeatedField_deep_copy(VALUE _self) { RepeatedField* self = ruby_to_RepeatedField(_self); VALUE new_rptfield = RepeatedField_new_this_type(_self); RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield); RepeatedField_reserve(new_rptfield_self, self->size); upb_fieldtype_t field_type = self->field_type; size_t elem_size = native_slot_size(field_type); size_t off = 0; for (int i = 0; i < self->size; i++, off += elem_size) { void* to_mem = (uint8_t *)new_rptfield_self->elements + off; void* from_mem = (uint8_t *)self->elements + off; native_slot_deep_copy(field_type, to_mem, from_mem); new_rptfield_self->size++; } return new_rptfield; }