panko_serializer 0.1.4 → 0.1.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b721121db1bee35804d8beda87689c2a76ef7c52
4
- data.tar.gz: 7b6610f84d75aa9f5c929833598a3467499f22d7
3
+ metadata.gz: 73b05629bbbeb18415188b8c70e316f678f604ba
4
+ data.tar.gz: 95922dc138d747c5fa0ca282ff6b9eda4e004d55
5
5
  SHA512:
6
- metadata.gz: 9ea137eb8d6229fee333c1dca93b0646bf072116f2541ec2a4a9dba80e25f55fa226dda3a95fd70780ba78dd1eae5e28438dadb109062c38656f38512ec67813
7
- data.tar.gz: e01f5ac93e458bfad776aa0e64d7cf168095688e6f9d8d2eeb19d2329e3eab4861aa2ff6d09736d673aa225872996df65471451685957168b31089d1eb856cf7
6
+ metadata.gz: 1b6489dc3d9532d01766a38cbb6d0652275883d8ea8ad7b8dc6b82494f1d5035f5c95a925b2b0908bdcaf3a6807ec7afaca3c5982a1a894e102ac9aa7ae35243
7
+ data.tar.gz: 83c2b331d7acb26d4bbf6e851b5f30250b7074195c2f8a722bea053db867aa34af23a05dc015a0ceec098cfbc747b9f892516f9a8d534c50f5189180bcd5cf82
data/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/yosiat/panko_serializer.svg?branch=master)](https://travis-ci.org/yosiat/panko_serializer)
4
4
 
5
+ Panko is high performance library for serializing ActiveRecord objects.
6
+
7
+ ## Status
8
+
9
+ Panko is not ready for official release (it's missing documentation, tests, configuration options to remove assumptions).
10
+
11
+
5
12
 
6
13
  ## License
7
14
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -45,11 +45,6 @@ def db_panko_time
45
45
  end
46
46
  end
47
47
 
48
- db_panko_time
49
- utc_panko_time
50
-
51
- exit
52
-
53
48
  panko_type_convert ActiveRecord::Type::String, 1, "1"
54
49
  panko_type_convert ActiveRecord::Type::Text, 1, "1"
55
50
  panko_type_convert ActiveRecord::Type::Integer, "1", 1
@@ -1,24 +1,26 @@
1
1
  #include "attributes_iterator.h"
2
2
 
3
- static ID attributes_id = 0;
4
- static ID types_id = 0;
5
- static ID values_id = 0;
6
- static ID delegate_hash_id = 0;
3
+ static ID attributes_id;
4
+ static ID types_id;
5
+ static ID values_id;
6
+ static ID delegate_hash_id;
7
7
 
8
- static ID value_before_type_cast_id = 0;
9
- static ID type_id = 0;
8
+ static ID value_before_type_cast_id;
9
+ static ID type_id;
10
10
 
11
11
  VALUE read_attributes(VALUE obj) {
12
12
  return rb_ivar_get(obj, attributes_id);
13
13
  }
14
14
 
15
15
  VALUE panko_read_lazy_attributes_hash(VALUE object) {
16
- VALUE attributes_set = read_attributes(object);
16
+ volatile VALUE attributes_set, attributes_hash;
17
+
18
+ attributes_set = read_attributes(object);
17
19
  if (attributes_set == Qnil) {
18
20
  return Qnil;
19
21
  }
20
22
 
21
- VALUE attributes_hash = read_attributes(attributes_set);
23
+ attributes_hash = read_attributes(attributes_set);
22
24
  if (attributes_hash == Qnil) {
23
25
  return Qnil;
24
26
  }
@@ -37,29 +39,31 @@ VALUE panko_each_attribute(VALUE obj,
37
39
  VALUE attributes,
38
40
  EachAttributeFunc func,
39
41
  VALUE context) {
40
- VALUE attributes_hash = panko_read_lazy_attributes_hash(obj);
42
+ volatile VALUE attributes_hash, delegate_hash;
43
+ int i;
44
+
45
+ attributes_hash = panko_read_lazy_attributes_hash(obj);
41
46
  if (attributes_hash == Qnil) {
42
47
  return Qnil;
43
48
  }
44
49
 
45
- VALUE delegate_hash = rb_ivar_get(attributes_hash, delegate_hash_id);
50
+ delegate_hash = rb_ivar_get(attributes_hash, delegate_hash_id);
46
51
  bool tryToReadFromDelegateHash = RHASH_SIZE(delegate_hash) > 0;
47
52
 
48
53
  VALUE types, values;
49
54
  panko_read_types_and_value(attributes_hash, &types, &values);
50
55
 
51
- int i;
52
56
  for (i = 0; i < RARRAY_LEN(attributes); i++) {
53
- VALUE member = RARRAY_AREF(attributes, i);
57
+ volatile VALUE member = rb_sym2str(RARRAY_AREF(attributes, i));
54
58
 
55
- VALUE value = Qundef;
56
- VALUE type_metadata = Qnil;
59
+ volatile VALUE value = Qundef;
60
+ volatile VALUE type_metadata = Qnil;
57
61
 
58
62
  // First try to read from delegate hash,
59
63
  // If the object was create in memory `User.new(name: "Yosi")`
60
64
  // it won't exist in types/values
61
65
  if (tryToReadFromDelegateHash) {
62
- VALUE attribute_metadata = rb_hash_aref(delegate_hash, member);
66
+ volatile VALUE attribute_metadata = rb_hash_aref(delegate_hash, member);
63
67
  if (attribute_metadata != Qnil) {
64
68
  value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
65
69
  type_metadata = rb_ivar_get(attribute_metadata, type_id);
@@ -2,12 +2,12 @@
2
2
 
3
3
  #include "panko_serializer.h"
4
4
 
5
- static ID push_value_id = 0;
6
- static ID push_array_id = 0;
7
- static ID push_object_id = 0;
8
- static ID pop_id = 0;
5
+ static ID push_value_id;
6
+ static ID push_array_id;
7
+ static ID push_object_id;
8
+ static ID pop_id;
9
9
 
10
- static ID to_a_id = 0;
10
+ static ID to_a_id;
11
11
 
12
12
  void write_value(VALUE str_writer,
13
13
  VALUE key,
@@ -24,18 +24,21 @@ void serialize_method_fields(VALUE subject,
24
24
  VALUE str_writer,
25
25
  SerializationDescriptor descriptor,
26
26
  VALUE context) {
27
- VALUE method_fields = descriptor->method_fields;
27
+ VALUE method_fields, serializer;
28
+ long i;
29
+
30
+ method_fields = descriptor->method_fields;
28
31
  if (RARRAY_LEN(method_fields) == 0) {
29
32
  return;
30
33
  }
31
34
 
32
- VALUE serializer = sd_build_serializer(descriptor);
35
+ serializer = sd_build_serializer(descriptor);
33
36
  sd_apply_serializer_config(serializer, subject, context);
34
37
 
35
- long i;
36
38
  for (i = 0; i < RARRAY_LEN(method_fields); i++) {
37
39
  VALUE attribute_name = RARRAY_AREF(method_fields, i);
38
- VALUE result = rb_funcall(serializer, rb_sym2id(attribute_name), 0);
40
+ volatile VALUE result =
41
+ rb_funcall(serializer, rb_sym2id(attribute_name), 0);
39
42
 
40
43
  write_value(str_writer, rb_sym2str(attribute_name), result, Qnil);
41
44
  }
@@ -53,7 +56,8 @@ void serialize_fields(VALUE subject,
53
56
  VALUE str_writer,
54
57
  SerializationDescriptor descriptor,
55
58
  VALUE context) {
56
- panko_each_attribute(subject, descriptor->fields, panko_attributes_iter, str_writer);
59
+ panko_each_attribute(subject, descriptor->fields, panko_attributes_iter,
60
+ str_writer);
57
61
 
58
62
  serialize_method_fields(subject, str_writer, descriptor, context);
59
63
  }
@@ -65,11 +69,11 @@ void serialize_has_one_associatoins(VALUE subject,
65
69
  VALUE associations) {
66
70
  long i;
67
71
  for (i = 0; i < RARRAY_LEN(associations); i++) {
68
- VALUE association = RARRAY_AREF(associations, i);
72
+ volatile VALUE association = RARRAY_AREF(associations, i);
69
73
 
70
- VALUE name = RARRAY_AREF(association, 0);
71
- VALUE association_descriptor = RARRAY_AREF(association, 1);
72
- VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
74
+ volatile VALUE name = RARRAY_AREF(association, 0);
75
+ volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
76
+ volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
73
77
 
74
78
  if (value == Qnil) {
75
79
  write_value(str_writer, rb_sym2str(name), value, Qnil);
@@ -87,11 +91,11 @@ void serialize_has_many_associatoins(VALUE subject,
87
91
  VALUE associations) {
88
92
  long i;
89
93
  for (i = 0; i < RARRAY_LEN(associations); i++) {
90
- VALUE association = RARRAY_AREF(associations, i);
94
+ volatile VALUE association = RARRAY_AREF(associations, i);
91
95
 
92
- VALUE name = RARRAY_AREF(association, 0);
93
- VALUE association_descriptor = RARRAY_AREF(association, 1);
94
- VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
96
+ volatile VALUE name = RARRAY_AREF(association, 0);
97
+ volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
98
+ volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
95
99
 
96
100
  if (value == Qnil) {
97
101
  write_value(str_writer, rb_sym2str(name), value, Qnil);
@@ -131,15 +135,16 @@ VALUE serialize_subjects(VALUE key,
131
135
  VALUE str_writer,
132
136
  SerializationDescriptor descriptor,
133
137
  VALUE context) {
138
+ long i;
139
+
134
140
  rb_funcall(str_writer, push_array_id, 1, key);
135
141
 
136
142
  if (!RB_TYPE_P(subjects, T_ARRAY)) {
137
143
  subjects = rb_funcall(subjects, to_a_id, 0);
138
144
  }
139
145
 
140
- long i;
141
146
  for (i = 0; i < RARRAY_LEN(subjects); i++) {
142
- VALUE subject = RARRAY_AREF(subjects, i);
147
+ volatile VALUE subject = RARRAY_AREF(subjects, i);
143
148
  serialize_subject(Qnil, subject, str_writer, descriptor, context);
144
149
  }
145
150
 
@@ -168,11 +173,11 @@ VALUE serialize_subjects_api(VALUE klass,
168
173
  }
169
174
 
170
175
  void Init_panko_serializer() {
171
- CONST_ID(push_value_id, "push_value");
172
- CONST_ID(push_array_id, "push_array");
173
- CONST_ID(push_object_id, "push_object");
174
- CONST_ID(pop_id, "pop");
175
- CONST_ID(to_a_id, "to_a");
176
+ push_value_id = rb_intern("push_value");
177
+ push_array_id = rb_intern("push_array");
178
+ push_object_id = rb_intern("push_object");
179
+ pop_id = rb_intern("pop");
180
+ to_a_id = rb_intern("to_a");
176
181
 
177
182
  VALUE mPanko = rb_define_module("Panko");
178
183
 
@@ -2,15 +2,16 @@
2
2
 
3
3
  VALUE cSerializationDescriptor;
4
4
 
5
- static ID context_id = 0;
6
- static ID object_id = 0;
5
+ static ID context_id;
6
+ static ID object_id;
7
7
 
8
8
  static void serialization_descriptor_free(void* ptr) {
9
+ SerializationDescriptor sd;
9
10
  if (ptr == 0) {
10
11
  return;
11
12
  }
12
13
 
13
- SerializationDescriptor sd = (SerializationDescriptor)ptr;
14
+ sd = (SerializationDescriptor)ptr;
14
15
  sd->serializer_type = Qnil;
15
16
  sd->serializer = Qnil;
16
17
  sd->fields = Qnil;
@@ -64,7 +65,6 @@ void sd_apply_serializer_config(VALUE serializer, VALUE object, VALUE context) {
64
65
  rb_ivar_set(serializer, context_id, context);
65
66
  }
66
67
 
67
-
68
68
  VALUE serialization_descriptor_fields_set(VALUE self, VALUE fields) {
69
69
  SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
70
70
 
@@ -121,6 +121,11 @@ VALUE serialization_descriptor_type_set(VALUE self, VALUE type) {
121
121
  return Qnil;
122
122
  }
123
123
 
124
+ VALUE serialization_descriptor_type_aref(VALUE self, VALUE type) {
125
+ SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
126
+ return sd->serializer_type;
127
+ }
128
+
124
129
  // Exposing this for testing
125
130
  VALUE serialization_descriptor_build_serializer(VALUE self) {
126
131
  SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
@@ -128,8 +133,8 @@ VALUE serialization_descriptor_build_serializer(VALUE self) {
128
133
  }
129
134
 
130
135
  void panko_init_serialization_descriptor(VALUE mPanko) {
131
- CONST_ID(object_id, "@object");
132
- CONST_ID(context_id, "@context");
136
+ object_id = rb_intern("@object");
137
+ context_id = rb_intern("@context");
133
138
 
134
139
  cSerializationDescriptor =
135
140
  rb_define_class_under(mPanko, "SerializationDescriptor", rb_cObject);
@@ -160,6 +165,8 @@ void panko_init_serialization_descriptor(VALUE mPanko) {
160
165
 
161
166
  rb_define_method(cSerializationDescriptor,
162
167
  "type=", serialization_descriptor_type_set, 1);
168
+ rb_define_method(cSerializationDescriptor,
169
+ "type", serialization_descriptor_type_aref, 0);
163
170
 
164
171
  rb_define_method(cSerializationDescriptor, "build_serializer",
165
172
  serialization_descriptor_build_serializer, 0);
@@ -1,65 +1,79 @@
1
1
  #include "time_conversion.h"
2
2
 
3
+ const int YEAR_REGION = 1;
4
+ const int MONTH_REGION = 2;
5
+ const int DAY_REGION = 3;
6
+ const int HOUR_REGION = 4;
7
+ const int MINUTE_REGION = 5;
8
+ const int SECOND_REGION = 6;
9
+
3
10
  static regex_t* iso8601_time_regex;
4
11
  static regex_t* ar_iso_datetime_regex;
5
12
 
6
13
  VALUE is_iso8601_time_string(const char* value) {
7
14
  const UChar *start, *range, *end;
15
+ OnigPosition r;
8
16
 
9
17
  const UChar* str = (const UChar*)(value);
10
18
 
11
19
  end = str + strlen(value);
12
20
  start = str;
13
21
  range = end;
14
- OnigPosition r = onig_search(iso8601_time_regex, str, end, start, range, NULL,
15
- ONIG_OPTION_NONE);
22
+ r = onig_search(iso8601_time_regex, str, end, start, range, NULL,
23
+ ONIG_OPTION_NONE);
16
24
 
17
25
  return r >= 0 ? Qtrue : Qfalse;
18
26
  }
19
27
 
20
- void append_region_part(char* buf,
21
- const char* value,
22
- const OnigRegion* region,
23
- int i) {
24
- long substringLength = region->end[i] - region->beg[i];
25
- strncat(buf, value + region->beg[i], substringLength);
28
+ void append_region(const char* source,
29
+ char** to,
30
+ const OnigRegion* region,
31
+ int region_number) {
32
+ long iter = 0;
33
+ long regionEnd = region->end[region_number];
34
+ for (iter = region->beg[region_number]; iter < regionEnd; iter++) {
35
+ *(*to)++ = source[iter];
36
+ }
26
37
  }
27
38
 
28
39
  VALUE iso_ar_iso_datetime_string(const char* value) {
29
40
  const UChar *start, *range, *end;
41
+ OnigPosition r;
30
42
  OnigRegion* region = onig_region_new();
43
+ volatile VALUE output;
31
44
 
32
45
  const UChar* str = (const UChar*)(value);
33
46
 
34
47
  end = str + strlen(value);
35
48
  start = str;
36
49
  range = end;
37
- OnigPosition r = onig_search(ar_iso_datetime_regex, str, end, start, range,
38
- region, ONIG_OPTION_NONE);
50
+ r = onig_search(ar_iso_datetime_regex, str, end, start, range, region,
51
+ ONIG_OPTION_NONE);
39
52
 
40
- VALUE output = Qnil;
53
+ output = Qnil;
41
54
  if (r >= 0) {
42
55
  char buf[21] = "";
56
+ char* cur = buf;
43
57
 
44
- append_region_part(buf, value, region, 1);
45
- strncat(buf, "-", 1);
58
+ append_region(value, &cur, region, YEAR_REGION);
59
+ *cur++ = '-';
46
60
 
47
- append_region_part(buf, value, region, 2);
48
- strncat(buf, "-", 1);
61
+ append_region(value, &cur, region, MONTH_REGION);
62
+ *cur++ = '-';
49
63
 
50
- append_region_part(buf, value, region, 3);
51
- strncat(buf, "T", 1);
64
+ append_region(value, &cur, region, DAY_REGION);
65
+ *cur++ = 'T';
52
66
 
53
- append_region_part(buf, value, region, 4);
54
- strncat(buf, ":", 1);
67
+ append_region(value, &cur, region, HOUR_REGION);
68
+ *cur++ = ':';
55
69
 
56
- append_region_part(buf, value, region, 5);
57
- strncat(buf, ":", 1);
70
+ append_region(value, &cur, region, MINUTE_REGION);
71
+ *cur++ = ':';
58
72
 
59
- append_region_part(buf, value, region, 6);
60
- strncat(buf, "Z", 1);
73
+ append_region(value, &cur, region, SECOND_REGION);
74
+ *cur++ = 'Z';
61
75
 
62
- output = rb_str_new(buf, strlen(buf));
76
+ output = rb_str_new(buf, cur - buf);
63
77
  }
64
78
 
65
79
  onig_region_free(region, 1);
@@ -81,12 +95,14 @@ void build_regex(OnigRegex* reg, const UChar* pattern) {
81
95
  }
82
96
 
83
97
  void panko_init_time(VALUE mPanko) {
84
- const UChar* ISO8601_PATTERN =
98
+ const UChar *ISO8601_PATTERN, *AR_ISO_DATETIME_PATTERN;
99
+
100
+ ISO8601_PATTERN =
85
101
  (UChar*)"^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$";
86
102
 
87
103
  build_regex(&iso8601_time_regex, ISO8601_PATTERN);
88
104
 
89
- const UChar* AR_ISO_DATETIME_PATTERN =
105
+ AR_ISO_DATETIME_PATTERN =
90
106
  (UChar*)"\\A(?<year>\\d{4})-(?<month>\\d\\d)-(?<mday>\\d\\d) (?<hour>\\d\\d):(?<min>\\d\\d):(?<sec>\\d\\d)(\\.(?<microsec>\\d+))?\\z";
91
107
 
92
108
  build_regex(&ar_iso_datetime_regex, AR_ISO_DATETIME_PATTERN);
@@ -1,9 +1,9 @@
1
1
  #include "type_cast.h"
2
2
  #include "time_conversion.h"
3
3
 
4
- static ID type_cast_from_database_id = 0;
5
- static ID to_s_id = 0;
6
- static ID to_i_id = 0;
4
+ ID type_cast_from_database_id = 0;
5
+ ID to_s_id = 0;
6
+ ID to_i_id = 0;
7
7
 
8
8
  // Caching ActiveRecord Types
9
9
  static VALUE ar_string_type = Qundef;
@@ -23,19 +23,20 @@ static VALUE ar_pg_date_time_type = Qundef;
23
23
  static int initiailized = 0;
24
24
 
25
25
  VALUE cache_postgres_type_lookup(VALUE ar) {
26
- VALUE ar_connection_adapters =
27
- rb_const_get_at(ar, rb_intern("ConnectionAdapters"));
26
+ VALUE ar_connection_adapters, ar_postgresql, ar_oid;
27
+
28
+ ar_connection_adapters = rb_const_get_at(ar, rb_intern("ConnectionAdapters"));
28
29
  if (ar_connection_adapters == Qundef) {
29
30
  return Qfalse;
30
31
  }
31
32
 
32
- VALUE ar_postgresql =
33
+ ar_postgresql =
33
34
  rb_const_get_at(ar_connection_adapters, rb_intern("PostgreSQL"));
34
35
  if (ar_postgresql == Qundef) {
35
36
  return Qfalse;
36
37
  }
37
38
 
38
- VALUE ar_oid = rb_const_get_at(ar_postgresql, rb_intern("OID"));
39
+ ar_oid = rb_const_get_at(ar_postgresql, rb_intern("OID"));
39
40
  if (ar_oid == Qundef) {
40
41
  return Qfalse;
41
42
  }
@@ -50,14 +51,16 @@ VALUE cache_postgres_type_lookup(VALUE ar) {
50
51
  }
51
52
 
52
53
  VALUE cache_time_zone_type_lookup(VALUE ar) {
54
+ VALUE ar_attr_methods, ar_time_zone_conversion;
55
+
53
56
  // ActiveRecord::AttributeMethods
54
- VALUE ar_attr_methods = rb_const_get_at(ar, rb_intern("AttributeMethods"));
57
+ ar_attr_methods = rb_const_get_at(ar, rb_intern("AttributeMethods"));
55
58
  if (ar_attr_methods == Qundef) {
56
59
  return Qfalse;
57
60
  }
58
61
 
59
62
  // ActiveRecord::AttributeMethods::TimeZoneConversion
60
- VALUE ar_time_zone_conversion =
63
+ ar_time_zone_conversion =
61
64
  rb_const_get_at(ar_attr_methods, rb_intern("TimeZoneConversion"));
62
65
  if (ar_time_zone_conversion == Qundef) {
63
66
  return Qfalse;
@@ -76,10 +79,12 @@ void cache_type_lookup() {
76
79
 
77
80
  initiailized = 1;
78
81
 
79
- VALUE ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
82
+ VALUE ar, ar_type;
83
+
84
+ ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
80
85
 
81
86
  // ActiveRecord::Type
82
- VALUE ar_type = rb_const_get_at(ar, rb_intern("Type"));
87
+ ar_type = rb_const_get_at(ar, rb_intern("Type"));
83
88
 
84
89
  ar_string_type = rb_const_get_at(ar_type, rb_intern("String"));
85
90
  ar_text_type = rb_const_get_at(ar_type, rb_intern("Text"));
@@ -226,7 +231,7 @@ VALUE cast_date_time_type(VALUE value) {
226
231
  return value;
227
232
  }
228
233
 
229
- VALUE iso8601_string = iso_ar_iso_datetime_string(val);
234
+ volatile VALUE iso8601_string = iso_ar_iso_datetime_string(val);
230
235
  if (iso8601_string != Qnil) {
231
236
  return iso8601_string;
232
237
  }
@@ -238,8 +243,10 @@ VALUE cast_date_time_type(VALUE value) {
238
243
  VALUE type_cast(VALUE type_metadata, VALUE value) {
239
244
  cache_type_lookup();
240
245
 
241
- VALUE type_klass = CLASS_OF(type_metadata);
242
- VALUE typeCastedValue = Qundef;
246
+ VALUE type_klass, typeCastedValue;
247
+
248
+ type_klass = CLASS_OF(type_metadata);
249
+ typeCastedValue = Qundef;
243
250
 
244
251
  TypeCast typeCast;
245
252
  for (typeCast = type_casts; typeCast->canCast != NULL; typeCast++) {
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require_relative "cache"
3
2
 
4
3
  module Panko
5
4
  class ArraySerializer
@@ -15,7 +14,7 @@ module Panko
15
14
  except: options.fetch(:except, [])
16
15
  }
17
16
 
18
- @descriptor = Panko::CACHE.fetch(@each_serializer, serializer_options)
17
+ @descriptor = SerializationDescriptorBuilder.build(@each_serializer, serializer_options)
19
18
  @context = options.fetch(:context, nil)
20
19
  end
21
20
 
@@ -1,32 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
  module Panko
3
3
  module SerializationDescriptorBuilder
4
- def self.build(serializer, options={})
5
- backend = Panko::SerializationDescriptor.new
6
-
4
+ def self.apply_filters(backend, options)
7
5
  serializer_only_filters, attributes_only_filters = resolve_filters(options, :only)
8
6
  serializer_except_filters, attributes_except_filters = resolve_filters(options, :except)
9
7
 
10
- fields, method_fields = fields_of(serializer)
11
-
12
- backend.type = serializer
13
-
14
8
  backend.fields = apply_fields_filters(
15
- fields,
9
+ backend.fields,
16
10
  serializer_only_filters,
17
11
  serializer_except_filters
18
12
  )
19
- backend.fields = backend.fields.map &:to_s
20
13
 
21
14
  backend.method_fields = apply_fields_filters(
22
- method_fields,
15
+ backend.method_fields,
23
16
  serializer_only_filters,
24
17
  serializer_except_filters
25
18
  )
26
19
 
27
20
  backend.has_many_associations = build_associations(
28
21
  apply_association_filters(
29
- serializer._has_many_associations,
22
+ backend.has_many_associations,
30
23
  serializer_only_filters,
31
24
  serializer_except_filters
32
25
  ),
@@ -36,44 +29,49 @@ module Panko
36
29
 
37
30
  backend.has_one_associations = build_associations(
38
31
  apply_association_filters(
39
- serializer._has_one_associations,
32
+ backend.has_one_associations,
40
33
  serializer_only_filters,
41
34
  serializer_except_filters
42
35
  ),
43
36
  attributes_only_filters,
44
37
  attributes_except_filters
45
38
  )
39
+ end
40
+
41
+ def self.duplicate(descriptor)
42
+ backend = Panko::SerializationDescriptor.new
43
+
44
+ backend.type = descriptor.type
45
+
46
+ backend.fields = descriptor.fields
47
+ backend.method_fields = descriptor.method_fields
48
+
49
+ backend.has_many_associations = descriptor.has_many_associations
50
+ backend.has_one_associations = descriptor.has_one_associations
46
51
 
47
52
  backend
48
53
  end
49
54
 
50
- def self.fields_of(serializer)
51
- fields = []
52
- method_fields = []
55
+ def self.build(serializer, options={})
56
+ backend = duplicate(serializer._descriptor)
53
57
 
54
- serializer._attributes.each do |attribute|
55
- if serializer.method_defined? attribute
56
- method_fields << attribute
57
- else
58
- fields << attribute
59
- end
60
- end
58
+ apply_filters(backend, options)
61
59
 
62
- return fields, method_fields
60
+ backend
63
61
  end
64
62
 
65
63
  def self.build_associations(associations, attributes_only_filters, attributes_except_filters)
66
- associations.map do |association|
67
- options = association[:options]
68
- serializer_const = resolve_serializer(options[:serializer])
64
+ associations.each do |association|
65
+ name = association.first
66
+ descriptor = association.last
69
67
 
70
- options[:only] = options.fetch(:only, []) + attributes_only_filters.fetch(association[:name], [])
71
- options[:except] = options.fetch(:except, []) + attributes_except_filters.fetch(association[:name], [])
72
68
 
73
- [
74
- association[:name],
75
- SerializationDescriptorBuilder.build(serializer_const, options.except(:serializer))
76
- ]
69
+ options = {
70
+ only: attributes_only_filters.fetch(name, []),
71
+ except: attributes_except_filters.fetch(name, [])
72
+ }
73
+
74
+ apply_filters(descriptor, options)
77
75
  end
78
76
  end
79
77
 
@@ -88,6 +86,8 @@ module Panko
88
86
  # which mean, for the current instance use `[:a]` as filter
89
87
  # and for association named `foo` use `[:b]`
90
88
 
89
+ return [], {} if filters.empty?
90
+
91
91
  serializer_filters = filters.fetch(:instance, [])
92
92
  association_filters = filters.except(:instance)
93
93
 
@@ -95,19 +95,19 @@ module Panko
95
95
  end
96
96
 
97
97
  def self.apply_fields_filters(fields, only, except)
98
- return fields & only if only.present?
99
- return fields - except if except.present?
98
+ return fields & only unless only.empty?
99
+ return fields - except unless except.empty?
100
100
 
101
101
  fields
102
102
  end
103
103
 
104
104
  def self.apply_association_filters(associations, only, except)
105
- if only.present?
106
- return associations.select { |assoc| only.include?(assoc[:name]) }
105
+ unless only.empty?
106
+ return associations.select { |assoc| only.include?(assoc.first) }
107
107
  end
108
108
 
109
- if except.present?
110
- return associations.reject { |assoc| except.include?(assoc[:name]) }
109
+ unless except.empty?
110
+ return associations.reject { |assoc| except.include?(assoc.first) }
111
111
  end
112
112
 
113
113
  associations
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require_relative "cache"
3
2
  require_relative "serialization_descriptor"
4
3
  require "oj"
5
4
 
@@ -7,33 +6,48 @@ module Panko
7
6
  class Serializer
8
7
  class << self
9
8
  def inherited(base)
10
- base._attributes = (_attributes || []).dup
11
- base._has_one_associations = (_has_one_associations || []).dup
12
- base._has_many_associations = (_has_many_associations || []).dup
9
+ base._descriptor = Panko::SerializationDescriptor.new
10
+ base._descriptor.type = base
13
11
 
14
- @_attributes = []
15
- @_has_one_associations = []
16
- @_has_many_associations = []
12
+ base._descriptor.fields = []
13
+ base._descriptor.method_fields = []
14
+ base._descriptor.has_many_associations = []
15
+ base._descriptor.has_one_associations = []
17
16
  end
18
17
 
19
- attr_accessor :_attributes, :_has_one_associations, :_has_many_associations
18
+ attr_accessor :_descriptor
20
19
 
21
20
  def attributes(*attrs)
22
- @_attributes.push(*attrs).uniq!
21
+ @_descriptor.fields.push(*attrs).uniq!
22
+ end
23
+
24
+ def method_added(method)
25
+ return if @_descriptor.nil?
26
+ @_descriptor.fields.delete(method)
27
+ @_descriptor.method_fields << method
23
28
  end
24
29
 
25
30
  def has_one(name, options)
26
- @_has_one_associations << { name: name, options: options }
31
+ serializer_const = SerializationDescriptorBuilder.resolve_serializer(options[:serializer])
32
+
33
+ @_descriptor.has_one_associations << [
34
+ name,
35
+ SerializationDescriptorBuilder.build(serializer_const, options)
36
+ ]
27
37
  end
28
38
 
29
39
  def has_many(name, options)
30
- @_has_many_associations << { name: name, options: options }
40
+ serializer_const = SerializationDescriptorBuilder.resolve_serializer(options[:serializer])
41
+
42
+ @_descriptor.has_many_associations << [
43
+ name,
44
+ SerializationDescriptorBuilder.build(serializer_const, options)
45
+ ]
31
46
  end
32
47
  end
33
48
 
34
49
  def initialize(options = {})
35
- @descriptor = Panko::CACHE.fetch(self.class, options)
36
-
50
+ @descriptor = SerializationDescriptorBuilder.build(self.class, options)
37
51
  @context = options[:context]
38
52
  end
39
53
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Panko
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
@@ -27,5 +27,4 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rake-compiler"
28
28
 
29
29
  spec.add_dependency "oj", "~> 3.2.0"
30
- spec.add_dependency "concurrent-ruby"
31
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: panko_serializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yosi Attias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-22 00:00:00.000000000 Z
11
+ date: 2017-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 3.2.0
83
- - !ruby/object:Gem::Dependency
84
- name: concurrent-ruby
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
83
  description:
98
84
  email:
99
85
  - yosy101@gmail.com
@@ -139,7 +125,6 @@ files:
139
125
  - ext/panko_serializer/type_cast.h
140
126
  - lib/panko.rb
141
127
  - lib/panko/array_serializer.rb
142
- - lib/panko/cache.rb
143
128
  - lib/panko/response.rb
144
129
  - lib/panko/serialization_descriptor.rb
145
130
  - lib/panko/serializer.rb
@@ -165,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
150
  version: '0'
166
151
  requirements: []
167
152
  rubyforge_project:
168
- rubygems_version: 2.6.12
153
+ rubygems_version: 2.6.13
169
154
  signing_key:
170
155
  specification_version: 4
171
156
  summary: Fast serialization for ActiveModel
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
- require "concurrent"
3
-
4
-
5
- module Panko
6
- # Serialer Descriptor Cache
7
- class Cache
8
- def initialize
9
- @_cache = Concurrent::Map.new
10
- end
11
-
12
- def fetch(serializer_const, options)
13
- serializer_key = build_key(serializer_const, options[:only], options[:except])
14
- serializer = @_cache.compute_if_absent(serializer_key) {
15
- SerializationDescriptorBuilder.build(serializer_const,
16
- only: options.fetch(:only, []),
17
- except: options.fetch(:except, [])
18
- )
19
- }
20
-
21
- serializer
22
- end
23
-
24
- private
25
-
26
- #
27
- # Create key based on what we define unique serializer
28
- #
29
- def build_key(serializer_const, only, except)
30
- [serializer_const, only, except].hash
31
- end
32
- end
33
-
34
- CACHE = Panko::Cache.new
35
- end