Visitar URL original
Simpler and faster C code to handle structs · msgpack/msgpack-ruby@1c81f0a · GitHub
Skip to content

Commit 1c81f0a

Browse files
committed
Simpler and faster C code to handle structs
1 parent 40af3f3 commit 1c81f0a

1 file changed

Lines changed: 9 additions & 45 deletions

File tree

‎ext/msgpack/unpacker.c‎

Lines changed: 9 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -489,57 +489,21 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
489489
reset_head_byte(uk);
490490
uk->reading_raw_remaining = 0;
491491

492-
/* Get struct members */
493-
VALUE members = rb_struct_s_members(struct_class);
494-
long num_fields = RARRAY_LEN(members);
495-
496-
/* Check if this is a keyword_init struct (Ruby 2.7+) */
497-
VALUE keyword_init = Qfalse;
498-
if (rb_respond_to(struct_class, rb_intern("keyword_init?"))) {
499-
keyword_init = rb_funcall(struct_class, rb_intern("keyword_init?"), 0);
500-
}
501-
502492
/* Push a recursive marker so nested reads don't prematurely return */
503493
_msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
504494

505-
VALUE obj;
506-
if (num_fields == 0) {
507-
/* Special case for empty structs */
508-
obj = rb_class_new_instance(0, NULL, struct_class);
509-
} else if (RTEST(keyword_init)) {
510-
/* For keyword_init structs, build a hash with member names as keys */
511-
VALUE kwargs = rb_hash_new();
512-
for (long i = 0; i < num_fields; i++) {
513-
int ret = msgpack_unpacker_read(uk, 0);
514-
if (ret < 0) {
515-
msgpack_unpacker_stack_pop(uk);
516-
return ret;
517-
}
518-
VALUE key = rb_ary_entry(members, i);
519-
rb_hash_aset(kwargs, key, uk->last_object);
520-
}
521-
/* Call new with keyword arguments */
522-
obj = rb_class_new_instance_kw(1, &kwargs, struct_class, RB_PASS_KEYWORDS);
523-
} else {
524-
/* For regular structs, use positional arguments
525-
* Use RB_ALLOCV to avoid stack overflow with large structs */
526-
VALUE allocv_holder;
527-
VALUE *values = RB_ALLOCV_N(VALUE, allocv_holder, num_fields);
528-
for (int i = 0; i < num_fields; i++) {
529-
int ret = msgpack_unpacker_read(uk, 0);
530-
if (ret < 0) {
531-
msgpack_unpacker_stack_pop(uk);
532-
RB_ALLOCV_END(allocv_holder);
533-
return ret;
534-
}
535-
values[i] = uk->last_object;
495+
VALUE obj = rb_obj_alloc(struct_class);
496+
long num_fields = RSTRUCT_LEN(obj);
497+
498+
for (int i = 0; i < num_fields; i++) {
499+
int ret = msgpack_unpacker_read(uk, 0);
500+
if (RB_UNLIKELY(ret < 0)) {
501+
msgpack_unpacker_stack_pop(uk);
502+
return ret;
536503
}
537-
obj = rb_class_new_instance((int)num_fields, values, struct_class);
538-
RB_ALLOCV_END(allocv_holder);
504+
RSTRUCT_SET(obj, i, uk->last_object);
539505
}
540506

541-
RB_GC_GUARD(struct_class);
542-
RB_GC_GUARD(members);
543507
msgpack_unpacker_stack_pop(uk);
544508
return object_complete(uk, obj);
545509
}

0 commit comments

Comments
 (0)