paquito 0.2.1 → 0.4.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/.github/workflows/ci.yml +15 -0
- data/Gemfile +4 -3
- data/Gemfile.lock +27 -25
- data/README.md +25 -12
- data/benchmark/msgpack-pooling.rb +19 -0
- data/lib/paquito/allow_nil.rb +2 -0
- data/lib/paquito/cache_entry_coder.rb +22 -0
- data/lib/paquito/codec_factory.rb +21 -8
- data/lib/paquito/safe_yaml.rb +20 -14
- data/lib/paquito/typed_struct.rb +1 -0
- data/lib/paquito/types.rb +45 -14
- data/lib/paquito/version.rb +1 -1
- data/lib/paquito.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd3a891430b40fa7fad9d50b8f383070cee22cba06d19c0db67670324c575613
|
|
4
|
+
data.tar.gz: 752e27818f5781652fc91407b51a7f5c16e0a8a07baa0f1285b3e4a3c9029bb0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b25933ab48ec3327e7e2c781f6502f90ed7a440163e58c3255d43bb1473fc5da5414b44d85f06de7f0d90ef05d57871bd8fcb3aabd22caa19d97df3422240d2
|
|
7
|
+
data.tar.gz: aca4aa6e5d417d40926d9cf57045157d1eaffdae225cc051b97ad861e0dc2d19fecf1f6acdea1a9fa91982697cee231326d410a21b0c130f327fc21f967c914e
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -3,6 +3,21 @@ name: CI
|
|
|
3
3
|
on: [push, pull_request]
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
|
+
rubocop:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
fail-fast: false
|
|
10
|
+
steps:
|
|
11
|
+
- name: Checkout
|
|
12
|
+
uses: actions/checkout@v2
|
|
13
|
+
- name: Set up Ruby
|
|
14
|
+
uses: ruby/setup-ruby@v1
|
|
15
|
+
with:
|
|
16
|
+
ruby-version: '2.7'
|
|
17
|
+
bundler-cache: true
|
|
18
|
+
- name: Run test
|
|
19
|
+
run: bundle exec rubocop
|
|
20
|
+
|
|
6
21
|
rubies:
|
|
7
22
|
runs-on: ubuntu-latest
|
|
8
23
|
strategy:
|
data/Gemfile
CHANGED
|
@@ -5,12 +5,13 @@ source "https://rubygems.org"
|
|
|
5
5
|
# Specify your gem's dependencies in paquito.gemspec
|
|
6
6
|
gemspec
|
|
7
7
|
|
|
8
|
-
gem "msgpack", github: "msgpack/msgpack-ruby"
|
|
8
|
+
gem "msgpack", github: "msgpack/msgpack-ruby"
|
|
9
9
|
|
|
10
10
|
gem "rake", "~> 13.0"
|
|
11
|
-
gem "activesupport", ">= 7.0.0
|
|
12
|
-
gem "activerecord", ">= 7.0.0
|
|
11
|
+
gem "activesupport", ">= 7.0.0"
|
|
12
|
+
gem "activerecord", ">= 7.0.0"
|
|
13
13
|
gem "sqlite3"
|
|
14
|
+
gem "benchmark-ips"
|
|
14
15
|
|
|
15
16
|
gem "minitest", "~> 5.0"
|
|
16
17
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,56 +1,57 @@
|
|
|
1
1
|
GIT
|
|
2
2
|
remote: https://github.com/msgpack/msgpack-ruby.git
|
|
3
|
-
revision:
|
|
3
|
+
revision: b69e6d6965ef46890885ddf73f02b820f3185d80
|
|
4
4
|
specs:
|
|
5
|
-
msgpack (1.4.
|
|
5
|
+
msgpack (1.4.5)
|
|
6
6
|
|
|
7
7
|
PATH
|
|
8
8
|
remote: .
|
|
9
9
|
specs:
|
|
10
|
-
paquito (0.
|
|
10
|
+
paquito (0.4.0)
|
|
11
11
|
msgpack
|
|
12
12
|
|
|
13
13
|
GEM
|
|
14
14
|
remote: https://rubygems.org/
|
|
15
15
|
specs:
|
|
16
|
-
activemodel (7.0.
|
|
17
|
-
activesupport (= 7.0.
|
|
18
|
-
activerecord (7.0.
|
|
19
|
-
activemodel (= 7.0.
|
|
20
|
-
activesupport (= 7.0.
|
|
21
|
-
activesupport (7.0.
|
|
16
|
+
activemodel (7.0.2.3)
|
|
17
|
+
activesupport (= 7.0.2.3)
|
|
18
|
+
activerecord (7.0.2.3)
|
|
19
|
+
activemodel (= 7.0.2.3)
|
|
20
|
+
activesupport (= 7.0.2.3)
|
|
21
|
+
activesupport (7.0.2.3)
|
|
22
22
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
23
23
|
i18n (>= 1.6, < 2)
|
|
24
24
|
minitest (>= 5.1)
|
|
25
25
|
tzinfo (~> 2.0)
|
|
26
26
|
ast (2.4.2)
|
|
27
|
+
benchmark-ips (2.10.0)
|
|
27
28
|
byebug (11.1.3)
|
|
28
29
|
concurrent-ruby (1.1.9)
|
|
29
|
-
i18n (1.
|
|
30
|
+
i18n (1.10.0)
|
|
30
31
|
concurrent-ruby (~> 1.0)
|
|
31
|
-
minitest (5.
|
|
32
|
+
minitest (5.15.0)
|
|
32
33
|
parallel (1.21.0)
|
|
33
|
-
parser (3.
|
|
34
|
+
parser (3.1.1.0)
|
|
34
35
|
ast (~> 2.4.1)
|
|
35
|
-
rainbow (3.
|
|
36
|
+
rainbow (3.1.1)
|
|
36
37
|
rake (13.0.6)
|
|
37
|
-
regexp_parser (2.
|
|
38
|
+
regexp_parser (2.2.1)
|
|
38
39
|
rexml (3.2.5)
|
|
39
|
-
rubocop (1.
|
|
40
|
+
rubocop (1.25.1)
|
|
40
41
|
parallel (~> 1.10)
|
|
41
|
-
parser (>= 3.
|
|
42
|
+
parser (>= 3.1.0.0)
|
|
42
43
|
rainbow (>= 2.2.2, < 4.0)
|
|
43
44
|
regexp_parser (>= 1.8, < 3.0)
|
|
44
45
|
rexml
|
|
45
|
-
rubocop-ast (>= 1.
|
|
46
|
+
rubocop-ast (>= 1.15.1, < 2.0)
|
|
46
47
|
ruby-progressbar (~> 1.7)
|
|
47
48
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
48
|
-
rubocop-ast (1.
|
|
49
|
-
parser (>= 3.
|
|
50
|
-
rubocop-shopify (2.
|
|
51
|
-
rubocop (~> 1.
|
|
49
|
+
rubocop-ast (1.16.0)
|
|
50
|
+
parser (>= 3.1.1.0)
|
|
51
|
+
rubocop-shopify (2.5.0)
|
|
52
|
+
rubocop (~> 1.25)
|
|
52
53
|
ruby-progressbar (1.11.0)
|
|
53
|
-
sorbet-runtime (0.5.
|
|
54
|
+
sorbet-runtime (0.5.9742)
|
|
54
55
|
sqlite3 (1.4.2)
|
|
55
56
|
tzinfo (2.0.4)
|
|
56
57
|
concurrent-ruby (~> 1.0)
|
|
@@ -62,8 +63,9 @@ PLATFORMS
|
|
|
62
63
|
x86_64-linux
|
|
63
64
|
|
|
64
65
|
DEPENDENCIES
|
|
65
|
-
activerecord (>= 7.0.0
|
|
66
|
-
activesupport (>= 7.0.0
|
|
66
|
+
activerecord (>= 7.0.0)
|
|
67
|
+
activesupport (>= 7.0.0)
|
|
68
|
+
benchmark-ips
|
|
67
69
|
byebug
|
|
68
70
|
minitest (~> 5.0)
|
|
69
71
|
msgpack!
|
|
@@ -75,4 +77,4 @@ DEPENDENCIES
|
|
|
75
77
|
sqlite3
|
|
76
78
|
|
|
77
79
|
BUNDLED WITH
|
|
78
|
-
2.2.
|
|
80
|
+
2.2.33
|
data/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Or install it yourself as:
|
|
|
22
22
|
|
|
23
23
|
### `chain`
|
|
24
24
|
|
|
25
|
-
`Paquito::CoderChain`
|
|
25
|
+
`Paquito::CoderChain` combines two or more serializers into one.
|
|
26
26
|
|
|
27
27
|
Example:
|
|
28
28
|
|
|
@@ -34,7 +34,7 @@ compressed_yaml_coder.load(payload) # => { foo: 42 }
|
|
|
34
34
|
|
|
35
35
|
### `ConditionalCompressor`
|
|
36
36
|
|
|
37
|
-
`Paquito::ConditionalCompressor`
|
|
37
|
+
`Paquito::ConditionalCompressor` compresses payloads if they are over a defined size.
|
|
38
38
|
|
|
39
39
|
Example:
|
|
40
40
|
```ruby
|
|
@@ -45,8 +45,8 @@ coder.dump("foo" * 500) # => "\x01<compressed-data....>"
|
|
|
45
45
|
|
|
46
46
|
### `SingleBytePrefixVersion`
|
|
47
47
|
|
|
48
|
-
`Paquito::SingleBytePrefixVersion` prepends a version prefix to the payloads, which
|
|
49
|
-
different serialization methods.
|
|
48
|
+
`Paquito::SingleBytePrefixVersion` prepends a version prefix to the payloads, which allows you to seamlessly transition
|
|
49
|
+
between different serialization methods.
|
|
50
50
|
|
|
51
51
|
The first argument is the current version used for newly generated payloads.
|
|
52
52
|
|
|
@@ -64,9 +64,9 @@ coder.load("\x00---\n:foo: 42") # => { foo: 42 }
|
|
|
64
64
|
|
|
65
65
|
### `CommentPrefixVersion`
|
|
66
66
|
|
|
67
|
-
Similar to the single byte prefix, but meant to be human readable and to allow for migrating
|
|
67
|
+
Similar to the single byte prefix, but meant to be human readable and to allow for migrating unversioned payloads.
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Payloads without a version prefix are assumed to be version `0`.
|
|
70
70
|
|
|
71
71
|
The first argument is the current version used for newly generated payloads.
|
|
72
72
|
|
|
@@ -84,7 +84,7 @@ coder.dump([1]) # => "#☠1☢\n[1]"
|
|
|
84
84
|
|
|
85
85
|
### `allow_nil`
|
|
86
86
|
|
|
87
|
-
In some
|
|
87
|
+
In some situations where you'd rather not serialize `nil`, you can use the `Paquito.allow_nil` shorthand:
|
|
88
88
|
|
|
89
89
|
```ruby
|
|
90
90
|
coder = Paquito.allow_nil(Marshal)
|
|
@@ -95,7 +95,7 @@ coder.load(nil) # => nil
|
|
|
95
95
|
### `TranslateErrors`
|
|
96
96
|
|
|
97
97
|
If you do need to handle serialization or deserialization errors, for instance to fallback to acting like a cache miss,
|
|
98
|
-
`Paquito::TranslateErrors`
|
|
98
|
+
`Paquito::TranslateErrors` translates all underlying exceptions into `Paquito::Error` descendants.
|
|
99
99
|
|
|
100
100
|
Example:
|
|
101
101
|
|
|
@@ -117,9 +117,11 @@ coder.load(coder.dump(%i(foo bar).to_set)) # => #<Set: {:foo, :bar}>
|
|
|
117
117
|
|
|
118
118
|
### `TypedStruct`
|
|
119
119
|
|
|
120
|
-
`Paquito::TypedStruct` is a opt-in Sorbet runtime plugin that allows `T::Struct` classes to be serializable. You need
|
|
120
|
+
`Paquito::TypedStruct` is a opt-in Sorbet runtime plugin that allows `T::Struct` classes to be serializable. You need
|
|
121
|
+
to explicitly include the module in the `T::Struct` classes that you will be serializing.
|
|
121
122
|
|
|
122
123
|
Example
|
|
124
|
+
|
|
123
125
|
```ruby
|
|
124
126
|
class MyStruct < T::Struct
|
|
125
127
|
include Paquito::TypedStruct
|
|
@@ -134,13 +136,24 @@ my_struct.as_pack # => [26450, "foo", 1]
|
|
|
134
136
|
MyStruct.from_pack([26450, "foo", 1]) # => <MyStruct bar=1, foo="foo">
|
|
135
137
|
```
|
|
136
138
|
|
|
137
|
-
##
|
|
139
|
+
## Rails utilities
|
|
140
|
+
|
|
141
|
+
`paquito` doesn't depend on `rails` or any of its components, however it does provide some optional utilities.
|
|
142
|
+
|
|
143
|
+
### `CacheEntryCoder`
|
|
144
|
+
|
|
145
|
+
`Paquito::CacheEntryCoder` turns an `ActiveSupport::Cache::Entry` instance into a simple `Array` instance. This allows
|
|
146
|
+
you to implement custom coders for `ActiveSupport::Cache`.
|
|
138
147
|
|
|
139
|
-
|
|
148
|
+
Example:
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
ActiveSupport::Cache::FileStore.new("tmp/cache", coder: Paquito.chain(Paquito::CacheEntryCoder, JSON))
|
|
152
|
+
```
|
|
140
153
|
|
|
141
154
|
### `SerializedColumn`
|
|
142
155
|
|
|
143
|
-
`Paquito::SerializedColumn` allows to decorate any encoder to behave like Rails's builtin `YAMLColumn`
|
|
156
|
+
`Paquito::SerializedColumn` allows you to decorate any encoder to behave like Rails's builtin `YAMLColumn`
|
|
144
157
|
|
|
145
158
|
Example:
|
|
146
159
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "paquito"
|
|
6
|
+
require "benchmark/ips"
|
|
7
|
+
|
|
8
|
+
BASELINE = Paquito::CodecFactory.build([Symbol], pool: false)
|
|
9
|
+
POOLED = Paquito::CodecFactory.build([Symbol], pool: 1)
|
|
10
|
+
|
|
11
|
+
PAYLOAD = BASELINE.dump(:foo)
|
|
12
|
+
MARSHAL_PAYLOAD = Marshal.dump(:foo)
|
|
13
|
+
|
|
14
|
+
Benchmark.ips do |x|
|
|
15
|
+
x.report("marshal") { Marshal.load(MARSHAL_PAYLOAD) }
|
|
16
|
+
x.report("msgpack") { BASELINE.load(PAYLOAD) }
|
|
17
|
+
x.report("pooled") { POOLED.load(PAYLOAD) }
|
|
18
|
+
x.compare!(order: :baseline)
|
|
19
|
+
end
|
data/lib/paquito/allow_nil.rb
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Paquito
|
|
4
|
+
module CacheEntryCoder
|
|
5
|
+
def self.dump(entry)
|
|
6
|
+
attrs = [entry.value, entry.expires_at, entry.version]
|
|
7
|
+
# drop any trailing nil values to save a couple bytes
|
|
8
|
+
attrs.pop until !attrs.last.nil? || attrs.empty?
|
|
9
|
+
attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.load(payload)
|
|
13
|
+
entry = ::ActiveSupport::Cache::Entry.allocate
|
|
14
|
+
value, expires_in, version = payload
|
|
15
|
+
entry.instance_variable_set(:@value, value)
|
|
16
|
+
entry.instance_variable_set(:@expires_in, expires_in)
|
|
17
|
+
entry.instance_variable_set(:@created_at, 0.0)
|
|
18
|
+
entry.instance_variable_set(:@version, version)
|
|
19
|
+
entry
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -5,15 +5,24 @@ require "paquito/coder_chain"
|
|
|
5
5
|
|
|
6
6
|
module Paquito
|
|
7
7
|
class CodecFactory
|
|
8
|
-
def self.build(types, freeze: false, serializable_type: false)
|
|
9
|
-
factory =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
def self.build(types, freeze: false, serializable_type: false, pool: 1)
|
|
9
|
+
factory = if types.empty? && !serializable_type
|
|
10
|
+
MessagePack::DefaultFactory
|
|
11
|
+
else
|
|
12
|
+
MessagePack::Factory.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
15
|
Types.register(factory, types) unless types.empty?
|
|
16
16
|
Types.register_serializable_type(factory) if serializable_type
|
|
17
|
+
|
|
18
|
+
if pool && pool > 0 && factory.respond_to?(:pool)
|
|
19
|
+
if serializable_type || types.any? { |t| Types.recursive?(t) }
|
|
20
|
+
pool *= 2
|
|
21
|
+
end
|
|
22
|
+
factory = factory.freeze.pool(pool, freeze: freeze)
|
|
23
|
+
freeze = false
|
|
24
|
+
end
|
|
25
|
+
|
|
17
26
|
MessagePackCodec.new(factory, freeze: freeze)
|
|
18
27
|
end
|
|
19
28
|
|
|
@@ -32,7 +41,11 @@ module Paquito
|
|
|
32
41
|
end
|
|
33
42
|
|
|
34
43
|
def load(payload)
|
|
35
|
-
|
|
44
|
+
if @freeze
|
|
45
|
+
@factory.load(payload, freeze: @freeze)
|
|
46
|
+
else
|
|
47
|
+
@factory.load(payload)
|
|
48
|
+
end
|
|
36
49
|
rescue MessagePack::UnpackError => error
|
|
37
50
|
raise UnpackError, error.message
|
|
38
51
|
rescue IOError => error
|
data/lib/paquito/safe_yaml.rb
CHANGED
|
@@ -43,31 +43,37 @@ module Paquito
|
|
|
43
43
|
|
|
44
44
|
class RestrictedYAMLTree < Psych::Visitors::YAMLTree
|
|
45
45
|
class DispatchCache
|
|
46
|
-
def initialize(visitor, cache
|
|
46
|
+
def initialize(visitor, cache)
|
|
47
47
|
@visitor = visitor
|
|
48
48
|
@cache = cache
|
|
49
|
-
@permitted_classes = permitted_classes
|
|
50
|
-
|
|
51
|
-
@permitted_cache = Hash.new do |h, klass|
|
|
52
|
-
unless @permitted_classes.include?(klass.name)
|
|
53
|
-
raise UnsupportedType, "Tried to dump unspecified class: #{klass.name.inspect}"
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
h[klass] = true
|
|
57
|
-
end.compare_by_identity
|
|
58
49
|
end
|
|
59
50
|
|
|
60
51
|
def [](klass)
|
|
61
|
-
if @
|
|
62
|
-
@cache[klass]
|
|
63
|
-
end
|
|
52
|
+
@cache[klass] if @visitor.permitted_class?(klass)
|
|
64
53
|
end
|
|
65
54
|
end
|
|
66
55
|
|
|
67
56
|
def initialize(...)
|
|
68
57
|
super
|
|
69
58
|
@permitted_classes = Set.new(@options[:permitted_classes])
|
|
70
|
-
@dispatch_cache = DispatchCache.new(self, @dispatch_cache
|
|
59
|
+
@dispatch_cache = DispatchCache.new(self, @dispatch_cache)
|
|
60
|
+
@permitted_cache = Hash.new do |h, klass|
|
|
61
|
+
unless @permitted_classes.include?(klass.name)
|
|
62
|
+
raise UnsupportedType, "Tried to dump unspecified class: #{klass.name.inspect}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
h[klass] = true
|
|
66
|
+
end.compare_by_identity
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def dump_coder(target)
|
|
70
|
+
return unless permitted_class?(target.class)
|
|
71
|
+
|
|
72
|
+
super
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def permitted_class?(klass)
|
|
76
|
+
@permitted_cache[klass]
|
|
71
77
|
end
|
|
72
78
|
end
|
|
73
79
|
end
|
data/lib/paquito/typed_struct.rb
CHANGED
data/lib/paquito/types.rb
CHANGED
|
@@ -37,10 +37,12 @@ module Paquito
|
|
|
37
37
|
def register(klass, packer: nil, unpacker:)
|
|
38
38
|
if packer
|
|
39
39
|
raise ArgumentError, "packer for #{klass} already defined" if packers.key?(klass)
|
|
40
|
+
|
|
40
41
|
packers[klass] = packer
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
raise ArgumentError, "unpacker for #{klass} already defined" if unpackers.key?(klass)
|
|
45
|
+
|
|
44
46
|
unpackers[klass] = unpacker
|
|
45
47
|
|
|
46
48
|
self
|
|
@@ -72,13 +74,13 @@ module Paquito
|
|
|
72
74
|
# New types can be added as long as they have unique #code.
|
|
73
75
|
TYPES = {
|
|
74
76
|
"Symbol" => {
|
|
75
|
-
code:
|
|
76
|
-
packer: :to_s,
|
|
77
|
+
code: 0,
|
|
78
|
+
packer: Symbol.method_defined?(:name) ? :name : :to_s,
|
|
77
79
|
unpacker: :to_sym,
|
|
78
80
|
optimized_symbols_parsing: true,
|
|
79
81
|
}.freeze,
|
|
80
82
|
"Time" => {
|
|
81
|
-
code:
|
|
83
|
+
code: 1,
|
|
82
84
|
packer: ->(value) do
|
|
83
85
|
rational = value.utc.to_r
|
|
84
86
|
[rational.numerator, rational.denominator].pack(TIME_FORMAT)
|
|
@@ -89,7 +91,7 @@ module Paquito
|
|
|
89
91
|
end,
|
|
90
92
|
}.freeze,
|
|
91
93
|
"DateTime" => {
|
|
92
|
-
code:
|
|
94
|
+
code: 2,
|
|
93
95
|
packer: ->(value) do
|
|
94
96
|
sec = value.sec + value.sec_fraction
|
|
95
97
|
offset = value.offset
|
|
@@ -129,7 +131,7 @@ module Paquito
|
|
|
129
131
|
end,
|
|
130
132
|
}.freeze,
|
|
131
133
|
"Date" => {
|
|
132
|
-
code:
|
|
134
|
+
code: 3,
|
|
133
135
|
packer: ->(value) do
|
|
134
136
|
[value.year, value.month, value.day].pack(DATE_FORMAT)
|
|
135
137
|
end,
|
|
@@ -139,28 +141,29 @@ module Paquito
|
|
|
139
141
|
end,
|
|
140
142
|
}.freeze,
|
|
141
143
|
"BigDecimal" => {
|
|
142
|
-
code:
|
|
144
|
+
code: 4,
|
|
143
145
|
packer: :_dump,
|
|
144
146
|
unpacker: BigDecimal.method(:_load),
|
|
145
147
|
}.freeze,
|
|
146
148
|
# Range => { code: 0x05 }, do not recycle that code
|
|
147
149
|
"ActiveRecord::Base" => {
|
|
148
|
-
code:
|
|
150
|
+
code: 6,
|
|
149
151
|
packer: ->(value) { ActiveRecordPacker.dump(value) },
|
|
150
152
|
unpacker: ->(value) { ActiveRecordPacker.load(value) },
|
|
151
153
|
}.freeze,
|
|
152
154
|
"ActiveSupport::HashWithIndifferentAccess" => {
|
|
153
|
-
code:
|
|
155
|
+
code: 7,
|
|
154
156
|
packer: ->(factory, value) do
|
|
155
157
|
unless value.instance_of?(ActiveSupport::HashWithIndifferentAccess)
|
|
156
158
|
raise PackError.new("cannot pack HashWithIndifferentClass subclass", value)
|
|
157
159
|
end
|
|
160
|
+
|
|
158
161
|
factory.dump(value.to_h)
|
|
159
162
|
end,
|
|
160
163
|
unpacker: ->(factory, value) { HashWithIndifferentAccess.new(factory.load(value)) },
|
|
161
164
|
},
|
|
162
165
|
"ActiveSupport::TimeWithZone" => {
|
|
163
|
-
code:
|
|
166
|
+
code: 8,
|
|
164
167
|
packer: ->(value) do
|
|
165
168
|
[
|
|
166
169
|
value.utc.to_i,
|
|
@@ -176,12 +179,27 @@ module Paquito
|
|
|
176
179
|
end,
|
|
177
180
|
},
|
|
178
181
|
"Set" => {
|
|
179
|
-
code:
|
|
182
|
+
code: 9,
|
|
180
183
|
packer: ->(factory, value) { factory.dump(value.to_a) },
|
|
181
184
|
unpacker: ->(factory, value) { factory.load(value).to_set },
|
|
182
185
|
},
|
|
183
|
-
#
|
|
184
|
-
|
|
186
|
+
# Integer => { code: 10 }, reserved for oversized Integer
|
|
187
|
+
# Object => { code: 127 }, reserved for serializable Object type
|
|
188
|
+
}
|
|
189
|
+
begin
|
|
190
|
+
require "msgpack/bigint"
|
|
191
|
+
|
|
192
|
+
TYPES["Integer"] = {
|
|
193
|
+
code: 10,
|
|
194
|
+
packer: MessagePack::Bigint.method(:to_msgpack_ext),
|
|
195
|
+
unpacker: MessagePack::Bigint.method(:from_msgpack_ext),
|
|
196
|
+
oversized_integer_extension: true,
|
|
197
|
+
}
|
|
198
|
+
rescue LoadError
|
|
199
|
+
# expected on older msgpack
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
TYPES.freeze
|
|
185
203
|
|
|
186
204
|
class << self
|
|
187
205
|
def register(factory, types)
|
|
@@ -194,15 +212,23 @@ module Paquito
|
|
|
194
212
|
end
|
|
195
213
|
|
|
196
214
|
type_attributes = TYPES.fetch(name)
|
|
215
|
+
type_attributes = type_attributes.merge(
|
|
216
|
+
packer: curry_callback(type_attributes.fetch(:packer), factory),
|
|
217
|
+
unpacker: curry_callback(type_attributes.fetch(:unpacker), factory),
|
|
218
|
+
)
|
|
197
219
|
factory.register_type(
|
|
198
220
|
type_attributes.fetch(:code),
|
|
199
221
|
type,
|
|
200
|
-
|
|
201
|
-
unpacker: curry_callback(type_attributes.fetch(:unpacker), factory),
|
|
222
|
+
type_attributes
|
|
202
223
|
)
|
|
203
224
|
end
|
|
204
225
|
end
|
|
205
226
|
|
|
227
|
+
def recursive?(type)
|
|
228
|
+
type_attributes = TYPES.fetch(type.name)
|
|
229
|
+
recursive_callback?(type_attributes[:packer]) || recursive_callback?(type_attributes[:unpacker])
|
|
230
|
+
end
|
|
231
|
+
|
|
206
232
|
def register_serializable_type(factory)
|
|
207
233
|
factory.register_type(
|
|
208
234
|
0x7f,
|
|
@@ -233,9 +259,14 @@ module Paquito
|
|
|
233
259
|
|
|
234
260
|
private
|
|
235
261
|
|
|
262
|
+
def recursive_callback?(callback)
|
|
263
|
+
callback.respond_to?(:arity) && callback.arity != 1
|
|
264
|
+
end
|
|
265
|
+
|
|
236
266
|
def curry_callback(callback, factory)
|
|
237
267
|
return callback.to_proc if callback.is_a?(Symbol)
|
|
238
268
|
return callback if callback.arity == 1
|
|
269
|
+
|
|
239
270
|
callback.curry.call(factory)
|
|
240
271
|
end
|
|
241
272
|
end
|
data/lib/paquito/version.rb
CHANGED
data/lib/paquito.rb
CHANGED
|
@@ -14,6 +14,7 @@ require "paquito/allow_nil"
|
|
|
14
14
|
require "paquito/translate_errors"
|
|
15
15
|
require "paquito/safe_yaml"
|
|
16
16
|
require "paquito/conditional_compressor"
|
|
17
|
+
require "paquito/cache_entry_coder"
|
|
17
18
|
require "paquito/single_byte_prefix_version"
|
|
18
19
|
require "paquito/comment_prefix_version"
|
|
19
20
|
require "paquito/types"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: paquito
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jean Boussier
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-03-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: msgpack
|
|
@@ -39,12 +39,14 @@ files:
|
|
|
39
39
|
- LICENSE.txt
|
|
40
40
|
- README.md
|
|
41
41
|
- Rakefile
|
|
42
|
+
- benchmark/msgpack-pooling.rb
|
|
42
43
|
- bin/console
|
|
43
44
|
- bin/setup
|
|
44
45
|
- dev.yml
|
|
45
46
|
- lib/paquito.rb
|
|
46
47
|
- lib/paquito/active_record_coder.rb
|
|
47
48
|
- lib/paquito/allow_nil.rb
|
|
49
|
+
- lib/paquito/cache_entry_coder.rb
|
|
48
50
|
- lib/paquito/codec_factory.rb
|
|
49
51
|
- lib/paquito/coder_chain.rb
|
|
50
52
|
- lib/paquito/comment_prefix_version.rb
|