msgpack 1.5.6 → 1.8.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +50 -0
  3. data/README.md +48 -12
  4. data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
  5. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +11 -20
  6. data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
  7. data/ext/java/org/msgpack/jruby/Factory.java +11 -50
  8. data/ext/java/org/msgpack/jruby/Packer.java +9 -24
  9. data/ext/java/org/msgpack/jruby/Unpacker.java +15 -32
  10. data/ext/msgpack/buffer.c +69 -56
  11. data/ext/msgpack/buffer.h +138 -44
  12. data/ext/msgpack/buffer_class.c +132 -31
  13. data/ext/msgpack/buffer_class.h +1 -0
  14. data/ext/msgpack/extconf.rb +20 -30
  15. data/ext/msgpack/factory_class.c +75 -86
  16. data/ext/msgpack/packer.c +13 -16
  17. data/ext/msgpack/packer.h +24 -21
  18. data/ext/msgpack/packer_class.c +72 -98
  19. data/ext/msgpack/packer_class.h +11 -0
  20. data/ext/msgpack/packer_ext_registry.c +31 -28
  21. data/ext/msgpack/packer_ext_registry.h +10 -14
  22. data/ext/msgpack/rbinit.c +1 -1
  23. data/ext/msgpack/rmem.c +3 -4
  24. data/ext/msgpack/sysdep.h +5 -2
  25. data/ext/msgpack/unpacker.c +201 -113
  26. data/ext/msgpack/unpacker.h +22 -15
  27. data/ext/msgpack/unpacker_class.c +87 -92
  28. data/ext/msgpack/unpacker_class.h +11 -0
  29. data/ext/msgpack/unpacker_ext_registry.c +4 -16
  30. data/ext/msgpack/unpacker_ext_registry.h +3 -7
  31. data/lib/msgpack/buffer.rb +9 -0
  32. data/lib/msgpack/factory.rb +90 -63
  33. data/lib/msgpack/packer.rb +10 -1
  34. data/lib/msgpack/unpacker.rb +14 -1
  35. data/lib/msgpack/version.rb +1 -1
  36. data/lib/msgpack.rb +1 -0
  37. data/msgpack.gemspec +8 -3
  38. metadata +21 -51
  39. data/.github/workflows/ci.yaml +0 -57
  40. data/.gitignore +0 -23
  41. data/.rubocop.yml +0 -36
  42. data/Gemfile +0 -9
  43. data/Rakefile +0 -70
  44. data/appveyor.yml +0 -18
  45. data/bench/bench.rb +0 -78
  46. data/doclib/msgpack/buffer.rb +0 -193
  47. data/doclib/msgpack/core_ext.rb +0 -101
  48. data/doclib/msgpack/error.rb +0 -19
  49. data/doclib/msgpack/extension_value.rb +0 -9
  50. data/doclib/msgpack/factory.rb +0 -145
  51. data/doclib/msgpack/packer.rb +0 -209
  52. data/doclib/msgpack/time.rb +0 -22
  53. data/doclib/msgpack/timestamp.rb +0 -44
  54. data/doclib/msgpack/unpacker.rb +0 -183
  55. data/doclib/msgpack.rb +0 -87
  56. data/msgpack.org.md +0 -46
  57. data/spec/bigint_spec.rb +0 -26
  58. data/spec/cases.json +0 -1
  59. data/spec/cases.msg +0 -0
  60. data/spec/cases_compact.msg +0 -0
  61. data/spec/cases_spec.rb +0 -39
  62. data/spec/cruby/buffer_io_spec.rb +0 -255
  63. data/spec/cruby/buffer_packer.rb +0 -29
  64. data/spec/cruby/buffer_spec.rb +0 -575
  65. data/spec/cruby/buffer_unpacker.rb +0 -19
  66. data/spec/cruby/unpacker_spec.rb +0 -70
  67. data/spec/ext_value_spec.rb +0 -99
  68. data/spec/exttypes.rb +0 -51
  69. data/spec/factory_spec.rb +0 -688
  70. data/spec/format_spec.rb +0 -301
  71. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  72. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  73. data/spec/jruby/unpacker_spec.rb +0 -186
  74. data/spec/msgpack_spec.rb +0 -214
  75. data/spec/pack_spec.rb +0 -61
  76. data/spec/packer_spec.rb +0 -575
  77. data/spec/random_compat.rb +0 -24
  78. data/spec/spec_helper.rb +0 -71
  79. data/spec/timestamp_spec.rb +0 -159
  80. data/spec/unpack_spec.rb +0 -57
  81. data/spec/unpacker_spec.rb +0 -859
data/spec/factory_spec.rb DELETED
@@ -1,688 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe MessagePack::Factory do
4
- subject do
5
- described_class.new
6
- end
7
-
8
- describe '#packer' do
9
- it 'creates a Packer instance' do
10
- subject.packer.should be_kind_of(MessagePack::Packer)
11
- end
12
-
13
- it 'creates new instance' do
14
- subject.packer.object_id.should_not == subject.packer.object_id
15
- end
16
- end
17
-
18
- describe '#unpacker' do
19
- it 'creates a Unpacker instance' do
20
- subject.unpacker.should be_kind_of(MessagePack::Unpacker)
21
- end
22
-
23
- it 'creates new instance' do
24
- subject.unpacker.object_id.should_not == subject.unpacker.object_id
25
- end
26
-
27
- it 'creates unpacker with symbolize_keys option' do
28
- unpacker = subject.unpacker(symbolize_keys: true)
29
- unpacker.feed(MessagePack.pack({'k'=>'v'}))
30
- unpacker.read.should == {:k => 'v'}
31
- end
32
-
33
- it 'creates unpacker with allow_unknown_ext option' do
34
- unpacker = subject.unpacker(allow_unknown_ext: true)
35
- unpacker.feed(MessagePack::ExtensionValue.new(1, 'a').to_msgpack)
36
- unpacker.read.should == MessagePack::ExtensionValue.new(1, 'a')
37
- end
38
-
39
- it 'creates unpacker without allow_unknown_ext option' do
40
- unpacker = subject.unpacker
41
- unpacker.feed(MessagePack::ExtensionValue.new(1, 'a').to_msgpack)
42
- expect{ unpacker.read }.to raise_error(MessagePack::UnknownExtTypeError)
43
- end
44
-
45
- it 'does not share the extension registry with unpackers' do
46
- subject.register_type(0x00, Symbol)
47
- expect do
48
- unpacker = subject.unpacker
49
- expect do
50
- unpacker.register_type(0x01) {}
51
- end.to change { unpacker.registered_types }
52
-
53
- second_unpacker = subject.unpacker
54
- expect do
55
- second_unpacker.register_type(0x01) {}
56
- end.to_not change { unpacker.registered_types }
57
- end.to_not change { subject.registered_types }
58
- end
59
- end
60
-
61
- describe '#dump and #load' do
62
- it 'can be used like a standard coder' do
63
- subject.register_type(0x00, Symbol)
64
- expect(subject.load(subject.dump(:symbol))).to be == :symbol
65
- end
66
-
67
- it 'is alias as pack and unpack' do
68
- subject.register_type(0x00, Symbol)
69
- expect(subject.unpack(subject.pack(:symbol))).to be == :symbol
70
- end
71
-
72
- it 'accept options' do
73
- hash = subject.unpack(MessagePack.pack('k' => 'v'), symbolize_keys: true)
74
- expect(hash).to be == { k: 'v' }
75
- end
76
- end
77
-
78
- describe '#freeze' do
79
- it 'can freeze factory instance to deny new registrations anymore' do
80
- subject.register_type(0x00, Symbol)
81
- subject.freeze
82
- expect(subject.frozen?).to be_truthy
83
- expect{ subject.register_type(0x01, Array) }.to raise_error(RuntimeError, "can't modify frozen Factory")
84
- end
85
- end
86
-
87
- class MyType
88
- def initialize(a, b)
89
- @a = a
90
- @b = b
91
- end
92
-
93
- attr_reader :a, :b
94
-
95
- def to_msgpack_ext
96
- [a, b].pack('CC')
97
- end
98
-
99
- def self.from_msgpack_ext(data)
100
- new(*data.unpack('CC'))
101
- end
102
-
103
- def to_msgpack_ext_only_a
104
- [a, 0].pack('CC')
105
- end
106
-
107
- def self.from_msgpack_ext_only_b(data)
108
- a, b = *data.unpack('CC')
109
- new(0, b)
110
- end
111
- end
112
-
113
- class MyType2 < MyType
114
- end
115
-
116
- describe '#registered_types' do
117
- it 'returns Array' do
118
- expect(subject.registered_types).to be_instance_of(Array)
119
- end
120
-
121
- it 'returns Array of Hash contains :type, :class, :packer, :unpacker' do
122
- subject.register_type(0x20, ::MyType)
123
- subject.register_type(0x21, ::MyType2)
124
-
125
- list = subject.registered_types
126
-
127
- expect(list.size).to eq(2)
128
- expect(list[0]).to be_instance_of(Hash)
129
- expect(list[1]).to be_instance_of(Hash)
130
- expect(list[0].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
131
- expect(list[1].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
132
-
133
- expect(list[0][:type]).to eq(0x20)
134
- expect(list[0][:class]).to eq(::MyType)
135
- expect(list[0][:packer]).to eq(:to_msgpack_ext)
136
- expect(list[0][:unpacker]).to eq(:from_msgpack_ext)
137
-
138
- expect(list[1][:type]).to eq(0x21)
139
- expect(list[1][:class]).to eq(::MyType2)
140
- expect(list[1][:packer]).to eq(:to_msgpack_ext)
141
- expect(list[1][:unpacker]).to eq(:from_msgpack_ext)
142
- end
143
-
144
- it 'returns Array of Hash which has nil for unregistered feature' do
145
- subject.register_type(0x21, ::MyType2, unpacker: :from_msgpack_ext)
146
- subject.register_type(0x20, ::MyType, packer: :to_msgpack_ext)
147
-
148
- list = subject.registered_types
149
-
150
- expect(list.size).to eq(2)
151
- expect(list[0]).to be_instance_of(Hash)
152
- expect(list[1]).to be_instance_of(Hash)
153
- expect(list[0].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
154
- expect(list[1].keys.sort).to eq([:type, :class, :packer, :unpacker].sort)
155
-
156
- expect(list[0][:type]).to eq(0x20)
157
- expect(list[0][:class]).to eq(::MyType)
158
- expect(list[0][:packer]).to eq(:to_msgpack_ext)
159
- expect(list[0][:unpacker]).to be_nil
160
-
161
- expect(list[1][:type]).to eq(0x21)
162
- expect(list[1][:class]).to eq(::MyType2)
163
- expect(list[1][:packer]).to be_nil
164
- expect(list[1][:unpacker]).to eq(:from_msgpack_ext)
165
- end
166
- end
167
-
168
- describe '#type_registered?' do
169
- it 'receive Class or Integer, and return bool' do
170
- expect(subject.type_registered?(0x00)).to be_falsy
171
- expect(subject.type_registered?(0x01)).to be_falsy
172
- expect(subject.type_registered?(::MyType)).to be_falsy
173
- end
174
-
175
- it 'has option to specify what types are registered for' do
176
- expect(subject.type_registered?(0x00, :both)).to be_falsy
177
- expect(subject.type_registered?(0x00, :packer)).to be_falsy
178
- expect(subject.type_registered?(0x00, :unpacker)).to be_falsy
179
- expect{ subject.type_registered?(0x00, :something) }.to raise_error(ArgumentError)
180
- end
181
-
182
- it 'returns true if specified type or class is already registered' do
183
- subject.register_type(0x20, ::MyType)
184
- subject.register_type(0x21, ::MyType2)
185
-
186
- expect(subject.type_registered?(0x00)).to be_falsy
187
- expect(subject.type_registered?(0x01)).to be_falsy
188
-
189
- expect(subject.type_registered?(0x20)).to be_truthy
190
- expect(subject.type_registered?(0x21)).to be_truthy
191
- expect(subject.type_registered?(::MyType)).to be_truthy
192
- expect(subject.type_registered?(::MyType2)).to be_truthy
193
- end
194
- end
195
-
196
- describe '#register_type' do
197
- let :src do
198
- ::MyType.new(1, 2)
199
- end
200
-
201
- it 'registers #to_msgpack_ext and .from_msgpack_ext by default' do
202
- subject.register_type(0x7f, ::MyType)
203
-
204
- data = subject.packer.write(src).to_s
205
- my = subject.unpacker.feed(data).read
206
- my.a.should == 1
207
- my.b.should == 2
208
- end
209
-
210
- it 'registers custom packer method name' do
211
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext_only_a, unpacker: :from_msgpack_ext)
212
-
213
- data = subject.packer.write(src).to_s
214
- my = subject.unpacker.feed(data).read
215
- my.a.should == 1
216
- my.b.should == 0
217
- end
218
-
219
- it 'registers custom unpacker method name' do
220
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext, unpacker: 'from_msgpack_ext_only_b')
221
-
222
- data = subject.packer.write(src).to_s
223
- my = subject.unpacker.feed(data).read
224
- my.a.should == 0
225
- my.b.should == 2
226
- end
227
-
228
- it 'registers custom proc objects' do
229
- pk = lambda {|obj| [obj.a + obj.b].pack('C') }
230
- uk = lambda {|data| ::MyType.new(data.unpack('C').first, -1) }
231
- subject.register_type(0x7f, ::MyType, packer: pk, unpacker: uk)
232
-
233
- data = subject.packer.write(src).to_s
234
- my = subject.unpacker.feed(data).read
235
- my.a.should == 3
236
- my.b.should == -1
237
- end
238
-
239
- it 'does not affect existent packer and unpackers' do
240
- subject.register_type(0x7f, ::MyType)
241
- packer = subject.packer
242
- unpacker = subject.unpacker
243
-
244
- subject.register_type(0x7f, ::MyType, packer: :to_msgpack_ext_only_a, unpacker: :from_msgpack_ext_only_b)
245
-
246
- data = packer.write(src).to_s
247
- my = unpacker.feed(data).read
248
- my.a.should == 1
249
- my.b.should == 2
250
- end
251
-
252
- describe "registering an ext type for a module" do
253
- before do
254
- mod = Module.new do
255
- def self.from_msgpack_ext(data)
256
- "unpacked #{data}"
257
- end
258
-
259
- def to_msgpack_ext
260
- 'value_msgpacked'
261
- end
262
- end
263
- stub_const('Mod', mod)
264
- end
265
- let(:factory) { described_class.new }
266
- before { factory.register_type(0x01, Mod) }
267
-
268
- describe "packing an object whose class included the module" do
269
- subject { factory.packer.pack(value).to_s }
270
- before { stub_const('Value', Class.new{ include Mod }) }
271
- let(:value) { Value.new }
272
- it { is_expected.to eq "\xC7\x0F\x01value_msgpacked".force_encoding(Encoding::BINARY) }
273
- end
274
-
275
- describe "packing an object which has been extended by the module" do
276
- subject { factory.packer.pack(object).to_s }
277
- let(:object) { Object.new.extend Mod }
278
- it { is_expected.to eq "\xC7\x0F\x01value_msgpacked".force_encoding(Encoding::BINARY) }
279
- end
280
-
281
- describe "unpacking with the module" do
282
- subject { factory.unpacker.feed("\xC7\x06\x01module".force_encoding(Encoding::BINARY)).unpack }
283
- it { is_expected.to eq "unpacked module" }
284
- end
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
454
- end
455
-
456
- describe 'the special treatment of symbols with ext type' do
457
- def roundtrip(object, options = nil)
458
- subject.load(subject.dump(object), options)
459
- end
460
-
461
- context 'using the optimized symbol unpacker' do
462
- before do
463
- skip if IS_JRUBY # JRuby implementation doesn't support the optimized symbols unpacker for now
464
- subject.register_type(
465
- 0x00,
466
- ::Symbol,
467
- packer: :to_msgpack_ext,
468
- unpacker: :from_msgpack_ext,
469
- optimized_symbols_parsing: true,
470
- )
471
- end
472
-
473
- it 'lets symbols survive a roundtrip' do
474
- expect(roundtrip(:symbol)).to be :symbol
475
- end
476
-
477
- it 'works with empty symbol' do
478
- expect(roundtrip(:"")).to be :""
479
- end
480
-
481
- it 'preserves encoding for ASCII symbols' do
482
- expect(:symbol.encoding).to be Encoding::US_ASCII
483
- expect(roundtrip(:symbol)).to be :symbol
484
- expect(roundtrip(:symbol).encoding).to be Encoding::US_ASCII
485
- end
486
-
487
- it 'preserves encoding for UTF-8 symbols' do
488
- expect(:"fée".encoding).to be Encoding::UTF_8
489
- expect(roundtrip(:"fée").encoding).to be Encoding::UTF_8
490
- expect(roundtrip(:"fée")).to be :"fée"
491
- end
492
- end
493
-
494
- context 'if no ext type is registered for symbols' do
495
- it 'converts symbols to string' do
496
- expect(roundtrip(:symbol)).to eq 'symbol'
497
- end
498
- end
499
-
500
- context 'if an ext type is registered for symbols' do
501
- context 'if using the default serializer' do
502
- before { subject.register_type(0x00, ::Symbol) }
503
-
504
- it 'lets symbols survive a roundtrip' do
505
- expect(roundtrip(:symbol)).to be :symbol
506
- end
507
-
508
- it 'works with hash keys' do
509
- expect(roundtrip(symbol: 1)).to be == { symbol: 1 }
510
- end
511
-
512
- it 'works with frozen: true option' do
513
- expect(roundtrip(:symbol, freeze: true)).to be :symbol
514
- end
515
-
516
- it 'preserves encoding for ASCII symbols' do
517
- expect(:symbol.encoding).to be Encoding::US_ASCII
518
- expect(roundtrip(:symbol)).to be :symbol
519
- expect(roundtrip(:symbol).encoding).to be Encoding::US_ASCII
520
- end
521
-
522
- it 'preserves encoding for UTF-8 symbols' do
523
- expect(:"fée".encoding).to be Encoding::UTF_8
524
- expect(roundtrip(:"fée")).to be :"fée"
525
- expect(roundtrip(:"fée").encoding).to be Encoding::UTF_8
526
- end
527
-
528
- it 'does not handle symbols in other encodings' do
529
- symbol = "fàe".encode(Encoding::ISO_8859_1).to_sym
530
- expect(symbol.encoding).to be Encoding::ISO_8859_1
531
-
532
- if IS_JRUBY
533
- # JRuby doesn't quite behave like MRI here.
534
- # "fàe".force_encoding(Encoding::BINARY).to_sym is able to lookup the existing ISO-8859-1 symbol
535
- # It likely is a JRuby bug.
536
- expect(roundtrip(symbol).encoding).to be Encoding::ISO_8859_1
537
- else
538
- expect(roundtrip(symbol).encoding).to be Encoding::BINARY
539
- end
540
- end
541
- end
542
-
543
- context 'if using a custom serializer' do
544
- before do
545
- class Symbol
546
- alias_method :to_msgpack_ext_orig, :to_msgpack_ext
547
- def to_msgpack_ext
548
- self.to_s.codepoints.to_a.pack('n*')
549
- end
550
- end
551
-
552
- class << Symbol
553
- alias_method :from_msgpack_ext_orig, :from_msgpack_ext
554
- def from_msgpack_ext(data)
555
- data.unpack('n*').map(&:chr).join.to_sym
556
- end
557
- end
558
- end
559
-
560
- before { subject.register_type(0x00, ::Symbol) }
561
-
562
- it 'lets symbols survive a roundtrip' do
563
- expect(roundtrip(:symbol)).to be :symbol
564
- end
565
-
566
- after do
567
- class Symbol
568
- alias_method :to_msgpack_ext, :to_msgpack_ext_orig
569
- end
570
-
571
- class << Symbol
572
- alias_method :from_msgpack_ext, :from_msgpack_ext_orig
573
- end
574
- end
575
- end
576
- end
577
- end
578
-
579
- describe 'under stressful GC' do
580
- it 'works well' do
581
- begin
582
- GC.stress = true
583
-
584
- f = MessagePack::Factory.new
585
- f.register_type(0x0a, Symbol)
586
- ensure
587
- GC.stress = false
588
- end
589
- end
590
-
591
- it 'does not crash in recursive extensions' do
592
- my_hash_type = Class.new(Hash)
593
- factory = MessagePack::Factory.new
594
- factory.register_type(7,
595
- my_hash_type,
596
- packer: ->(value, packer) do
597
- packer.write(value.to_h)
598
- end,
599
- unpacker: ->(unpacker) { my_hash_type.new(unpacker.read) },
600
- recursive: true,
601
- )
602
-
603
- payload = factory.dump(
604
- [my_hash_type.new]
605
- )
606
-
607
- begin
608
- GC.stress = true
609
- factory.load(payload)
610
- ensure
611
- GC.stress = false
612
- end
613
- end
614
- end
615
-
616
- describe 'DefaultFactory' do
617
- it 'is a factory' do
618
- MessagePack::DefaultFactory.should be_kind_of(MessagePack::Factory)
619
- end
620
-
621
- require_relative 'exttypes'
622
-
623
- it 'should be referred by MessagePack.pack and MessagePack.unpack' do
624
- MessagePack::DefaultFactory.register_type(DummyTimeStamp1::TYPE, DummyTimeStamp1)
625
- MessagePack::DefaultFactory.register_type(DummyTimeStamp2::TYPE, DummyTimeStamp2, packer: :serialize, unpacker: :deserialize)
626
-
627
- t = Time.now
628
-
629
- dm1 = DummyTimeStamp1.new(t.to_i, t.usec)
630
- expect(MessagePack.unpack(MessagePack.pack(dm1))).to eq(dm1)
631
-
632
- dm2 = DummyTimeStamp1.new(t.to_i, t.usec)
633
- expect(MessagePack.unpack(MessagePack.pack(dm2))).to eq(dm2)
634
- end
635
- end
636
-
637
- describe '#pool' do
638
- let(:factory) { described_class.new }
639
-
640
- it 'responds to serializers interface' do
641
- pool = factory.pool(1)
642
- expect(pool.load(pool.dump(42))).to be == 42
643
- end
644
-
645
- it 'types can be registered before the pool is created' do
646
- factory.register_type(0x00, Symbol)
647
- pool = factory.pool(1)
648
- expect(pool.load(pool.dump(:foo))).to be == :foo
649
- end
650
-
651
- it 'types cannot be registered after the pool is created' do
652
- pool = factory.pool(1)
653
- factory.register_type(0x20, ::MyType)
654
-
655
- expect do
656
- pool.dump(MyType.new(1, 2))
657
- end.to raise_error NoMethodError
658
-
659
- payload = factory.dump(MyType.new(1, 2))
660
- expect do
661
- pool.load(payload)
662
- end.to raise_error MessagePack::UnknownExtTypeError
663
- end
664
-
665
- it 'support symbolize_keys: true' do
666
- pool = factory.pool(1, symbolize_keys: true)
667
- expect(pool.load(pool.dump('foo' => 1))).to be == { foo: 1 }
668
- end
669
-
670
- it 'support freeze: true' do
671
- pool = factory.pool(1, freeze: true)
672
- expect(pool.load(pool.dump('foo'))).to be_frozen
673
- end
674
-
675
- it 'is thread safe' do
676
- pool = factory.pool(1)
677
-
678
- threads = 10.times.map do
679
- Thread.new do
680
- 1_000.times do |i|
681
- expect(pool.load(pool.dump(i))).to be == i
682
- end
683
- end
684
- end
685
- threads.each(&:join)
686
- end
687
- end
688
- end