Skip to content

Commit a0584ce

Browse files
committed
DateTimeWriter: write in native
1 parent 90e9879 commit a0584ce

File tree

2 files changed

+62
-22
lines changed

2 files changed

+62
-22
lines changed

ext/panko_serializer/panko_serializer.c

+60-9
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,72 @@
22

33
#include "time_conversion.h"
44

5-
VALUE public_is_iso8601_time_string(VALUE klass, VALUE value) {
6-
return is_iso8601_time_string(StringValuePtr(value)) ? Qtrue : Qfalse;
5+
static ID push_value_id;
6+
7+
static VALUE datetime_writer_write(VALUE self, VALUE value, VALUE writer,
8+
VALUE key) {
9+
if (RB_TYPE_P(value, T_STRING)) {
10+
const char* val = StringValuePtr(value);
11+
12+
// 'Z' in ISO8601 says it's UTC
13+
if (val[strlen(val) - 1] == 'Z' && is_iso8601_time_string(val) == Qtrue) {
14+
rb_funcall(writer, push_value_id, 2, value, key);
15+
return Qtrue;
16+
}
17+
18+
volatile VALUE iso8601_string = iso_ar_iso_datetime_string(val);
19+
if (iso8601_string != Qnil) {
20+
rb_funcall(writer, push_value_id, 2, iso8601_string, key);
21+
return Qtrue;
22+
}
23+
}
24+
25+
return Qfalse;
726
}
827

9-
VALUE public_iso_ar_iso_datetime_string(VALUE klass, VALUE value) {
10-
return iso_ar_iso_datetime_string(StringValuePtr(value));
28+
// Helper function to safely get a constant if it exists
29+
static VALUE safe_const_get(VALUE parent, const char* name) {
30+
if (rb_const_defined(parent, rb_intern(name))) {
31+
return rb_const_get(parent, rb_intern(name));
32+
}
33+
return Qnil;
1134
}
1235

1336
void Init_panko_serializer() {
14-
VALUE mPanko = rb_define_module("Panko");
37+
push_value_id = rb_intern("push_value");
1538

16-
rb_define_singleton_method(mPanko, "is_iso8601_time_string",
17-
public_is_iso8601_time_string, 1);
18-
rb_define_singleton_method(mPanko, "iso_ar_iso_datetime_string",
19-
public_iso_ar_iso_datetime_string, 1);
39+
VALUE mPanko = rb_define_module("Panko");
2040

2141
panko_init_time(mPanko);
42+
43+
VALUE impl = safe_const_get(mPanko, "Impl");
44+
if (NIL_P(impl)) {
45+
printf("Not patching\n");
46+
return;
47+
}
48+
49+
VALUE attributes_writer = safe_const_get(impl, "AttributesWriter");
50+
if (NIL_P(attributes_writer)) {
51+
printf("Not patching\n");
52+
return;
53+
}
54+
55+
VALUE active_record = safe_const_get(attributes_writer, "ActiveRecord");
56+
if (NIL_P(active_record)) {
57+
printf("Not patching\n");
58+
return;
59+
}
60+
61+
VALUE values_writer = safe_const_get(active_record, "ValuesWriter");
62+
if (NIL_P(values_writer)) {
63+
printf("Not patching\n");
64+
return;
65+
}
66+
67+
VALUE cDateTimeWriter = safe_const_get(values_writer, "DateTimeWriter");
68+
if (NIL_P(cDateTimeWriter)) {
69+
printf("Not patching\n");
70+
} else {
71+
rb_define_method(cDateTimeWriter, "write", datetime_writer_write, 3);
72+
}
2273
}

lib/panko/impl/attributes_writer/active_record/values_writer/datetime_writer.rb

+2-13
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,8 @@
33
module Panko::Impl::AttributesWriter::ActiveRecord::ValuesWriter
44
class DateTimeWriter
55
def write(value, writer, key)
6-
return false unless value.is_a?(String)
7-
8-
if value.end_with?("Z") && Panko.is_iso8601_time_string(value)
9-
writer.push_value(value, key)
10-
return true
11-
end
12-
13-
iso8601_string = Panko.iso_ar_iso_datetime_string(value)
14-
unless iso8601_string.nil?
15-
writer.push_value(iso8601_string, key)
16-
return true
17-
end
18-
6+
# The actual implementation is in the native extension
7+
# if there is no native extension, we will fallback to Rails implementation
198
false
209
end
2110
end

0 commit comments

Comments
 (0)