msgpack 1.4.5 → 1.5.2
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.yaml +5 -5
- data/ChangeLog +14 -0
- data/README.md +22 -0
- data/doclib/msgpack/factory.rb +45 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
- data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +24 -31
- data/ext/java/org/msgpack/jruby/Factory.java +40 -5
- data/ext/java/org/msgpack/jruby/Packer.java +21 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
- data/ext/msgpack/buffer_class.c +12 -3
- data/ext/msgpack/factory_class.c +62 -5
- data/ext/msgpack/packer.c +42 -5
- data/ext/msgpack/packer.h +24 -0
- data/ext/msgpack/packer_class.c +22 -19
- data/ext/msgpack/packer_ext_registry.c +13 -4
- data/ext/msgpack/packer_ext_registry.h +10 -5
- data/ext/msgpack/unpacker.c +59 -19
- data/ext/msgpack/unpacker_class.c +14 -5
- data/ext/msgpack/unpacker_ext_registry.c +3 -2
- data/ext/msgpack/unpacker_ext_registry.h +5 -2
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +220 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/timestamp_spec.rb +2 -2
- metadata +4 -2
data/spec/factory_spec.rb
CHANGED
@@ -283,6 +283,174 @@ describe MessagePack::Factory do
|
|
283
283
|
it { is_expected.to eq "unpacked module" }
|
284
284
|
end
|
285
285
|
end
|
286
|
+
|
287
|
+
describe "registering an ext type for Integer" do
|
288
|
+
let(:factory) { described_class.new }
|
289
|
+
let(:bigint) { 10**150 }
|
290
|
+
|
291
|
+
it 'does not work by default without passing `oversized_integer_extension: true`' do
|
292
|
+
factory.register_type(0x01, Integer, packer: :to_s, unpacker: method(:Integer))
|
293
|
+
|
294
|
+
expect do
|
295
|
+
factory.dump(bigint)
|
296
|
+
end.to raise_error RangeError
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'raises ArgumentError if the type is not Integer' do
|
300
|
+
expect do
|
301
|
+
factory.register_type(0x01, MyType, packer: :to_s, unpacker: method(:Integer), oversized_integer_extension: true)
|
302
|
+
end.to raise_error(ArgumentError)
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'invokes the packer if registered with `oversized_integer_extension: true`' do
|
306
|
+
factory.register_type(0x01, Integer, packer: :to_s, unpacker: method(:Integer), oversized_integer_extension: true)
|
307
|
+
|
308
|
+
expect(factory.load(factory.dump(bigint))).to be == bigint
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'does not use the oversized_integer_extension packer for integers fitting in native types' do
|
312
|
+
factory.register_type(
|
313
|
+
0x01,
|
314
|
+
Integer,
|
315
|
+
packer: ->(int) { raise NotImplementedError },
|
316
|
+
unpacker: ->(payload) { raise NotImplementedError },
|
317
|
+
oversized_integer_extension: true
|
318
|
+
)
|
319
|
+
|
320
|
+
expect(factory.dump(42)).to eq(MessagePack.dump(42))
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "registering ext type with recursive serialization" do
|
325
|
+
before do
|
326
|
+
stub_const("Point", Struct.new(:x, :y, :z))
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'can receive the packer as argument (proc)' do
|
330
|
+
factory = MessagePack::Factory.new
|
331
|
+
factory.register_type(0x00, Symbol)
|
332
|
+
factory.register_type(
|
333
|
+
0x01,
|
334
|
+
Point,
|
335
|
+
packer: ->(point, packer) do
|
336
|
+
packer.write(point.to_h)
|
337
|
+
nil
|
338
|
+
end,
|
339
|
+
unpacker: ->(unpacker) do
|
340
|
+
attrs = unpacker.read
|
341
|
+
Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
|
342
|
+
end,
|
343
|
+
recursive: true,
|
344
|
+
)
|
345
|
+
|
346
|
+
point = Point.new(1, 2, 3)
|
347
|
+
payload = factory.dump(point)
|
348
|
+
expect(factory.load(payload)).to be == point
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'can receive the packer as argument (Method)' do
|
352
|
+
mod = Module.new
|
353
|
+
mod.define_singleton_method(:packer) do |point, packer|
|
354
|
+
packer.write(point.to_h)
|
355
|
+
nil
|
356
|
+
end
|
357
|
+
|
358
|
+
mod.define_singleton_method(:unpacker) do |unpacker|
|
359
|
+
attrs = unpacker.read
|
360
|
+
Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
|
361
|
+
end
|
362
|
+
|
363
|
+
factory = MessagePack::Factory.new
|
364
|
+
factory.register_type(0x00, Symbol)
|
365
|
+
factory.register_type(
|
366
|
+
0x01,
|
367
|
+
Point,
|
368
|
+
packer: mod.method(:packer),
|
369
|
+
unpacker: mod.method(:unpacker),
|
370
|
+
recursive: true,
|
371
|
+
)
|
372
|
+
|
373
|
+
point = Point.new(1, 2, 3)
|
374
|
+
payload = factory.dump(point)
|
375
|
+
expect(factory.load(payload)).to be == point
|
376
|
+
end
|
377
|
+
|
378
|
+
it 'respect message pack format' do
|
379
|
+
factory = MessagePack::Factory.new
|
380
|
+
factory.register_type(0x00, Symbol)
|
381
|
+
factory.register_type(
|
382
|
+
0x01,
|
383
|
+
Point,
|
384
|
+
packer: ->(point, packer) do
|
385
|
+
packer.write(point.to_a)
|
386
|
+
nil
|
387
|
+
end,
|
388
|
+
unpacker: ->(unpacker) do
|
389
|
+
attrs = unpacker.read
|
390
|
+
Point.new(*attrs)
|
391
|
+
end,
|
392
|
+
recursive: true,
|
393
|
+
)
|
394
|
+
|
395
|
+
point = Point.new(1, 2, 3)
|
396
|
+
expect(factory.dump(point)).to be == "\xD6\x01".b + MessagePack.dump([1, 2, 3])
|
397
|
+
end
|
398
|
+
|
399
|
+
it 'sets the correct length' do
|
400
|
+
factory = MessagePack::Factory.new
|
401
|
+
factory.register_type(0x00, Symbol)
|
402
|
+
factory.register_type(
|
403
|
+
0x01,
|
404
|
+
Point,
|
405
|
+
packer: ->(point, packer) do
|
406
|
+
packer.write(point.to_h)
|
407
|
+
nil
|
408
|
+
end,
|
409
|
+
unpacker: ->(unpacker) do
|
410
|
+
attrs = unpacker.read
|
411
|
+
Point.new(attrs.fetch(:x), attrs.fetch(:y), attrs.fetch(:z))
|
412
|
+
end,
|
413
|
+
recursive: true,
|
414
|
+
)
|
415
|
+
|
416
|
+
point = Point.new(1, 2, 3)
|
417
|
+
payload = factory.dump([1, point, 3])
|
418
|
+
|
419
|
+
obj = MessagePack::Factory.new.load(payload, allow_unknown_ext: true)
|
420
|
+
expect(obj).to be == [
|
421
|
+
1,
|
422
|
+
MessagePack::ExtensionValue.new(1, factory.dump(x: 1, y: 2, z: 3)),
|
423
|
+
3,
|
424
|
+
]
|
425
|
+
|
426
|
+
expect(factory.load(payload)).to be == [
|
427
|
+
1,
|
428
|
+
Point.new(1, 2, 3),
|
429
|
+
3,
|
430
|
+
]
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'can be nested' do
|
434
|
+
factory = MessagePack::Factory.new
|
435
|
+
factory.register_type(
|
436
|
+
0x02,
|
437
|
+
Set,
|
438
|
+
packer: ->(set, packer) do
|
439
|
+
packer.write(set.to_a)
|
440
|
+
nil
|
441
|
+
end,
|
442
|
+
unpacker: ->(unpacker) do
|
443
|
+
unpacker.read.to_set
|
444
|
+
end,
|
445
|
+
recursive: true,
|
446
|
+
)
|
447
|
+
|
448
|
+
expected = Set[1, Set[2, Set[3]]]
|
449
|
+
payload = factory.dump(expected)
|
450
|
+
expect(payload).to be == "\xC7\v\x02\x92\x01\xC7\x06\x02\x92\x02\xD5\x02\x91\x03".b
|
451
|
+
expect(factory.load(factory.dump(expected))).to be == expected
|
452
|
+
end
|
453
|
+
end
|
286
454
|
end
|
287
455
|
|
288
456
|
describe 'the special treatment of symbols with ext type' do
|
@@ -437,4 +605,56 @@ describe MessagePack::Factory do
|
|
437
605
|
expect(MessagePack.unpack(MessagePack.pack(dm2))).to eq(dm2)
|
438
606
|
end
|
439
607
|
end
|
608
|
+
|
609
|
+
describe '#pool' do
|
610
|
+
let(:factory) { described_class.new }
|
611
|
+
|
612
|
+
it 'responds to serializers interface' do
|
613
|
+
pool = factory.pool(1)
|
614
|
+
expect(pool.load(pool.dump(42))).to be == 42
|
615
|
+
end
|
616
|
+
|
617
|
+
it 'types can be registered before the pool is created' do
|
618
|
+
factory.register_type(0x00, Symbol)
|
619
|
+
pool = factory.pool(1)
|
620
|
+
expect(pool.load(pool.dump(:foo))).to be == :foo
|
621
|
+
end
|
622
|
+
|
623
|
+
it 'types cannot be registered after the pool is created' do
|
624
|
+
pool = factory.pool(1)
|
625
|
+
factory.register_type(0x20, ::MyType)
|
626
|
+
|
627
|
+
expect do
|
628
|
+
pool.dump(MyType.new(1, 2))
|
629
|
+
end.to raise_error NoMethodError
|
630
|
+
|
631
|
+
payload = factory.dump(MyType.new(1, 2))
|
632
|
+
expect do
|
633
|
+
pool.load(payload)
|
634
|
+
end.to raise_error MessagePack::UnknownExtTypeError
|
635
|
+
end
|
636
|
+
|
637
|
+
it 'support symbolize_keys: true' do
|
638
|
+
pool = factory.pool(1, symbolize_keys: true)
|
639
|
+
expect(pool.load(pool.dump('foo' => 1))).to be == { foo: 1 }
|
640
|
+
end
|
641
|
+
|
642
|
+
it 'support freeze: true' do
|
643
|
+
pool = factory.pool(1, freeze: true)
|
644
|
+
expect(pool.load(pool.dump('foo'))).to be_frozen
|
645
|
+
end
|
646
|
+
|
647
|
+
it 'is thread safe' do
|
648
|
+
pool = factory.pool(1)
|
649
|
+
|
650
|
+
threads = 10.times.map do
|
651
|
+
Thread.new do
|
652
|
+
1_000.times do |i|
|
653
|
+
expect(pool.load(pool.dump(i))).to be == i
|
654
|
+
end
|
655
|
+
end
|
656
|
+
end
|
657
|
+
threads.each(&:join)
|
658
|
+
end
|
659
|
+
end
|
440
660
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "set"
|
1
2
|
|
2
3
|
if ENV['SIMPLE_COV']
|
3
4
|
require 'simplecov'
|
@@ -14,6 +15,7 @@ if ENV['GC_STRESS']
|
|
14
15
|
end
|
15
16
|
|
16
17
|
require 'msgpack'
|
18
|
+
require "msgpack/bigint"
|
17
19
|
|
18
20
|
if GC.respond_to?(:verify_compaction_references)
|
19
21
|
# This method was added in Ruby 3.0.0. Calling it this way asks the GC to
|
@@ -27,6 +29,8 @@ end
|
|
27
29
|
|
28
30
|
IS_JRUBY = RUBY_ENGINE == 'jruby'
|
29
31
|
|
32
|
+
IS_TRUFFLERUBY = RUBY_ENGINE == 'truffleruby'
|
33
|
+
|
30
34
|
# checking if Hash#[]= (rb_hash_aset) dedupes string keys
|
31
35
|
def automatic_string_keys_deduplication?
|
32
36
|
h = {}
|
data/spec/timestamp_spec.rb
CHANGED
@@ -87,14 +87,14 @@ describe MessagePack::Timestamp do
|
|
87
87
|
|
88
88
|
let(:time96_min) { Time.at(-2**63).utc }
|
89
89
|
it 'is serialized into timestamp96' do
|
90
|
-
skip if IS_JRUBY # JRuby
|
90
|
+
skip if IS_JRUBY || IS_TRUFFLERUBY # JRuby and TruffleRuby both use underlying Java time classes that do not support |year| >= 1 billion
|
91
91
|
expect(factory.pack(time96_min).size).to be 15
|
92
92
|
expect(factory.unpack(factory.pack(time96_min)).utc).to eq(time96_min)
|
93
93
|
end
|
94
94
|
|
95
95
|
let(:time96_max) { Time.at(2**63 - 1).utc }
|
96
96
|
it 'is serialized into timestamp96' do
|
97
|
-
skip if IS_JRUBY # JRuby
|
97
|
+
skip if IS_JRUBY || IS_TRUFFLERUBY # JRuby and TruffleRuby both use underlying Java time classes that do not support |year| >= 1 billion
|
98
98
|
expect(factory.pack(time96_max).size).to be 15
|
99
99
|
expect(factory.unpack(factory.pack(time96_max)).utc).to eq(time96_max)
|
100
100
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msgpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-05-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -176,6 +176,7 @@ files:
|
|
176
176
|
- ext/msgpack/unpacker_ext_registry.c
|
177
177
|
- ext/msgpack/unpacker_ext_registry.h
|
178
178
|
- lib/msgpack.rb
|
179
|
+
- lib/msgpack/bigint.rb
|
179
180
|
- lib/msgpack/core_ext.rb
|
180
181
|
- lib/msgpack/factory.rb
|
181
182
|
- lib/msgpack/packer.rb
|
@@ -186,6 +187,7 @@ files:
|
|
186
187
|
- lib/msgpack/version.rb
|
187
188
|
- msgpack.gemspec
|
188
189
|
- msgpack.org.md
|
190
|
+
- spec/bigint_spec.rb
|
189
191
|
- spec/cases.json
|
190
192
|
- spec/cases.msg
|
191
193
|
- spec/cases_compact.msg
|