panko_serializer 0.8.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -4
  3. data/lib/panko/array_serializer.rb +55 -16
  4. data/lib/panko/code_gen/active_record/access_classifier.rb +65 -0
  5. data/lib/panko/code_gen/active_record/define_attribute_methods.rb +13 -0
  6. data/lib/panko/code_gen/code_builder.rb +32 -0
  7. data/lib/panko/code_gen/compile_cache.rb +28 -0
  8. data/lib/panko/code_gen/compiler.rb +56 -0
  9. data/lib/panko/code_gen/config.rb +79 -0
  10. data/lib/panko/code_gen/datetime_format.rb +38 -0
  11. data/lib/panko/code_gen/descriptor.rb +136 -0
  12. data/lib/panko/code_gen/descriptor_builder.rb +166 -0
  13. data/lib/panko/code_gen/dump.rb +52 -0
  14. data/lib/panko/code_gen/errors.rb +21 -0
  15. data/lib/panko/code_gen/filter.rb +29 -0
  16. data/lib/panko/code_gen/filter_adapter.rb +44 -0
  17. data/lib/panko/code_gen/filters/indexed.rb +62 -0
  18. data/lib/panko/code_gen/filters/none.rb +19 -0
  19. data/lib/panko/code_gen/generator.rb +23 -0
  20. data/lib/panko/code_gen/generators/banner.rb +27 -0
  21. data/lib/panko/code_gen/generators/class_emitter.rb +120 -0
  22. data/lib/panko/code_gen/generators/cycle_membership.rb +53 -0
  23. data/lib/panko/code_gen/generators/descriptor_walk.rb +22 -0
  24. data/lib/panko/code_gen/generators/fanout.rb +60 -0
  25. data/lib/panko/code_gen/generators/field_index.rb +31 -0
  26. data/lib/panko/code_gen/generators/field_walk.rb +38 -0
  27. data/lib/panko/code_gen/generators/generated_names.rb +73 -0
  28. data/lib/panko/code_gen/generators/hash_sink.rb +217 -0
  29. data/lib/panko/code_gen/generators/json_sink.rb +290 -0
  30. data/lib/panko/code_gen/generators/record_access/generic.rb +92 -0
  31. data/lib/panko/code_gen/generators/record_access/specialized.rb +90 -0
  32. data/lib/panko/code_gen/generators/release.rb +60 -0
  33. data/lib/panko/code_gen/generators/sink.rb +80 -0
  34. data/lib/panko/code_gen/instance_pool.rb +27 -0
  35. data/lib/panko/code_gen/runtime.rb +27 -0
  36. data/lib/panko/code_gen/serializer_cache.rb +242 -0
  37. data/lib/panko/code_gen/validators/callable_arity.rb +42 -0
  38. data/lib/panko/code_gen/validators/name_uniqueness.rb +44 -0
  39. data/lib/panko/code_gen/validators/source_resolution.rb +48 -0
  40. data/lib/panko/code_gen/validators/validator.rb +19 -0
  41. data/lib/panko/code_gen/writers_pool.rb +51 -0
  42. data/lib/panko/code_gen.rb +82 -0
  43. data/lib/panko/compile_all.rb +80 -0
  44. data/lib/panko/compile_all_result.rb +21 -0
  45. data/lib/panko/config.rb +71 -0
  46. data/lib/panko/descriptor.rb +93 -0
  47. data/lib/panko/response.rb +40 -8
  48. data/lib/panko/serializer.rb +175 -91
  49. data/lib/panko/serializer_resolver.rb +2 -8
  50. data/lib/panko/version.rb +1 -1
  51. data/lib/panko_serializer.rb +3 -5
  52. metadata +49 -35
  53. data/ext/panko_serializer/attributes_writer/active_record.c +0 -181
  54. data/ext/panko_serializer/attributes_writer/active_record.h +0 -17
  55. data/ext/panko_serializer/attributes_writer/attributes_writer.c +0 -55
  56. data/ext/panko_serializer/attributes_writer/attributes_writer.h +0 -35
  57. data/ext/panko_serializer/attributes_writer/common.c +0 -10
  58. data/ext/panko_serializer/attributes_writer/common.h +0 -9
  59. data/ext/panko_serializer/attributes_writer/hash.c +0 -13
  60. data/ext/panko_serializer/attributes_writer/hash.h +0 -7
  61. data/ext/panko_serializer/attributes_writer/plain.c +0 -13
  62. data/ext/panko_serializer/attributes_writer/plain.h +0 -7
  63. data/ext/panko_serializer/attributes_writer/type_cast/time_conversion.c +0 -156
  64. data/ext/panko_serializer/attributes_writer/type_cast/time_conversion.h +0 -10
  65. data/ext/panko_serializer/attributes_writer/type_cast/type_cast.c +0 -409
  66. data/ext/panko_serializer/attributes_writer/type_cast/type_cast.h +0 -81
  67. data/ext/panko_serializer/common.h +0 -9
  68. data/ext/panko_serializer/extconf.rb +0 -28
  69. data/ext/panko_serializer/panko_serializer.c +0 -181
  70. data/ext/panko_serializer/panko_serializer.h +0 -12
  71. data/ext/panko_serializer/serialization_descriptor/association.c +0 -90
  72. data/ext/panko_serializer/serialization_descriptor/association.h +0 -20
  73. data/ext/panko_serializer/serialization_descriptor/attribute.c +0 -96
  74. data/ext/panko_serializer/serialization_descriptor/attribute.h +0 -27
  75. data/ext/panko_serializer/serialization_descriptor/serialization_descriptor.c +0 -177
  76. data/ext/panko_serializer/serialization_descriptor/serialization_descriptor.h +0 -30
  77. data/lib/panko/association.rb +0 -17
  78. data/lib/panko/attribute.rb +0 -29
  79. data/lib/panko/object_writer.rb +0 -68
  80. data/lib/panko/serialization_descriptor.rb +0 -180
@@ -1,409 +0,0 @@
1
- #include "type_cast.h"
2
-
3
- #include "time_conversion.h"
4
-
5
- ID deserialize_from_db_id = 0;
6
- ID to_s_id = 0;
7
- ID to_i_id = 0;
8
-
9
- static VALUE oj_type = Qundef;
10
- static VALUE oj_parseerror_type = Qundef;
11
- ID oj_sc_parse_id = 0;
12
-
13
- // Caching ActiveRecord Types
14
- static VALUE ar_string_type = Qundef;
15
- static VALUE ar_text_type = Qundef;
16
- static VALUE ar_float_type = Qundef;
17
- static VALUE ar_integer_type = Qundef;
18
- static VALUE ar_boolean_type = Qundef;
19
- static VALUE ar_date_time_type = Qundef;
20
- static VALUE ar_time_zone_converter = Qundef;
21
- static VALUE ar_json_type = Qundef;
22
-
23
- static VALUE ar_pg_integer_type = Qundef;
24
- static VALUE ar_pg_float_type = Qundef;
25
- static VALUE ar_pg_uuid_type = Qundef;
26
- static VALUE ar_pg_json_type = Qundef;
27
- static VALUE ar_pg_jsonb_type = Qundef;
28
- static VALUE ar_pg_array_type = Qundef;
29
- static VALUE ar_pg_date_time_type = Qundef;
30
- static VALUE ar_pg_timestamp_type = Qundef;
31
-
32
- static int initiailized = 0;
33
-
34
- VALUE cache_postgres_type_lookup(VALUE ar) {
35
- VALUE ar_connection_adapters, ar_postgresql, ar_oid;
36
-
37
- if (rb_const_defined_at(ar, rb_intern("ConnectionAdapters")) != (int)Qtrue) {
38
- return Qfalse;
39
- }
40
- ar_connection_adapters = rb_const_get_at(ar, rb_intern("ConnectionAdapters"));
41
-
42
- if (rb_const_defined_at(ar_connection_adapters, rb_intern("PostgreSQL")) !=
43
- (int)Qtrue) {
44
- return Qfalse;
45
- }
46
- ar_postgresql =
47
- rb_const_get_at(ar_connection_adapters, rb_intern("PostgreSQL"));
48
-
49
- if (rb_const_defined_at(ar_postgresql, rb_intern("OID")) != (int)Qtrue) {
50
- return Qfalse;
51
- }
52
- ar_oid = rb_const_get_at(ar_postgresql, rb_intern("OID"));
53
-
54
- if (rb_const_defined_at(ar_oid, rb_intern("Float")) == (int)Qtrue) {
55
- ar_pg_float_type = rb_const_get_at(ar_oid, rb_intern("Float"));
56
- }
57
-
58
- if (rb_const_defined_at(ar_oid, rb_intern("Integer")) == (int)Qtrue) {
59
- ar_pg_integer_type = rb_const_get_at(ar_oid, rb_intern("Integer"));
60
- }
61
-
62
- if (rb_const_defined_at(ar_oid, rb_intern("Uuid")) == (int)Qtrue) {
63
- ar_pg_uuid_type = rb_const_get_at(ar_oid, rb_intern("Uuid"));
64
- }
65
-
66
- if (rb_const_defined_at(ar_oid, rb_intern("Json")) == (int)Qtrue) {
67
- ar_pg_json_type = rb_const_get_at(ar_oid, rb_intern("Json"));
68
- }
69
-
70
- if (rb_const_defined_at(ar_oid, rb_intern("Jsonb")) == (int)Qtrue) {
71
- ar_pg_jsonb_type = rb_const_get_at(ar_oid, rb_intern("Jsonb"));
72
- }
73
-
74
- if (rb_const_defined_at(ar_oid, rb_intern("DateTime")) == (int)Qtrue) {
75
- ar_pg_date_time_type = rb_const_get_at(ar_oid, rb_intern("DateTime"));
76
- }
77
-
78
- if (rb_const_defined_at(ar_oid, rb_intern("Timestamp")) == (int)Qtrue) {
79
- ar_pg_timestamp_type = rb_const_get_at(ar_oid, rb_intern("Timestamp"));
80
- }
81
-
82
- return Qtrue;
83
- }
84
-
85
- VALUE cache_time_zone_type_lookup(VALUE ar) {
86
- VALUE ar_attr_methods, ar_time_zone_conversion;
87
-
88
- // ActiveRecord::AttributeMethods
89
- if (rb_const_defined_at(ar, rb_intern("AttributeMethods")) != (int)Qtrue) {
90
- return Qfalse;
91
- }
92
- ar_attr_methods = rb_const_get_at(ar, rb_intern("AttributeMethods"));
93
-
94
- // ActiveRecord::AttributeMethods::TimeZoneConversion
95
- if (rb_const_defined_at(ar_attr_methods, rb_intern("TimeZoneConversion")) !=
96
- (int)Qtrue) {
97
- return Qfalse;
98
- }
99
- ar_time_zone_conversion =
100
- rb_const_get_at(ar_attr_methods, rb_intern("TimeZoneConversion"));
101
-
102
- if (rb_const_defined_at(ar_time_zone_conversion,
103
- rb_intern("TimeZoneConverter")) != (int)Qtrue) {
104
- return Qfalse;
105
- }
106
- ar_time_zone_converter =
107
- rb_const_get_at(ar_time_zone_conversion, rb_intern("TimeZoneConverter"));
108
-
109
- return Qtrue;
110
- }
111
-
112
- void cache_type_lookup() {
113
- if (initiailized == 1) {
114
- return;
115
- }
116
-
117
- initiailized = 1;
118
-
119
- VALUE ar, ar_type, ar_type_methods;
120
-
121
- ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
122
-
123
- // ActiveRecord::Type
124
- ar_type = rb_const_get_at(ar, rb_intern("Type"));
125
-
126
- ar_string_type = rb_const_get_at(ar_type, rb_intern("String"));
127
- ar_text_type = rb_const_get_at(ar_type, rb_intern("Text"));
128
- ar_float_type = rb_const_get_at(ar_type, rb_intern("Float"));
129
- ar_integer_type = rb_const_get_at(ar_type, rb_intern("Integer"));
130
- ar_boolean_type = rb_const_get_at(ar_type, rb_intern("Boolean"));
131
- ar_date_time_type = rb_const_get_at(ar_type, rb_intern("DateTime"));
132
-
133
- ar_type_methods = rb_class_instance_methods(0, NULL, ar_string_type);
134
- if (rb_ary_includes(ar_type_methods,
135
- rb_to_symbol(rb_str_new_cstr("deserialize")))) {
136
- deserialize_from_db_id = rb_intern("deserialize");
137
- } else {
138
- deserialize_from_db_id = rb_intern("type_cast_from_database");
139
- }
140
-
141
- if (rb_const_defined_at(ar_type, rb_intern("Json")) == (int)Qtrue) {
142
- ar_json_type = rb_const_get_at(ar_type, rb_intern("Json"));
143
- }
144
-
145
- int isErrored;
146
- rb_protect(cache_postgres_type_lookup, ar, &isErrored);
147
- if (isErrored) {
148
- rb_set_errinfo(Qnil);
149
- }
150
-
151
- rb_protect(cache_time_zone_type_lookup, ar, &isErrored);
152
- if (isErrored) {
153
- rb_set_errinfo(Qnil);
154
- }
155
- }
156
-
157
- bool is_string_or_text_type(VALUE type_klass) {
158
- return type_klass == ar_string_type || type_klass == ar_text_type ||
159
- (ar_pg_uuid_type != Qundef && type_klass == ar_pg_uuid_type);
160
- }
161
-
162
- VALUE cast_string_or_text_type(VALUE value) {
163
- if (RB_TYPE_P(value, T_STRING)) {
164
- return value;
165
- }
166
-
167
- if (value == Qtrue) {
168
- return rb_str_new_cstr("t");
169
- }
170
-
171
- if (value == Qfalse) {
172
- return rb_str_new_cstr("f");
173
- }
174
-
175
- return rb_funcall(value, to_s_id, 0);
176
- }
177
-
178
- bool is_float_type(VALUE type_klass) {
179
- return type_klass == ar_float_type ||
180
- (ar_pg_float_type != Qundef && type_klass == ar_pg_float_type);
181
- }
182
-
183
- VALUE cast_float_type(VALUE value) {
184
- if (RB_TYPE_P(value, T_FLOAT)) {
185
- return value;
186
- }
187
-
188
- if (RB_TYPE_P(value, T_STRING)) {
189
- const char* val = StringValuePtr(value);
190
- return rb_float_new(strtod(val, NULL));
191
- }
192
-
193
- return Qundef;
194
- }
195
-
196
- bool is_integer_type(VALUE type_klass) {
197
- return type_klass == ar_integer_type ||
198
- (ar_pg_integer_type != Qundef && type_klass == ar_pg_integer_type);
199
- }
200
-
201
- VALUE cast_integer_type(VALUE value) {
202
- if (RB_INTEGER_TYPE_P(value)) {
203
- return value;
204
- }
205
-
206
- if (RB_TYPE_P(value, T_STRING)) {
207
- const char* val = StringValuePtr(value);
208
- if (strlen(val) == 0) {
209
- return Qnil;
210
- }
211
- return rb_cstr2inum(val, 10);
212
- }
213
-
214
- if (RB_FLOAT_TYPE_P(value)) {
215
- // We are calling the `to_i` here, because ruby internal
216
- // `flo_to_i` is not accessible
217
- return rb_funcall(value, to_i_id, 0);
218
- }
219
-
220
- if (value == Qtrue) {
221
- return INT2NUM(1);
222
- }
223
-
224
- if (value == Qfalse) {
225
- return INT2NUM(0);
226
- }
227
-
228
- // At this point, we handled integer, float, string and booleans
229
- // any thing other than this (array, hashes, etc) should result in nil
230
- return Qnil;
231
- }
232
-
233
- bool is_json_type(VALUE type_klass) {
234
- return ((ar_pg_json_type != Qundef && type_klass == ar_pg_json_type) ||
235
- (ar_pg_jsonb_type != Qundef && type_klass == ar_pg_jsonb_type) ||
236
- (ar_json_type != Qundef && type_klass == ar_json_type));
237
- }
238
-
239
- bool is_boolean_type(VALUE type_klass) { return type_klass == ar_boolean_type; }
240
-
241
- VALUE cast_boolean_type(VALUE value) {
242
- if (value == Qtrue || value == Qfalse) {
243
- return value;
244
- }
245
-
246
- if (value == Qnil) {
247
- return Qnil;
248
- }
249
-
250
- if (RB_TYPE_P(value, T_STRING)) {
251
- if (RSTRING_LEN(value) == 0) {
252
- return Qnil;
253
- }
254
-
255
- const char* val = StringValuePtr(value);
256
-
257
- bool isFalseValue =
258
- (*val == '0' || (*val == 'f' || *val == 'F') ||
259
- (strcmp(val, "false") == 0 || strcmp(val, "FALSE") == 0) ||
260
- (strcmp(val, "off") == 0 || strcmp(val, "OFF") == 0));
261
-
262
- return isFalseValue ? Qfalse : Qtrue;
263
- }
264
-
265
- if (RB_INTEGER_TYPE_P(value)) {
266
- return value == INT2NUM(1) ? Qtrue : Qfalse;
267
- }
268
-
269
- return Qundef;
270
- }
271
-
272
- bool is_date_time_type(VALUE type_klass) {
273
- return (type_klass == ar_date_time_type) ||
274
- (ar_pg_date_time_type != Qundef &&
275
- type_klass == ar_pg_date_time_type) ||
276
- (ar_pg_timestamp_type != Qundef &&
277
- type_klass == ar_pg_timestamp_type) ||
278
- (ar_time_zone_converter != Qundef &&
279
- type_klass == ar_time_zone_converter);
280
- }
281
-
282
- VALUE cast_date_time_type(VALUE value) {
283
- // Instead of take strings to comparing them to time zones
284
- // and then comparing them back to string
285
- // We will just make sure we have string on ISO8601 and it's utc
286
- if (RB_TYPE_P(value, T_STRING)) {
287
- const char* val = StringValuePtr(value);
288
- // 'Z' in ISO8601 says it's UTC
289
- if (val[strlen(val) - 1] == 'Z' && is_iso8601_time_string(val) == Qtrue) {
290
- return value;
291
- }
292
-
293
- volatile VALUE iso8601_string = iso_ar_iso_datetime_string(val);
294
- if (iso8601_string != Qnil) {
295
- return iso8601_string;
296
- }
297
- }
298
-
299
- return Qundef;
300
- }
301
-
302
- VALUE rescue_func(VALUE _arg, VALUE _data) { return Qfalse; }
303
-
304
- VALUE parse_json(VALUE value) {
305
- return rb_funcall(oj_type, oj_sc_parse_id, 2, rb_cObject, value);
306
- }
307
-
308
- VALUE is_json_value(VALUE value) {
309
- if (!RB_TYPE_P(value, T_STRING)) {
310
- return value;
311
- }
312
-
313
- if (RSTRING_LEN(value) == 0) {
314
- return Qfalse;
315
- }
316
-
317
- volatile VALUE result =
318
- rb_rescue2(parse_json, value, rescue_func, Qundef, oj_parseerror_type, 0);
319
-
320
- if (NIL_P(result)) {
321
- return Qtrue;
322
- }
323
-
324
- if (result == Qfalse) {
325
- return Qfalse;
326
- }
327
-
328
- // TODO: fix me!
329
- return Qfalse;
330
- }
331
-
332
- VALUE type_cast(VALUE type_metadata, VALUE value, volatile VALUE* isJson) {
333
- if (value == Qnil || value == Qundef) {
334
- return value;
335
- }
336
-
337
- cache_type_lookup();
338
-
339
- VALUE type_klass, typeCastedValue;
340
-
341
- type_klass = CLASS_OF(type_metadata);
342
- typeCastedValue = Qundef;
343
-
344
- TypeCast typeCast;
345
- for (typeCast = type_casts; typeCast->canCast != NULL; typeCast++) {
346
- if (typeCast->canCast(type_klass)) {
347
- typeCastedValue = typeCast->typeCast(value);
348
- break;
349
- }
350
- }
351
-
352
- if (is_json_type(type_klass)) {
353
- if (is_json_value(value) == Qfalse) {
354
- return Qnil;
355
- }
356
- *isJson = Qtrue;
357
- return value;
358
- }
359
-
360
- if (typeCastedValue == Qundef) {
361
- return rb_funcall(type_metadata, deserialize_from_db_id, 1, value);
362
- }
363
-
364
- return typeCastedValue;
365
- }
366
-
367
- VALUE public_type_cast(int argc, VALUE* argv, VALUE self) {
368
- VALUE type_metadata, value, isJson;
369
- rb_scan_args(argc, argv, "21", &type_metadata, &value, &isJson);
370
-
371
- if (isJson == Qnil || isJson == Qundef) {
372
- isJson = Qfalse;
373
- }
374
-
375
- return type_cast(type_metadata, value, &isJson);
376
- }
377
-
378
- void panko_init_type_cast(VALUE mPanko) {
379
- to_s_id = rb_intern("to_s");
380
- to_i_id = rb_intern("to_i");
381
-
382
- oj_type = rb_const_get_at(rb_cObject, rb_intern("Oj"));
383
- oj_parseerror_type = rb_const_get_at(oj_type, rb_intern("ParseError"));
384
- oj_sc_parse_id = rb_intern("sc_parse");
385
-
386
- // TODO: pass 3 arguments here
387
- rb_define_singleton_method(mPanko, "_type_cast", public_type_cast, -1);
388
-
389
- panko_init_time(mPanko);
390
-
391
- rb_global_variable(&oj_type);
392
- rb_global_variable(&oj_parseerror_type);
393
- rb_global_variable(&ar_string_type);
394
- rb_global_variable(&ar_text_type);
395
- rb_global_variable(&ar_float_type);
396
- rb_global_variable(&ar_integer_type);
397
- rb_global_variable(&ar_boolean_type);
398
- rb_global_variable(&ar_date_time_type);
399
- rb_global_variable(&ar_time_zone_converter);
400
- rb_global_variable(&ar_json_type);
401
- rb_global_variable(&ar_pg_integer_type);
402
- rb_global_variable(&ar_pg_float_type);
403
- rb_global_variable(&ar_pg_uuid_type);
404
- rb_global_variable(&ar_pg_json_type);
405
- rb_global_variable(&ar_pg_jsonb_type);
406
- rb_global_variable(&ar_pg_array_type);
407
- rb_global_variable(&ar_pg_date_time_type);
408
- rb_global_variable(&ar_pg_timestamp_type);
409
- }
@@ -1,81 +0,0 @@
1
- #pragma once
2
-
3
- #include <ruby.h>
4
- #include <stdbool.h>
5
-
6
- /*
7
- * Type Casting
8
- *
9
- * We do "special" type casting which is mix of two inspirations:
10
- * *) light records gem
11
- * *) pg TextDecoders
12
- *
13
- * The whole idea behind those type casts, are to do the minimum required
14
- * type casting in the most performant manner and *allocation free*.
15
- *
16
- * For example, in `ActiveRecord::Type::String` the type_cast_from_database
17
- * creates new string, for known reasons, but, in serialization flow we don't
18
- * need to create new string becuase we afraid of mutations.
19
- *
20
- * Since we know before hand, that we are only reading from the database, and
21
- * *not* writing and the end result if for JSON we can skip some "defenses".
22
- */
23
-
24
- typedef bool (*TypeMatchFunc)(VALUE type_klass);
25
-
26
- /*
27
- * TypeCastFunc
28
- *
29
- * @return VALUE casted value or Qundef if not casted
30
- */
31
- typedef VALUE (*TypeCastFunc)(VALUE value);
32
-
33
- typedef struct _TypeCast {
34
- TypeMatchFunc canCast;
35
- TypeCastFunc typeCast;
36
- }* TypeCast;
37
-
38
- // ActiveRecord::Type::String
39
- // ActiveRecord::Type::Text
40
- bool is_string_or_text_type(VALUE type_klass);
41
- VALUE cast_string_or_text_type(VALUE value);
42
-
43
- // ActiveRecord::Type::Float
44
- bool is_float_type(VALUE type_klass);
45
- VALUE cast_float_type(VALUE value);
46
-
47
- // ActiveRecord::Type::Integer
48
- bool is_integer_type(VALUE type_klass);
49
- VALUE cast_integer_type(VALUE value);
50
-
51
- // ActiveRecord::ConnectoinAdapters::PostgreSQL::Json
52
- bool is_json_type(VALUE type_klass);
53
- VALUE cast_json_type(VALUE value);
54
-
55
- // ActiveRecord::Type::Boolean
56
- bool is_boolean_type(VALUE type_klass);
57
- VALUE cast_boolean_type(VALUE value);
58
-
59
- // ActiveRecord::Type::DateTime
60
- // ActiveRecord::ConnectionAdapters::PostgreSQL::OID::DateTime
61
- // ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter
62
- bool is_date_time_type(VALUE type_klass);
63
- VALUE cast_date_time_type(VALUE value);
64
-
65
- static struct _TypeCast type_casts[] = {
66
- {is_string_or_text_type, cast_string_or_text_type},
67
- {is_integer_type, cast_integer_type},
68
- {is_boolean_type, cast_boolean_type},
69
- {is_date_time_type, cast_date_time_type},
70
- {is_float_type, cast_float_type},
71
-
72
- {NULL, NULL}};
73
-
74
- extern VALUE type_cast(VALUE type_metadata, VALUE value,
75
- volatile VALUE* isJson);
76
- void panko_init_type_cast(VALUE mPanko);
77
-
78
- // Introduced in ruby 2.4
79
- #ifndef RB_INTEGER_TYPE_P
80
- #define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM))
81
- #endif
@@ -1,9 +0,0 @@
1
- #pragma once
2
-
3
- #include <ruby.h>
4
-
5
- #define PANKO_SAFE_HASH_SIZE(hash) \
6
- (hash == Qnil || hash == Qundef) ? 0 : RHASH_SIZE(hash)
7
-
8
- #define PANKO_EMPTY_HASH(hash) \
9
- (hash == Qnil || hash == Qundef) ? 1 : (RHASH_SIZE(hash) == 0)
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mkmf"
3
- require "pathname"
4
-
5
- $CPPFLAGS += " -Wall"
6
-
7
- extension_name = "panko_serializer"
8
- dir_config(extension_name)
9
-
10
- RbConfig.expand(srcdir = "$(srcdir)".dup)
11
-
12
- # enum all source files
13
- $srcs = Dir[File.join(srcdir, "**/*.c")]
14
-
15
-
16
- # Get all source directories recursivley
17
- directories = Dir[File.join(srcdir, "**/*")].select { |f| File.directory?(f) }
18
- directories = directories.map { |d| Pathname.new(d).relative_path_from(Pathname.new(srcdir)) }
19
- directories.each do |dir|
20
- # add include path to the internal folder
21
- # $(srcdir) is a root folder, where "extconf.rb" is stored
22
- $INCFLAGS << " -I$(srcdir)/#{dir}"
23
-
24
- # add folder, where compiler can search source files
25
- $VPATH << "$(srcdir)/#{dir}"
26
- end
27
-
28
- create_makefile("panko/panko_serializer")
@@ -1,181 +0,0 @@
1
- #include "panko_serializer.h"
2
-
3
- #include <ruby.h>
4
-
5
- static ID push_value_id;
6
- static ID push_array_id;
7
- static ID push_object_id;
8
- static ID push_json_id;
9
- static ID pop_id;
10
-
11
- static ID to_a_id;
12
-
13
- static ID object_id;
14
- static ID serialization_context_id;
15
-
16
- static VALUE SKIP = Qundef;
17
-
18
- void write_value(VALUE str_writer, VALUE key, VALUE value, VALUE isJson) {
19
- if (isJson == Qtrue) {
20
- rb_funcall(str_writer, push_json_id, 2, value, key);
21
- } else {
22
- rb_funcall(str_writer, push_value_id, 2, value, key);
23
- }
24
- }
25
-
26
- void serialize_method_fields(VALUE object, VALUE str_writer,
27
- SerializationDescriptor descriptor) {
28
- if (RARRAY_LEN(descriptor->method_fields) == 0) {
29
- return;
30
- }
31
-
32
- volatile VALUE method_fields, serializer, key;
33
- long i;
34
-
35
- method_fields = descriptor->method_fields;
36
-
37
- serializer = descriptor->serializer;
38
- rb_ivar_set(serializer, object_id, object);
39
-
40
- for (i = 0; i < RARRAY_LEN(method_fields); i++) {
41
- volatile VALUE raw_attribute = RARRAY_AREF(method_fields, i);
42
- Attribute attribute = PANKO_ATTRIBUTE_READ(raw_attribute);
43
-
44
- volatile VALUE result = rb_funcall(serializer, attribute->name_id, 0);
45
- if (result != SKIP) {
46
- key = attr_name_for_serialization(attribute);
47
- write_value(str_writer, key, result, Qfalse);
48
- }
49
- }
50
-
51
- rb_ivar_set(serializer, object_id, Qnil);
52
- }
53
-
54
- void serialize_fields(VALUE object, VALUE str_writer,
55
- SerializationDescriptor descriptor) {
56
- descriptor->attributes_writer.write_attributes(object, descriptor->attributes,
57
- write_value, str_writer);
58
-
59
- serialize_method_fields(object, str_writer, descriptor);
60
- }
61
-
62
- void serialize_has_one_associations(VALUE object, VALUE str_writer,
63
- VALUE associations) {
64
- long i;
65
- for (i = 0; i < RARRAY_LEN(associations); i++) {
66
- volatile VALUE association_el = RARRAY_AREF(associations, i);
67
- Association association = association_read(association_el);
68
-
69
- volatile VALUE value = rb_funcall(object, association->name_id, 0);
70
-
71
- if (NIL_P(value)) {
72
- write_value(str_writer, association->name_str, value, Qfalse);
73
- } else {
74
- serialize_object(association->name_str, value, str_writer,
75
- association->descriptor);
76
- }
77
- }
78
- }
79
-
80
- void serialize_has_many_associations(VALUE object, VALUE str_writer,
81
- VALUE associations) {
82
- long i;
83
- for (i = 0; i < RARRAY_LEN(associations); i++) {
84
- volatile VALUE association_el = RARRAY_AREF(associations, i);
85
- Association association = association_read(association_el);
86
-
87
- volatile VALUE value = rb_funcall(object, association->name_id, 0);
88
-
89
- if (NIL_P(value)) {
90
- write_value(str_writer, association->name_str, value, Qfalse);
91
- } else {
92
- serialize_objects(association->name_str, value, str_writer,
93
- association->descriptor);
94
- }
95
- }
96
- }
97
-
98
- VALUE serialize_object(VALUE key, VALUE object, VALUE str_writer,
99
- SerializationDescriptor descriptor) {
100
- sd_set_writer(descriptor, object);
101
-
102
- rb_funcall(str_writer, push_object_id, 1, key);
103
-
104
- serialize_fields(object, str_writer, descriptor);
105
-
106
- if (RARRAY_LEN(descriptor->has_one_associations) > 0) {
107
- serialize_has_one_associations(object, str_writer,
108
- descriptor->has_one_associations);
109
- }
110
-
111
- if (RARRAY_LEN(descriptor->has_many_associations) > 0) {
112
- serialize_has_many_associations(object, str_writer,
113
- descriptor->has_many_associations);
114
- }
115
-
116
- rb_funcall(str_writer, pop_id, 0);
117
-
118
- return Qnil;
119
- }
120
-
121
- VALUE serialize_objects(VALUE key, VALUE objects, VALUE str_writer,
122
- SerializationDescriptor descriptor) {
123
- long i;
124
-
125
- rb_funcall(str_writer, push_array_id, 1, key);
126
-
127
- if (!RB_TYPE_P(objects, T_ARRAY)) {
128
- objects = rb_funcall(objects, to_a_id, 0);
129
- }
130
-
131
- for (i = 0; i < RARRAY_LEN(objects); i++) {
132
- volatile VALUE object = RARRAY_AREF(objects, i);
133
- serialize_object(Qnil, object, str_writer, descriptor);
134
- }
135
-
136
- rb_funcall(str_writer, pop_id, 0);
137
-
138
- return Qnil;
139
- }
140
-
141
- VALUE serialize_object_api(VALUE klass, VALUE object, VALUE str_writer,
142
- VALUE descriptor) {
143
- SerializationDescriptor sd = sd_read(descriptor);
144
- return serialize_object(Qnil, object, str_writer, sd);
145
- }
146
-
147
- VALUE serialize_objects_api(VALUE klass, VALUE objects, VALUE str_writer,
148
- VALUE descriptor) {
149
- serialize_objects(Qnil, objects, str_writer, sd_read(descriptor));
150
-
151
- return Qnil;
152
- }
153
-
154
- void Init_panko_serializer() {
155
- push_value_id = rb_intern("push_value");
156
- push_array_id = rb_intern("push_array");
157
- push_object_id = rb_intern("push_object");
158
- push_json_id = rb_intern("push_json");
159
- pop_id = rb_intern("pop");
160
- to_a_id = rb_intern("to_a");
161
- object_id = rb_intern("@object");
162
- serialization_context_id = rb_intern("@serialization_context");
163
-
164
- VALUE mPanko = rb_define_module("Panko");
165
-
166
- rb_define_singleton_method(mPanko, "serialize_object", serialize_object_api,
167
- 3);
168
-
169
- rb_define_singleton_method(mPanko, "serialize_objects", serialize_objects_api,
170
- 3);
171
-
172
- VALUE mPankoSerializer = rb_const_get(mPanko, rb_intern("Serializer"));
173
- SKIP = rb_const_get(mPankoSerializer, rb_intern("SKIP"));
174
- rb_global_variable(&SKIP);
175
-
176
- panko_init_serialization_descriptor(mPanko);
177
- init_attributes_writer(mPanko);
178
- panko_init_type_cast(mPanko);
179
- panko_init_attribute(mPanko);
180
- panko_init_association(mPanko);
181
- }