panko_serializer 0.1.10 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +8 -2
- data/Gemfile +8 -9
- data/benchmarks/type_casts/bm_active_record.rb +41 -13
- data/benchmarks/type_casts/bm_panko.rb +8 -3
- data/ext/panko_serializer/attributes_iterator.c +49 -25
- data/ext/panko_serializer/type_cast.c +11 -5
- data/lib/panko/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f657c0585ef9811fe8d9fcf0e2d1556869823b72
|
4
|
+
data.tar.gz: 9e4cc917aabb38d3b803e0978fc312b5fe5696da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd44b3774e47cbd74a400c53040f41bc9edb7f58c1dc63a1e7c530827b2c878948bdfebe6c0250c59ea5af122ef281113f09402fd282e4f16aff5d883ca5df8f
|
7
|
+
data.tar.gz: 3da4b8644375ed05481a7d9e00e27082ee5274eea06a60282395abe5aab06b90f0c17d4b525bcc4c44c08a5e48108f6cc725e9c6a6e85ee40c6c70b4f21e9102
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,7 +2,13 @@ sudo: false
|
|
2
2
|
cache: bundler
|
3
3
|
language: ruby
|
4
4
|
rvm:
|
5
|
-
- 2.4.
|
6
|
-
|
5
|
+
- 2.4.2
|
6
|
+
install: bundle install --path=vendor/bundle --retry=3 --jobs=3
|
7
7
|
before_install: gem install bundler
|
8
8
|
after_success: bundle exec rake benchmarks
|
9
|
+
|
10
|
+
env:
|
11
|
+
matrix:
|
12
|
+
- "RAILS_VERSION=4.2"
|
13
|
+
- "RAILS_VERSION=5.0"
|
14
|
+
- "RAILS_VERSION=5.1"
|
data/Gemfile
CHANGED
@@ -3,15 +3,14 @@ source "https://rubygems.org"
|
|
3
3
|
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
gem "
|
10
|
-
gem "
|
11
|
-
gem "
|
12
|
-
gem "
|
13
|
-
gem "
|
14
|
-
gem "activerecord", gem_version, group: :test
|
6
|
+
rails_version = "~> #{ENV.fetch("RAILS_VERSION", "4.2")}"
|
7
|
+
|
8
|
+
gem "rails", rails_version
|
9
|
+
gem "railties", rails_version
|
10
|
+
gem "activesupport", rails_version
|
11
|
+
gem "activemodel", rails_version
|
12
|
+
gem "actionpack", rails_version
|
13
|
+
gem "activerecord", rails_version, group: :test
|
15
14
|
|
16
15
|
group :benchmarks do
|
17
16
|
gem "sqlite3"
|
@@ -3,14 +3,27 @@ require_relative "./support"
|
|
3
3
|
|
4
4
|
def ar_type_convert(type_klass, from, to)
|
5
5
|
converter = type_klass.new
|
6
|
-
assert type_klass.name, converter.type_cast_from_database(from), to
|
7
6
|
|
8
|
-
|
9
|
-
converter.type_cast_from_database(from)
|
10
|
-
|
7
|
+
if ENV["RAILS_VERSION"].start_with? "4.2"
|
8
|
+
assert type_klass.name, converter.type_cast_from_database(from), to
|
9
|
+
|
10
|
+
Benchmark.run("#{type_klass.name}_TypeCast") do
|
11
|
+
converter.type_cast_from_database(from)
|
12
|
+
end
|
13
|
+
|
14
|
+
Benchmark.run("#{type_klass.name}_NoTypeCast") do
|
15
|
+
converter.type_cast_from_database(to)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
assert type_klass.name, converter.deserialize(from), to
|
11
19
|
|
12
|
-
|
13
|
-
|
20
|
+
Benchmark.run("#{type_klass.name}_TypeCast") do
|
21
|
+
converter.deserialize(from)
|
22
|
+
end
|
23
|
+
|
24
|
+
Benchmark.run("#{type_klass.name}_NoTypeCast") do
|
25
|
+
converter.deserialize(to)
|
26
|
+
end
|
14
27
|
end
|
15
28
|
end
|
16
29
|
|
@@ -22,8 +35,14 @@ def utc_ar_time
|
|
22
35
|
type = ActiveRecord::ConnectionAdapters::PostgreSQL::OID::DateTime.new
|
23
36
|
converter = ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter.new(type)
|
24
37
|
|
25
|
-
|
26
|
-
|
38
|
+
if ENV["RAILS_VERSION"].start_with? "4.2"
|
39
|
+
Benchmark.run("#{tz}_#{type.class.name}_TypeCast") do
|
40
|
+
converter.type_cast_from_database(from).iso8601
|
41
|
+
end
|
42
|
+
else
|
43
|
+
Benchmark.run("#{tz}_#{type.class.name}_TypeCast") do
|
44
|
+
converter.deserialize(from).iso8601
|
45
|
+
end
|
27
46
|
end
|
28
47
|
end
|
29
48
|
|
@@ -35,8 +54,15 @@ def db_ar_time
|
|
35
54
|
|
36
55
|
from = "2017-07-10 09:26:40.937392"
|
37
56
|
|
38
|
-
|
39
|
-
|
57
|
+
|
58
|
+
if ENV["RAILS_VERSION"].start_with? "4.2"
|
59
|
+
Benchmark.run("ActiveRecord_Time_TypeCast_WithISO8601") do
|
60
|
+
converter.type_cast_from_database(from).iso8601
|
61
|
+
end
|
62
|
+
else
|
63
|
+
Benchmark.run("ActiveRecord_Time_TypeCast_WithISO8601") do
|
64
|
+
converter.deserialize(from).iso8601
|
65
|
+
end
|
40
66
|
end
|
41
67
|
end
|
42
68
|
|
@@ -48,9 +74,11 @@ ar_type_convert ActiveRecord::Type::Float, "Infinity", 0.0
|
|
48
74
|
ar_type_convert ActiveRecord::Type::Boolean, "true", true
|
49
75
|
ar_type_convert ActiveRecord::Type::Boolean, "t", true
|
50
76
|
|
51
|
-
|
52
|
-
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::
|
53
|
-
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "
|
77
|
+
if ENV["RAILS_VERSION"].start_with? "4.2"
|
78
|
+
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer, "1", 1
|
79
|
+
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "1.23", 1.23
|
80
|
+
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "Infinity", ::Float::INFINITY
|
81
|
+
end
|
54
82
|
ar_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
55
83
|
|
56
84
|
db_ar_time
|
@@ -44,6 +44,9 @@ def db_panko_time
|
|
44
44
|
Panko::_type_cast(converter, from)
|
45
45
|
end
|
46
46
|
end
|
47
|
+
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
48
|
+
db_panko_time
|
49
|
+
utc_panko_time
|
47
50
|
|
48
51
|
panko_type_convert ActiveRecord::Type::String, 1, "1"
|
49
52
|
panko_type_convert ActiveRecord::Type::Text, 1, "1"
|
@@ -53,9 +56,11 @@ panko_type_convert ActiveRecord::Type::Float, "Infinity", ::Float::INFINITY
|
|
53
56
|
panko_type_convert ActiveRecord::Type::Boolean, "true", true
|
54
57
|
panko_type_convert ActiveRecord::Type::Boolean, "t", true
|
55
58
|
|
56
|
-
|
57
|
-
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::
|
58
|
-
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "
|
59
|
+
if ENV["RAILS_VERSION"].start_with? "4.2"
|
60
|
+
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Integer, "1", 1
|
61
|
+
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "1.23", 1.23
|
62
|
+
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Float, "Infinity", ::Float::INFINITY
|
63
|
+
end
|
59
64
|
|
60
65
|
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
61
66
|
db_panko_time
|
@@ -14,19 +14,15 @@ VALUE read_attributes(VALUE obj) {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
VALUE panko_read_lazy_attributes_hash(VALUE object) {
|
17
|
-
volatile VALUE attributes_set,
|
17
|
+
volatile VALUE attributes_set, lazy_attributes_hash;
|
18
18
|
|
19
19
|
attributes_set = read_attributes(object);
|
20
20
|
if (attributes_set == Qnil) {
|
21
21
|
return Qnil;
|
22
22
|
}
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
return Qnil;
|
27
|
-
}
|
28
|
-
|
29
|
-
return attributes_hash;
|
24
|
+
lazy_attributes_hash = read_attributes(attributes_set);
|
25
|
+
return lazy_attributes_hash;
|
30
26
|
}
|
31
27
|
|
32
28
|
void panko_read_types_and_value(VALUE attributes_hash,
|
@@ -38,28 +34,60 @@ void panko_read_types_and_value(VALUE attributes_hash,
|
|
38
34
|
*values = rb_ivar_get(attributes_hash, values_id);
|
39
35
|
}
|
40
36
|
|
37
|
+
bool panko_is_empty_hash(VALUE hash) {
|
38
|
+
if (hash == Qnil || hash == Qundef) {
|
39
|
+
return true;
|
40
|
+
}
|
41
|
+
|
42
|
+
return RHASH_SIZE(hash) == 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
void read_attribute_from_hash(VALUE attributes_hash,
|
46
|
+
VALUE member,
|
47
|
+
volatile VALUE* value,
|
48
|
+
volatile VALUE* type) {
|
49
|
+
volatile VALUE attribute_metadata = rb_hash_aref(attributes_hash, member);
|
50
|
+
if (attribute_metadata != Qnil) {
|
51
|
+
*value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
|
52
|
+
*type = rb_ivar_get(attribute_metadata, type_id);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
41
56
|
VALUE panko_each_attribute(VALUE obj,
|
42
57
|
VALUE attributes,
|
43
58
|
VALUE aliases,
|
44
59
|
EachAttributeFunc func,
|
45
60
|
VALUE context) {
|
46
|
-
volatile VALUE
|
61
|
+
volatile VALUE lazy_attribute_hash, delegate_hash;
|
62
|
+
VALUE values = Qundef;
|
63
|
+
VALUE types = Qundef;
|
64
|
+
VALUE additional_types = Qundef;
|
47
65
|
int i;
|
48
66
|
|
49
|
-
|
50
|
-
if (
|
67
|
+
lazy_attribute_hash = panko_read_lazy_attributes_hash(obj);
|
68
|
+
if (lazy_attribute_hash == Qnil) {
|
51
69
|
return Qnil;
|
52
70
|
}
|
53
71
|
|
54
|
-
|
55
|
-
bool
|
72
|
+
bool tryToReadFromDelegateHash = false;
|
73
|
+
bool tryToReadFromAdditionalTypes = false;
|
56
74
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
75
|
+
// If lazy_attribute_hash is not ActiveRecord::LazyAttributeHash
|
76
|
+
// and it's actually hash, read from it
|
77
|
+
if (RB_TYPE_P(lazy_attribute_hash, T_HASH)) {
|
78
|
+
delegate_hash = lazy_attribute_hash;
|
79
|
+
tryToReadFromDelegateHash = true;
|
80
|
+
} else {
|
81
|
+
delegate_hash = rb_ivar_get(lazy_attribute_hash, delegate_hash_id);
|
82
|
+
tryToReadFromDelegateHash = !panko_is_empty_hash(delegate_hash);
|
61
83
|
|
62
|
-
|
84
|
+
panko_read_types_and_value(lazy_attribute_hash, &types, &additional_types,
|
85
|
+
&values);
|
86
|
+
|
87
|
+
tryToReadFromAdditionalTypes = !panko_is_empty_hash(additional_types);
|
88
|
+
}
|
89
|
+
|
90
|
+
bool tryToReadFromAliases = !panko_is_empty_hash(aliases);
|
63
91
|
|
64
92
|
for (i = 0; i < RARRAY_LEN(attributes); i++) {
|
65
93
|
volatile VALUE member_raw = RARRAY_AREF(attributes, i);
|
@@ -72,14 +100,10 @@ VALUE panko_each_attribute(VALUE obj,
|
|
72
100
|
// If the object was create in memory `User.new(name: "Yosi")`
|
73
101
|
// it won't exist in types/values
|
74
102
|
if (tryToReadFromDelegateHash) {
|
75
|
-
|
76
|
-
if (attribute_metadata != Qnil) {
|
77
|
-
value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
|
78
|
-
type_metadata = rb_ivar_get(attribute_metadata, type_id);
|
79
|
-
}
|
103
|
+
read_attribute_from_hash(delegate_hash, member, &value, &type_metadata);
|
80
104
|
}
|
81
105
|
|
82
|
-
if (value == Qundef) {
|
106
|
+
if (values != Qundef && value == Qundef) {
|
83
107
|
value = rb_hash_aref(values, member);
|
84
108
|
|
85
109
|
if (tryToReadFromAdditionalTypes) {
|
@@ -90,9 +114,9 @@ VALUE panko_each_attribute(VALUE obj,
|
|
90
114
|
}
|
91
115
|
}
|
92
116
|
|
93
|
-
if(tryToReadFromAliases) {
|
117
|
+
if (tryToReadFromAliases) {
|
94
118
|
volatile VALUE alias_name = rb_hash_aref(aliases, member_raw);
|
95
|
-
if(alias_name != Qnil) {
|
119
|
+
if (alias_name != Qnil) {
|
96
120
|
member = rb_sym2str(alias_name);
|
97
121
|
}
|
98
122
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#include "type_cast.h"
|
2
2
|
#include "time_conversion.h"
|
3
3
|
|
4
|
-
ID
|
4
|
+
ID deserialize_from_db_id = 0;
|
5
5
|
ID to_s_id = 0;
|
6
6
|
ID to_i_id = 0;
|
7
7
|
|
@@ -79,7 +79,7 @@ void cache_type_lookup() {
|
|
79
79
|
|
80
80
|
initiailized = 1;
|
81
81
|
|
82
|
-
VALUE ar, ar_type;
|
82
|
+
VALUE ar, ar_type, ar_type_methods;
|
83
83
|
|
84
84
|
ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
|
85
85
|
|
@@ -93,6 +93,13 @@ void cache_type_lookup() {
|
|
93
93
|
ar_boolean_type = rb_const_get_at(ar_type, rb_intern("Boolean"));
|
94
94
|
ar_date_time_type = rb_const_get_at(ar_type, rb_intern("DateTime"));
|
95
95
|
|
96
|
+
ar_type_methods = rb_class_instance_methods(0, NULL, ar_string_type);
|
97
|
+
if(rb_ary_includes(ar_type_methods, rb_to_symbol(rb_str_new_cstr("deserialize")))) {
|
98
|
+
deserialize_from_db_id = rb_intern("deserialize");
|
99
|
+
} else {
|
100
|
+
deserialize_from_db_id = rb_intern("type_cast_from_database");
|
101
|
+
}
|
102
|
+
|
96
103
|
// TODO: if we get error or not, add this to some debug log
|
97
104
|
int isErrored;
|
98
105
|
rb_protect(cache_postgres_type_lookup, ar, &isErrored);
|
@@ -241,7 +248,7 @@ VALUE cast_date_time_type(VALUE value) {
|
|
241
248
|
}
|
242
249
|
|
243
250
|
VALUE type_cast(VALUE type_metadata, VALUE value) {
|
244
|
-
if(value == Qnil || value == Qundef) {
|
251
|
+
if (value == Qnil || value == Qundef) {
|
245
252
|
return value;
|
246
253
|
}
|
247
254
|
|
@@ -261,7 +268,7 @@ VALUE type_cast(VALUE type_metadata, VALUE value) {
|
|
261
268
|
}
|
262
269
|
|
263
270
|
if (typeCastedValue == Qundef) {
|
264
|
-
return rb_funcall(type_metadata,
|
271
|
+
return rb_funcall(type_metadata, deserialize_from_db_id, 1, value);
|
265
272
|
}
|
266
273
|
|
267
274
|
return typeCastedValue;
|
@@ -272,7 +279,6 @@ VALUE public_type_cast(VALUE module, VALUE type_metadata, VALUE value) {
|
|
272
279
|
}
|
273
280
|
|
274
281
|
void panko_init_type_cast(VALUE mPanko) {
|
275
|
-
type_cast_from_database_id = rb_intern_const("type_cast_from_database");
|
276
282
|
to_s_id = rb_intern_const("to_s");
|
277
283
|
to_i_id = rb_intern_const("to_i");
|
278
284
|
|
data/lib/panko/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.0
|
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-10-
|
11
|
+
date: 2017-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|