panko_serializer 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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