msgpack 1.4.5 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/ext/msgpack/unpacker.c
CHANGED
@@ -52,6 +52,16 @@ void msgpack_unpacker_static_destroy()
|
|
52
52
|
|
53
53
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
54
|
|
55
|
+
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
56
|
+
#ifdef UNPACKER_STACK_RMEM
|
57
|
+
return msgpack_rmem_alloc(&s_stack_rmem);
|
58
|
+
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
59
|
+
#else
|
60
|
+
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
|
61
|
+
return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
62
|
+
#endif
|
63
|
+
}
|
64
|
+
|
55
65
|
msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
56
66
|
{
|
57
67
|
msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
|
@@ -63,26 +73,23 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
|
63
73
|
uk->last_object = Qnil;
|
64
74
|
uk->reading_raw = Qnil;
|
65
75
|
|
66
|
-
|
67
|
-
uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
|
68
|
-
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
69
|
-
#else
|
70
|
-
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
|
71
|
-
uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
72
|
-
#endif
|
76
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
73
77
|
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
74
78
|
|
75
79
|
return uk;
|
76
80
|
}
|
77
81
|
|
82
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
83
|
+
#ifdef UNPACKER_STACK_RMEM
|
84
|
+
msgpack_rmem_free(&s_stack_rmem, stack);
|
85
|
+
#else
|
86
|
+
xfree(stack);
|
87
|
+
#endif
|
88
|
+
}
|
89
|
+
|
78
90
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
79
91
|
{
|
80
|
-
|
81
|
-
msgpack_rmem_free(&s_stack_rmem, uk->stack);
|
82
|
-
#else
|
83
|
-
xfree(uk->stack);
|
84
|
-
#endif
|
85
|
-
|
92
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
86
93
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
87
94
|
}
|
88
95
|
|
@@ -166,14 +173,17 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
166
173
|
return object_complete_symbol(uk, rb_str_intern(str));
|
167
174
|
}
|
168
175
|
|
169
|
-
|
176
|
+
int ext_flags;
|
177
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
178
|
+
|
170
179
|
if(proc != Qnil) {
|
171
|
-
VALUE obj
|
180
|
+
VALUE obj;
|
181
|
+
obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
|
172
182
|
return object_complete(uk, obj);
|
173
183
|
}
|
174
184
|
|
175
185
|
if(uk->allow_unknown_ext) {
|
176
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
186
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
177
187
|
return object_complete(uk, obj);
|
178
188
|
}
|
179
189
|
|
@@ -283,6 +293,36 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
283
293
|
{
|
284
294
|
/* assuming uk->reading_raw == Qnil */
|
285
295
|
|
296
|
+
int ext_flags;
|
297
|
+
VALUE proc;
|
298
|
+
|
299
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
300
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
301
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
302
|
+
VALUE obj;
|
303
|
+
uk->last_object = Qnil;
|
304
|
+
reset_head_byte(uk);
|
305
|
+
uk->reading_raw_remaining = 0;
|
306
|
+
|
307
|
+
msgpack_unpacker_stack_t* stack = uk->stack;
|
308
|
+
size_t stack_depth = uk->stack_depth;
|
309
|
+
size_t stack_capacity = uk->stack_capacity;
|
310
|
+
|
311
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
312
|
+
uk->stack_depth = 0;
|
313
|
+
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
314
|
+
|
315
|
+
obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
|
316
|
+
|
317
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
318
|
+
uk->stack = stack;
|
319
|
+
uk->stack_depth = stack_depth;
|
320
|
+
uk->stack_capacity = stack_capacity;
|
321
|
+
|
322
|
+
return object_complete(uk, obj);
|
323
|
+
}
|
324
|
+
}
|
325
|
+
|
286
326
|
/* try optimized read */
|
287
327
|
size_t length = uk->reading_raw_remaining;
|
288
328
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
@@ -371,7 +411,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
371
411
|
uint8_t length = cb->u8;
|
372
412
|
int ext_type = (signed char) cb->buffer[1];
|
373
413
|
if(length == 0) {
|
374
|
-
return object_complete_ext(uk, ext_type,
|
414
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
375
415
|
}
|
376
416
|
uk->reading_raw_remaining = length;
|
377
417
|
return read_raw_body_begin(uk, ext_type);
|
@@ -383,7 +423,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
383
423
|
uint16_t length = _msgpack_be16(cb->u16);
|
384
424
|
int ext_type = (signed char) cb->buffer[2];
|
385
425
|
if(length == 0) {
|
386
|
-
return object_complete_ext(uk, ext_type,
|
426
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
387
427
|
}
|
388
428
|
uk->reading_raw_remaining = length;
|
389
429
|
return read_raw_body_begin(uk, ext_type);
|
@@ -395,7 +435,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
395
435
|
uint32_t length = _msgpack_be32(cb->u32);
|
396
436
|
int ext_type = (signed char) cb->buffer[4];
|
397
437
|
if(length == 0) {
|
398
|
-
return object_complete_ext(uk, ext_type,
|
438
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
399
439
|
}
|
400
440
|
uk->reading_raw_remaining = length;
|
401
441
|
return read_raw_body_begin(uk, ext_type);
|
@@ -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
|