msgpack 1.4.5 → 1.5.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/ChangeLog +6 -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 +45 -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 +26 -6
- 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 +193 -0
- data/spec/spec_helper.rb +1 -0
- metadata +4 -2
@@ -33,6 +33,10 @@ static VALUE eUnexpectedTypeError;
|
|
33
33
|
static VALUE eUnknownExtTypeError;
|
34
34
|
static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
|
35
35
|
|
36
|
+
static VALUE sym_symbolize_keys;
|
37
|
+
static VALUE sym_freeze;
|
38
|
+
static VALUE sym_allow_unknown_ext;
|
39
|
+
|
36
40
|
#define UNPACKER(from, name) \
|
37
41
|
msgpack_unpacker_t *name = NULL; \
|
38
42
|
Data_Get_Struct(from, msgpack_unpacker_t, name); \
|
@@ -83,7 +87,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
83
87
|
} else if(argc == 2) {
|
84
88
|
io = argv[0];
|
85
89
|
options = argv[1];
|
86
|
-
if(rb_type(options) != T_HASH) {
|
90
|
+
if(options != Qnil && rb_type(options) != T_HASH) {
|
87
91
|
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
88
92
|
}
|
89
93
|
|
@@ -100,13 +104,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
100
104
|
if(options != Qnil) {
|
101
105
|
VALUE v;
|
102
106
|
|
103
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_symbolize_keys);
|
104
108
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
105
109
|
|
106
|
-
v = rb_hash_aref(options,
|
110
|
+
v = rb_hash_aref(options, sym_freeze);
|
107
111
|
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
108
112
|
|
109
|
-
v = rb_hash_aref(options,
|
113
|
+
v = rb_hash_aref(options, sym_allow_unknown_ext);
|
110
114
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
111
115
|
}
|
112
116
|
|
@@ -143,6 +147,7 @@ NORETURN(static void raise_unpacker_error(int r))
|
|
143
147
|
case PRIMITIVE_UNEXPECTED_TYPE:
|
144
148
|
rb_raise(eUnexpectedTypeError, "unexpected type");
|
145
149
|
case PRIMITIVE_UNEXPECTED_EXT_TYPE:
|
150
|
+
// rb_bug("unexpected extension type");
|
146
151
|
rb_raise(eUnknownExtTypeError, "unexpected extension type");
|
147
152
|
default:
|
148
153
|
rb_raise(eUnpackError, "logically unknown error %d", r);
|
@@ -361,7 +366,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
361
366
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
362
367
|
}
|
363
368
|
|
364
|
-
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
|
369
|
+
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
|
365
370
|
|
366
371
|
return Qnil;
|
367
372
|
}
|
@@ -411,6 +416,10 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
411
416
|
|
412
417
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
413
418
|
|
419
|
+
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
420
|
+
sym_freeze = ID2SYM(rb_intern("freeze"));
|
421
|
+
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
422
|
+
|
414
423
|
rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
|
415
424
|
|
416
425
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
@@ -77,9 +77,10 @@ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg
|
|
77
77
|
}
|
78
78
|
|
79
79
|
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
80
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
80
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
|
81
81
|
{
|
82
82
|
msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
|
83
|
-
|
83
|
+
|
84
|
+
ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
|
84
85
|
*ukrg = ext_registry;
|
85
86
|
}
|
@@ -21,6 +21,8 @@
|
|
21
21
|
#include "compat.h"
|
22
22
|
#include "ruby.h"
|
23
23
|
|
24
|
+
#define MSGPACK_EXT_RECURSIVE 0b0001
|
25
|
+
|
24
26
|
struct msgpack_unpacker_ext_registry_t;
|
25
27
|
typedef struct msgpack_unpacker_ext_registry_t msgpack_unpacker_ext_registry_t;
|
26
28
|
|
@@ -46,14 +48,15 @@ static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_reg
|
|
46
48
|
void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
|
47
49
|
|
48
50
|
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
49
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
|
51
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
|
50
52
|
|
51
53
|
static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
|
52
|
-
int ext_type)
|
54
|
+
int ext_type, int* ext_flags_result)
|
53
55
|
{
|
54
56
|
if (ukrg) {
|
55
57
|
VALUE entry = ukrg->array[ext_type + 128];
|
56
58
|
if (entry != Qnil) {
|
59
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
|
57
60
|
return rb_ary_entry(entry, 1);
|
58
61
|
}
|
59
62
|
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MessagePack
|
4
|
+
module Bigint
|
5
|
+
# We split the bigint in 32bits chunks so that individual part fits into
|
6
|
+
# a MRI immediate Integer.
|
7
|
+
CHUNK_BITLENGTH = 32
|
8
|
+
FORMAT = 'CL>*'
|
9
|
+
|
10
|
+
if Integer.instance_method(:[]).arity != 1 # Ruby 2.7 and newer
|
11
|
+
# Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[]
|
12
|
+
# This allows to not allocate any Integer.
|
13
|
+
def self.to_msgpack_ext(bigint)
|
14
|
+
members = []
|
15
|
+
|
16
|
+
if bigint < 0
|
17
|
+
bigint = -bigint
|
18
|
+
members << 1
|
19
|
+
else
|
20
|
+
members << 0
|
21
|
+
end
|
22
|
+
|
23
|
+
offset = 0
|
24
|
+
length = bigint.bit_length
|
25
|
+
while offset < length
|
26
|
+
members << bigint[offset, CHUNK_BITLENGTH]
|
27
|
+
offset += CHUNK_BITLENGTH
|
28
|
+
end
|
29
|
+
|
30
|
+
members.pack(FORMAT)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
# On 2.6 and older since we can't address arbitrary bitranges, so we fallback to shifting the bigint.
|
34
|
+
# This means that after each shift, we may allocate another Integer instance.
|
35
|
+
BASE = (2**CHUNK_BITLENGTH) - 1
|
36
|
+
def self.to_msgpack_ext(bigint)
|
37
|
+
members = []
|
38
|
+
|
39
|
+
if bigint < 0
|
40
|
+
bigint = -bigint
|
41
|
+
members << 1
|
42
|
+
else
|
43
|
+
members << 0
|
44
|
+
end
|
45
|
+
|
46
|
+
while bigint > 0
|
47
|
+
members << (bigint & BASE)
|
48
|
+
bigint = bigint >> CHUNK_BITLENGTH
|
49
|
+
end
|
50
|
+
|
51
|
+
members.pack(FORMAT)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.from_msgpack_ext(data)
|
56
|
+
parts = data.unpack(FORMAT)
|
57
|
+
|
58
|
+
sign = parts.shift
|
59
|
+
sum = parts.pop.to_i
|
60
|
+
|
61
|
+
parts.reverse_each do |part|
|
62
|
+
sum = sum << CHUNK_BITLENGTH
|
63
|
+
sum += part
|
64
|
+
end
|
65
|
+
|
66
|
+
sign == 0 ? sum : -sum
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/msgpack/factory.rb
CHANGED
@@ -77,5 +77,108 @@ module MessagePack
|
|
77
77
|
packer.full_pack
|
78
78
|
end
|
79
79
|
alias :pack :dump
|
80
|
+
|
81
|
+
def pool(size = 1, **options)
|
82
|
+
Pool.new(
|
83
|
+
frozen? ? self : dup.freeze,
|
84
|
+
size,
|
85
|
+
options.empty? ? nil : options,
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
class Pool
|
90
|
+
if RUBY_ENGINE == "ruby"
|
91
|
+
class AbstractPool
|
92
|
+
def initialize(size, &block)
|
93
|
+
@size = size
|
94
|
+
@new_member = block
|
95
|
+
@members = []
|
96
|
+
end
|
97
|
+
|
98
|
+
def checkout
|
99
|
+
@members.pop || @new_member.call
|
100
|
+
end
|
101
|
+
|
102
|
+
def checkin(member)
|
103
|
+
# If the pool is already full, we simply drop the extra member.
|
104
|
+
# This is because contrary to a connection pool, creating an extra instance
|
105
|
+
# is extremely unlikely to cause some kind of resource exhaustion.
|
106
|
+
#
|
107
|
+
# We could cycle the members (keep the newer one) but first It's more work and second
|
108
|
+
# the older member might have been created pre-fork, so it might be at least partially
|
109
|
+
# in shared memory.
|
110
|
+
if member && @members.size < @size
|
111
|
+
member.reset
|
112
|
+
@members << member
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
else
|
117
|
+
class AbstractPool
|
118
|
+
def initialize(size, &block)
|
119
|
+
@size = size
|
120
|
+
@new_member = block
|
121
|
+
@members = []
|
122
|
+
@mutex = Mutex.new
|
123
|
+
end
|
124
|
+
|
125
|
+
def checkout
|
126
|
+
@mutex.synchronize { @members.pop } || @new_member.call
|
127
|
+
end
|
128
|
+
|
129
|
+
def checkin(member)
|
130
|
+
@mutex.synchronize do
|
131
|
+
if member && @members.size < @size
|
132
|
+
member.reset
|
133
|
+
@members << member
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class PackerPool < AbstractPool
|
141
|
+
private
|
142
|
+
|
143
|
+
def reset(packer)
|
144
|
+
packer.clear
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class UnpackerPool < AbstractPool
|
149
|
+
private
|
150
|
+
|
151
|
+
def reset(unpacker)
|
152
|
+
unpacker.reset
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def initialize(factory, size, options = nil)
|
157
|
+
options = nil if !options || options.empty?
|
158
|
+
@factory = factory
|
159
|
+
@packers = PackerPool.new(size) { factory.packer(options) }
|
160
|
+
@unpackers = UnpackerPool.new(size) { factory.unpacker(options) }
|
161
|
+
end
|
162
|
+
|
163
|
+
def load(data)
|
164
|
+
unpacker = @unpackers.checkout
|
165
|
+
begin
|
166
|
+
unpacker.feed_reference(data)
|
167
|
+
unpacker.full_unpack
|
168
|
+
ensure
|
169
|
+
@unpackers.checkin(unpacker)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def dump(object)
|
174
|
+
packer = @packers.checkout
|
175
|
+
begin
|
176
|
+
packer.write(object)
|
177
|
+
packer.full_pack
|
178
|
+
ensure
|
179
|
+
@packers.checkin(packer)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
80
183
|
end
|
81
184
|
end
|
data/lib/msgpack/version.rb
CHANGED
data/lib/msgpack.rb
CHANGED
@@ -17,16 +17,15 @@ require "msgpack/time"
|
|
17
17
|
|
18
18
|
module MessagePack
|
19
19
|
DefaultFactory = MessagePack::Factory.new
|
20
|
-
DEFAULT_EMPTY_PARAMS = {}.freeze
|
21
20
|
|
22
21
|
def load(src, param = nil)
|
23
22
|
unpacker = nil
|
24
23
|
|
25
24
|
if src.is_a? String
|
26
|
-
unpacker = DefaultFactory.unpacker param
|
25
|
+
unpacker = DefaultFactory.unpacker param
|
27
26
|
unpacker.feed_reference src
|
28
27
|
else
|
29
|
-
unpacker = DefaultFactory.unpacker src, param
|
28
|
+
unpacker = DefaultFactory.unpacker src, param
|
30
29
|
end
|
31
30
|
|
32
31
|
unpacker.full_unpack
|
@@ -36,8 +35,8 @@ module MessagePack
|
|
36
35
|
module_function :load
|
37
36
|
module_function :unpack
|
38
37
|
|
39
|
-
def pack(v,
|
40
|
-
packer = DefaultFactory.packer(
|
38
|
+
def pack(v, io = nil, options = nil)
|
39
|
+
packer = DefaultFactory.packer(io, options)
|
41
40
|
packer.write v
|
42
41
|
packer.full_pack
|
43
42
|
end
|
data/spec/bigint_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MessagePack::Bigint do
|
4
|
+
it 'serialize and deserialize arbitrary sized integer' do
|
5
|
+
[
|
6
|
+
1,
|
7
|
+
-1,
|
8
|
+
120938120391283122132313,
|
9
|
+
-21903120391203912391023920332103,
|
10
|
+
210290021321301203912933021323,
|
11
|
+
].each do |int|
|
12
|
+
expect(MessagePack::Bigint.from_msgpack_ext(MessagePack::Bigint.to_msgpack_ext(int))).to be == int
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'has a stable format' do
|
17
|
+
{
|
18
|
+
120938120391283122132313 => "\x00\x9F\xF4UY\x11\x92\x9A?\x00\x00\x19\x9C".b,
|
19
|
+
-21903120391203912391023920332103 => "\x01/\xB2\xBDG\xBD\xDE\xAA\xEBt\xCC\x8A\xC1\x00\x00\x01\x14".b,
|
20
|
+
210290021321301203912933021323 => "\x00\xC4\xD8\x96\x8Bm\xCB\xC7\x03\xA7{\xD4\"\x00\x00\x00\x02".b,
|
21
|
+
}.each do |int, payload|
|
22
|
+
expect(MessagePack::Bigint.to_msgpack_ext(int)).to be == payload
|
23
|
+
expect(MessagePack::Bigint.from_msgpack_ext(payload)).to be == int
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/factory_spec.rb
CHANGED
@@ -283,6 +283,147 @@ 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
|
+
end
|
426
|
+
end
|
286
427
|
end
|
287
428
|
|
288
429
|
describe 'the special treatment of symbols with ext type' do
|
@@ -437,4 +578,56 @@ describe MessagePack::Factory do
|
|
437
578
|
expect(MessagePack.unpack(MessagePack.pack(dm2))).to eq(dm2)
|
438
579
|
end
|
439
580
|
end
|
581
|
+
|
582
|
+
describe '#pool' do
|
583
|
+
let(:factory) { described_class.new }
|
584
|
+
|
585
|
+
it 'responds to serializers interface' do
|
586
|
+
pool = factory.pool(1)
|
587
|
+
expect(pool.load(pool.dump(42))).to be == 42
|
588
|
+
end
|
589
|
+
|
590
|
+
it 'types can be registered before the pool is created' do
|
591
|
+
factory.register_type(0x00, Symbol)
|
592
|
+
pool = factory.pool(1)
|
593
|
+
expect(pool.load(pool.dump(:foo))).to be == :foo
|
594
|
+
end
|
595
|
+
|
596
|
+
it 'types cannot be registered after the pool is created' do
|
597
|
+
pool = factory.pool(1)
|
598
|
+
factory.register_type(0x20, ::MyType)
|
599
|
+
|
600
|
+
expect do
|
601
|
+
pool.dump(MyType.new(1, 2))
|
602
|
+
end.to raise_error NoMethodError
|
603
|
+
|
604
|
+
payload = factory.dump(MyType.new(1, 2))
|
605
|
+
expect do
|
606
|
+
pool.load(payload)
|
607
|
+
end.to raise_error MessagePack::UnknownExtTypeError
|
608
|
+
end
|
609
|
+
|
610
|
+
it 'support symbolize_keys: true' do
|
611
|
+
pool = factory.pool(1, symbolize_keys: true)
|
612
|
+
expect(pool.load(pool.dump('foo' => 1))).to be == { foo: 1 }
|
613
|
+
end
|
614
|
+
|
615
|
+
it 'support freeze: true' do
|
616
|
+
pool = factory.pool(1, freeze: true)
|
617
|
+
expect(pool.load(pool.dump('foo'))).to be_frozen
|
618
|
+
end
|
619
|
+
|
620
|
+
it 'is thread safe' do
|
621
|
+
pool = factory.pool(1)
|
622
|
+
|
623
|
+
threads = 10.times.map do
|
624
|
+
Thread.new do
|
625
|
+
1_000.times do |i|
|
626
|
+
expect(pool.load(pool.dump(i))).to be == i
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
threads.each(&:join)
|
631
|
+
end
|
632
|
+
end
|
440
633
|
end
|
data/spec/spec_helper.rb
CHANGED
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.0
|
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-04-06 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
|