Skip to content

Commit

Permalink
panko_serializer: more robust and cache push_value
Browse files Browse the repository at this point in the history
  • Loading branch information
yosiat committed Nov 2, 2024
1 parent 1e4a23a commit 05ef610
Showing 1 changed file with 64 additions and 5 deletions.
69 changes: 64 additions & 5 deletions ext/panko_serializer/panko_serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include "time_conversion.h"

static ID push_value_id;

VALUE public_is_iso8601_time_string(VALUE klass, VALUE value) {
return is_iso8601_time_string(StringValuePtr(value)) ? Qtrue : Qfalse;
}
Expand All @@ -10,13 +12,70 @@ VALUE public_iso_ar_iso_datetime_string(VALUE klass, VALUE value) {
return iso_ar_iso_datetime_string(StringValuePtr(value));
}

static VALUE datetime_writer_write(VALUE self, VALUE value, VALUE writer,
VALUE key) {
if (RB_TYPE_P(value, T_STRING)) {
const char* val = StringValuePtr(value);

// 'Z' in ISO8601 says it's UTC
if (val[strlen(val) - 1] == 'Z' && is_iso8601_time_string(val) == Qtrue) {
rb_funcall(writer, push_value_id, 2, value, key);
return Qtrue;
}

volatile VALUE iso8601_string = iso_ar_iso_datetime_string(val);
if (iso8601_string != Qnil) {
rb_funcall(writer, push_value_id, 2, iso8601_string, key);
return Qtrue;
}
}

return Qfalse;
}

// Helper function to safely get a constant if it exists
static VALUE safe_const_get(VALUE parent, const char* name) {
if (rb_const_defined(parent, rb_intern(name))) {
return rb_const_get(parent, rb_intern(name));
}
return Qnil;
}

void Init_panko_serializer() {
VALUE mPanko = rb_define_module("Panko");
push_value_id = rb_intern("push_value");

rb_define_singleton_method(mPanko, "is_iso8601_time_string",
public_is_iso8601_time_string, 1);
rb_define_singleton_method(mPanko, "iso_ar_iso_datetime_string",
public_iso_ar_iso_datetime_string, 1);
VALUE mPanko = rb_define_module("Panko");

panko_init_time(mPanko);

VALUE impl = safe_const_get(mPanko, "Impl");
if (NIL_P(impl)) {
printf("Not patching\n");
return;
}

VALUE attributes_writer = safe_const_get(impl, "AttributesWriter");
if (NIL_P(attributes_writer)) {
printf("Not patching\n");
return;
}

VALUE active_record = safe_const_get(attributes_writer, "ActiveRecord");
if (NIL_P(active_record)) {
printf("Not patching\n");
return;
}

VALUE values_writer = safe_const_get(active_record, "ValuesWriter");
if (NIL_P(values_writer)) {
printf("Not patching\n");
return;
}

VALUE cDateTimeWriter = safe_const_get(values_writer, "DateTimeWriter");
if (NIL_P(cDateTimeWriter)) {
printf("Not patching\n");
} else {
rb_define_method(cDateTimeWriter, "write", datetime_writer_write, 3);
}
}

0 comments on commit 05ef610

Please sign in to comment.