msgpack 1.4.0.pre1 → 1.4.3
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 +56 -0
- data/ChangeLog +22 -0
- data/README.md +242 -0
- data/Rakefile +2 -9
- data/doclib/msgpack/factory.rb +1 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +17 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -10
- data/ext/java/org/msgpack/jruby/Encoder.java +22 -12
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +9 -9
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
- data/ext/java/org/msgpack/jruby/Factory.java +7 -2
- data/ext/java/org/msgpack/jruby/Packer.java +11 -9
- data/ext/java/org/msgpack/jruby/Unpacker.java +39 -26
- data/ext/msgpack/buffer.c +4 -16
- data/ext/msgpack/buffer.h +46 -5
- data/ext/msgpack/compat.h +1 -12
- data/ext/msgpack/extconf.rb +27 -7
- data/ext/msgpack/factory_class.c +10 -5
- data/ext/msgpack/packer.c +18 -5
- data/ext/msgpack/packer.h +0 -16
- data/ext/msgpack/packer_class.c +0 -9
- data/ext/msgpack/packer_ext_registry.c +0 -22
- data/ext/msgpack/unpacker.c +39 -50
- data/ext/msgpack/unpacker.h +8 -0
- data/ext/msgpack/unpacker_class.c +10 -5
- data/lib/msgpack/symbol.rb +14 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/version.rb +4 -8
- data/lib/msgpack.rb +1 -2
- data/msgpack.gemspec +3 -5
- data/spec/factory_spec.rb +17 -0
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/timestamp_spec.rb +40 -0
- data/spec/unpacker_spec.rb +102 -1
- metadata +12 -26
- data/.travis.yml +0 -39
- data/README.rdoc +0 -225
data/ext/msgpack/factory_class.c
CHANGED
@@ -32,6 +32,8 @@ struct msgpack_factory_t {
|
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
33
33
|
msgpack_unpacker_ext_registry_t ukrg;
|
34
34
|
bool has_symbol_ext_type;
|
35
|
+
bool optimized_symbol_ext_type;
|
36
|
+
int symbol_ext_type;
|
35
37
|
};
|
36
38
|
|
37
39
|
#define FACTORY(from, name) \
|
@@ -114,6 +116,8 @@ VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
|
114
116
|
|
115
117
|
msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
|
116
118
|
msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
|
119
|
+
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
120
|
+
uk->symbol_ext_type = fc->symbol_ext_type;
|
117
121
|
|
118
122
|
return unpacker;
|
119
123
|
}
|
@@ -128,11 +132,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
|
|
128
132
|
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg.array[i]);
|
129
133
|
}
|
130
134
|
}
|
131
|
-
#ifdef HAVE_RB_HASH_DUP
|
132
135
|
return rb_ary_new3(2, rb_hash_dup(fc->pkrg.hash), uk_mapping);
|
133
|
-
#else
|
134
|
-
return rb_ary_new3(2, rb_funcall(fc->pkrg.hash, rb_intern("dup"), 0), uk_mapping);
|
135
|
-
#endif
|
136
136
|
}
|
137
137
|
|
138
138
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -141,7 +141,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
141
141
|
|
142
142
|
int ext_type;
|
143
143
|
VALUE ext_module;
|
144
|
-
VALUE options;
|
144
|
+
VALUE options = Qnil;
|
145
145
|
VALUE packer_arg, unpacker_arg;
|
146
146
|
VALUE packer_proc, unpacker_proc;
|
147
147
|
|
@@ -188,6 +188,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
188
188
|
if(unpacker_arg != Qnil) {
|
189
189
|
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
|
190
190
|
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
|
191
|
+
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
|
192
|
+
unpacker_proc = unpacker_arg;
|
191
193
|
} else {
|
192
194
|
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
|
193
195
|
}
|
@@ -197,6 +199,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
197
199
|
|
198
200
|
if (ext_module == rb_cSymbol) {
|
199
201
|
fc->has_symbol_ext_type = true;
|
202
|
+
if(RB_TEST(options) && RB_TEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
203
|
+
fc->optimized_symbol_ext_type = true;
|
204
|
+
}
|
200
205
|
}
|
201
206
|
|
202
207
|
msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, unpacker_proc, unpacker_arg);
|
data/ext/msgpack/packer.c
CHANGED
@@ -121,7 +121,7 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
121
121
|
#endif
|
122
122
|
}
|
123
123
|
|
124
|
-
|
124
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
125
125
|
{
|
126
126
|
int ext_type;
|
127
127
|
|
@@ -131,7 +131,14 @@ void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
|
131
131
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
132
|
StringValue(payload);
|
133
133
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
|
134
|
+
return true;
|
135
|
+
}
|
136
|
+
return false;
|
137
|
+
}
|
138
|
+
|
139
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
140
|
+
{
|
141
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
135
142
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
136
143
|
}
|
137
144
|
}
|
@@ -155,13 +162,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
155
162
|
msgpack_packer_write_symbol_value(pk, v);
|
156
163
|
break;
|
157
164
|
case T_STRING:
|
158
|
-
|
165
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
166
|
+
msgpack_packer_write_string_value(pk, v);
|
167
|
+
}
|
159
168
|
break;
|
160
169
|
case T_ARRAY:
|
161
|
-
|
170
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
171
|
+
msgpack_packer_write_array_value(pk, v);
|
172
|
+
}
|
162
173
|
break;
|
163
174
|
case T_HASH:
|
164
|
-
|
175
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
176
|
+
msgpack_packer_write_hash_value(pk, v);
|
177
|
+
}
|
165
178
|
break;
|
166
179
|
case T_BIGNUM:
|
167
180
|
msgpack_packer_write_bignum_value(pk, v);
|
data/ext/msgpack/packer.h
CHANGED
@@ -396,7 +396,6 @@ static inline void msgpack_packer_write_ext(msgpack_packer_t* pk, int ext_type,
|
|
396
396
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), payload);
|
397
397
|
}
|
398
398
|
|
399
|
-
#ifdef COMPAT_HAVE_ENCODING
|
400
399
|
static inline bool msgpack_packer_is_binary(VALUE v, int encindex)
|
401
400
|
{
|
402
401
|
return encindex == msgpack_rb_encindex_ascii8bit;
|
@@ -414,7 +413,6 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
414
413
|
#endif
|
415
414
|
;
|
416
415
|
}
|
417
|
-
#endif
|
418
416
|
|
419
417
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
420
418
|
{
|
@@ -425,7 +423,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
425
423
|
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
426
424
|
}
|
427
425
|
|
428
|
-
#ifdef COMPAT_HAVE_ENCODING
|
429
426
|
int encindex = ENCODING_GET(v);
|
430
427
|
if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
|
431
428
|
/* write ASCII-8BIT string using Binary type */
|
@@ -443,24 +440,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
443
440
|
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
444
441
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
445
442
|
}
|
446
|
-
#else
|
447
|
-
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
448
|
-
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
449
|
-
#endif
|
450
443
|
}
|
451
444
|
|
452
445
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
453
446
|
{
|
454
|
-
#ifdef HAVE_RB_SYM2STR
|
455
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
456
447
|
msgpack_packer_write_string_value(pk, rb_sym2str(v));
|
457
|
-
#else
|
458
|
-
VALUE str = rb_id2str(SYM2ID(v));
|
459
|
-
if (!str) {
|
460
|
-
rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
|
461
|
-
}
|
462
|
-
msgpack_packer_write_string_value(pk, str);
|
463
|
-
#endif
|
464
448
|
}
|
465
449
|
|
466
450
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
data/ext/msgpack/packer_class.c
CHANGED
@@ -339,11 +339,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
339
339
|
static VALUE Packer_registered_types_internal(VALUE self)
|
340
340
|
{
|
341
341
|
PACKER(self, pk);
|
342
|
-
#ifdef HAVE_RB_HASH_DUP
|
343
342
|
return rb_hash_dup(pk->ext_registry.hash);
|
344
|
-
#else
|
345
|
-
return rb_funcall(pk->ext_registry.hash, rb_intern("dup"), 0);
|
346
|
-
#endif
|
347
343
|
}
|
348
344
|
|
349
345
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -359,12 +355,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
359
355
|
case 2:
|
360
356
|
/* register_type(0x7f, Time) {|obj| block... } */
|
361
357
|
rb_need_block();
|
362
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
363
358
|
proc = rb_block_lambda();
|
364
|
-
#else
|
365
|
-
/* MRI 1.8 */
|
366
|
-
proc = rb_block_proc();
|
367
|
-
#endif
|
368
359
|
arg = proc;
|
369
360
|
break;
|
370
361
|
case 3:
|
@@ -43,37 +43,15 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
|
|
43
43
|
void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
|
44
44
|
msgpack_packer_ext_registry_t* dst)
|
45
45
|
{
|
46
|
-
#ifdef HAVE_RB_HASH_DUP
|
47
46
|
dst->hash = rb_hash_dup(src->hash);
|
48
47
|
dst->cache = rb_hash_dup(src->cache);
|
49
|
-
#else
|
50
|
-
dst->hash = rb_funcall(src->hash, rb_intern("dup"), 0);
|
51
|
-
dst->cache = rb_funcall(src->cache, rb_intern("dup"), 0);
|
52
|
-
#endif
|
53
48
|
}
|
54
49
|
|
55
|
-
#ifndef HAVE_RB_HASH_CLEAR
|
56
|
-
|
57
|
-
static int
|
58
|
-
__rb_hash_clear_clear_i(key, value, dummy)
|
59
|
-
VALUE key, value, dummy;
|
60
|
-
{
|
61
|
-
return ST_DELETE;
|
62
|
-
}
|
63
|
-
|
64
|
-
#endif
|
65
|
-
|
66
50
|
VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
|
67
51
|
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
68
52
|
{
|
69
53
|
VALUE e = rb_ary_new3(3, INT2FIX(ext_type), proc, arg);
|
70
54
|
/* clear lookup cache not to miss added type */
|
71
|
-
#ifdef HAVE_RB_HASH_CLEAR
|
72
55
|
rb_hash_clear(pkrg->cache);
|
73
|
-
#else
|
74
|
-
if(FIX2INT(rb_funcall(pkrg->cache, rb_intern("size"), 0)) > 0) {
|
75
|
-
rb_hash_foreach(pkrg->cache, __rb_hash_clear_clear_i, 0);
|
76
|
-
}
|
77
|
-
#endif
|
78
56
|
return rb_hash_aset(pkrg->hash, ext_module, e);
|
79
57
|
}
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -142,32 +142,27 @@ static inline void reset_head_byte(msgpack_unpacker_t* uk)
|
|
142
142
|
|
143
143
|
static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
|
144
144
|
{
|
145
|
+
if(uk->freeze) {
|
146
|
+
rb_obj_freeze(object);
|
147
|
+
}
|
148
|
+
|
145
149
|
uk->last_object = object;
|
146
150
|
reset_head_byte(uk);
|
147
151
|
return PRIMITIVE_OBJECT_COMPLETE;
|
148
152
|
}
|
149
153
|
|
150
|
-
static inline int
|
151
|
-
{
|
152
|
-
#ifdef COMPAT_HAVE_ENCODING
|
153
|
-
ENCODING_SET(str, msgpack_rb_encindex_utf8);
|
154
|
-
#endif
|
155
|
-
return object_complete(uk, str);
|
156
|
-
}
|
157
|
-
|
158
|
-
static inline int object_complete_binary(msgpack_unpacker_t* uk, VALUE str)
|
154
|
+
static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
159
155
|
{
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
return object_complete(uk, str);
|
156
|
+
uk->last_object = object;
|
157
|
+
reset_head_byte(uk);
|
158
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
164
159
|
}
|
165
160
|
|
166
161
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
167
162
|
{
|
168
|
-
|
169
|
-
|
170
|
-
|
163
|
+
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
164
|
+
return object_complete_symbol(uk, rb_str_intern(str));
|
165
|
+
}
|
171
166
|
|
172
167
|
VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
|
173
168
|
if(proc != Qnil) {
|
@@ -271,9 +266,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
|
|
271
266
|
|
272
267
|
int ret;
|
273
268
|
if(uk->reading_raw_type == RAW_TYPE_STRING) {
|
274
|
-
|
275
|
-
|
276
|
-
|
269
|
+
ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
|
270
|
+
ret = object_complete(uk, uk->reading_raw);
|
271
|
+
} else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
|
272
|
+
ret = object_complete(uk, uk->reading_raw);
|
277
273
|
} else {
|
278
274
|
ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
|
279
275
|
}
|
@@ -288,24 +284,27 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
288
284
|
/* try optimized read */
|
289
285
|
size_t length = uk->reading_raw_remaining;
|
290
286
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
291
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
292
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
293
|
-
bool will_freeze = is_reading_map_key(uk);
|
294
|
-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze);
|
295
287
|
int ret;
|
296
|
-
if(
|
297
|
-
|
298
|
-
|
299
|
-
ret = object_complete_binary(uk, string);
|
288
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
289
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length);
|
290
|
+
ret = object_complete_symbol(uk, symbol);
|
300
291
|
} else {
|
301
|
-
|
302
|
-
|
292
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
293
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
294
|
+
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
295
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
296
|
+
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
297
|
+
ret = object_complete(uk, string);
|
298
|
+
} else {
|
299
|
+
ret = object_complete_ext(uk, raw_type, string);
|
300
|
+
}
|
303
301
|
|
304
302
|
# if !HASH_ASET_DEDUPE
|
305
|
-
|
306
|
-
|
307
|
-
|
303
|
+
if(will_freeze) {
|
304
|
+
rb_obj_freeze(string);
|
305
|
+
}
|
308
306
|
# endif
|
307
|
+
}
|
309
308
|
uk->reading_raw_remaining = 0;
|
310
309
|
return ret;
|
311
310
|
}
|
@@ -335,7 +334,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
335
334
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
336
335
|
int count = b & 0x1f;
|
337
336
|
if(count == 0) {
|
338
|
-
return
|
337
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
339
338
|
}
|
340
339
|
/* read_raw_body_begin sets uk->reading_raw */
|
341
340
|
uk->reading_raw_remaining = count;
|
@@ -520,7 +519,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
520
519
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
521
520
|
uint8_t count = cb->u8;
|
522
521
|
if(count == 0) {
|
523
|
-
return
|
522
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
524
523
|
}
|
525
524
|
/* read_raw_body_begin sets uk->reading_raw */
|
526
525
|
uk->reading_raw_remaining = count;
|
@@ -532,7 +531,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
532
531
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
533
532
|
uint16_t count = _msgpack_be16(cb->u16);
|
534
533
|
if(count == 0) {
|
535
|
-
return
|
534
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
536
535
|
}
|
537
536
|
/* read_raw_body_begin sets uk->reading_raw */
|
538
537
|
uk->reading_raw_remaining = count;
|
@@ -544,7 +543,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
544
543
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
545
544
|
uint32_t count = _msgpack_be32(cb->u32);
|
546
545
|
if(count == 0) {
|
547
|
-
return
|
546
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
548
547
|
}
|
549
548
|
/* read_raw_body_begin sets uk->reading_raw */
|
550
549
|
uk->reading_raw_remaining = count;
|
@@ -556,7 +555,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
556
555
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
557
556
|
uint8_t count = cb->u8;
|
558
557
|
if(count == 0) {
|
559
|
-
return
|
558
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
560
559
|
}
|
561
560
|
/* read_raw_body_begin sets uk->reading_raw */
|
562
561
|
uk->reading_raw_remaining = count;
|
@@ -568,7 +567,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
568
567
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
569
568
|
uint16_t count = _msgpack_be16(cb->u16);
|
570
569
|
if(count == 0) {
|
571
|
-
return
|
570
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
572
571
|
}
|
573
572
|
/* read_raw_body_begin sets uk->reading_raw */
|
574
573
|
uk->reading_raw_remaining = count;
|
@@ -580,7 +579,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
580
579
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
581
580
|
uint32_t count = _msgpack_be32(cb->u32);
|
582
581
|
if(count == 0) {
|
583
|
-
return
|
582
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
584
583
|
}
|
585
584
|
/* read_raw_body_begin sets uk->reading_raw */
|
586
585
|
uk->reading_raw_remaining = count;
|
@@ -722,18 +721,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
722
721
|
break;
|
723
722
|
case STACK_TYPE_MAP_VALUE:
|
724
723
|
if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
|
725
|
-
/* here uses
|
726
|
-
#ifdef HAVE_RB_STR_INTERN
|
727
|
-
/* rb_str_intern is added since MRI 2.2.0 */
|
724
|
+
/* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
|
728
725
|
rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
|
729
|
-
#else
|
730
|
-
#ifndef HAVE_RB_INTERN_STR
|
731
|
-
/* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
|
732
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
|
733
|
-
#else
|
734
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
|
735
|
-
#endif
|
736
|
-
#endif
|
737
726
|
} else {
|
738
727
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
739
728
|
}
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -64,7 +64,10 @@ struct msgpack_unpacker_t {
|
|
64
64
|
|
65
65
|
/* options */
|
66
66
|
bool symbolize_keys;
|
67
|
+
bool freeze;
|
67
68
|
bool allow_unknown_ext;
|
69
|
+
bool optimized_symbol_ext_type;
|
70
|
+
int symbol_ext_type;
|
68
71
|
};
|
69
72
|
|
70
73
|
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
@@ -96,6 +99,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
|
|
96
99
|
uk->symbolize_keys = enable;
|
97
100
|
}
|
98
101
|
|
102
|
+
static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
|
103
|
+
{
|
104
|
+
uk->freeze = enable;
|
105
|
+
}
|
106
|
+
|
99
107
|
static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
|
100
108
|
{
|
101
109
|
uk->allow_unknown_ext = enable;
|
@@ -105,6 +105,9 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
105
105
|
v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
|
106
106
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
107
107
|
|
108
|
+
v = rb_hash_aref(options, ID2SYM(rb_intern("freeze")));
|
109
|
+
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
110
|
+
|
108
111
|
v = rb_hash_aref(options, ID2SYM(rb_intern("allow_unknown_ext")));
|
109
112
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
110
113
|
}
|
@@ -118,6 +121,12 @@ static VALUE Unpacker_symbolized_keys_p(VALUE self)
|
|
118
121
|
return uk->symbolize_keys ? Qtrue : Qfalse;
|
119
122
|
}
|
120
123
|
|
124
|
+
static VALUE Unpacker_freeze_p(VALUE self)
|
125
|
+
{
|
126
|
+
UNPACKER(self, uk);
|
127
|
+
return uk->freeze ? Qtrue : Qfalse;
|
128
|
+
}
|
129
|
+
|
121
130
|
static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
|
122
131
|
{
|
123
132
|
UNPACKER(self, uk);
|
@@ -360,12 +369,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
360
369
|
case 1:
|
361
370
|
/* register_type(0x7f) {|data| block... } */
|
362
371
|
rb_need_block();
|
363
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
364
372
|
proc = rb_block_lambda();
|
365
|
-
#else
|
366
|
-
/* MRI 1.8 */
|
367
|
-
proc = rb_block_proc();
|
368
|
-
#endif
|
369
373
|
arg = proc;
|
370
374
|
ext_module = Qnil;
|
371
375
|
break;
|
@@ -438,6 +442,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
438
442
|
|
439
443
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
440
444
|
rb_define_method(cMessagePack_Unpacker, "symbolize_keys?", Unpacker_symbolized_keys_p, 0);
|
445
|
+
rb_define_method(cMessagePack_Unpacker, "freeze?", Unpacker_freeze_p, 0);
|
441
446
|
rb_define_method(cMessagePack_Unpacker, "allow_unknown_ext?", Unpacker_allow_unknown_ext_p, 0);
|
442
447
|
rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
|
443
448
|
rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
|
data/lib/msgpack/symbol.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
class Symbol
|
2
|
-
|
3
|
-
|
2
|
+
# to_msgpack_ext is supposed to return a binary string.
|
3
|
+
# The canonical way to do it for symbols would be:
|
4
|
+
# [to_s].pack('A*')
|
5
|
+
# However in this instance we can take a shortcut
|
6
|
+
if method_defined?(:name)
|
7
|
+
alias_method :to_msgpack_ext, :name
|
8
|
+
else
|
9
|
+
alias_method :to_msgpack_ext, :to_s
|
4
10
|
end
|
5
11
|
|
6
12
|
def self.from_msgpack_ext(data)
|
7
|
-
|
13
|
+
# from_msgpack_ext is supposed to parse a binary string.
|
14
|
+
# The canonical way to do it for symbols would be:
|
15
|
+
# data.unpack1('A*').to_sym
|
16
|
+
# However in this instance we can take a shortcut
|
17
|
+
data.to_sym
|
8
18
|
end
|
9
|
-
end
|
19
|
+
end
|
data/lib/msgpack/time.rb
CHANGED
data/lib/msgpack/version.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
module MessagePack
|
2
|
-
VERSION = "1.4.
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# * versions/supports of rake-compiler & rake-compiler-dock
|
7
|
-
# https://github.com/rake-compiler/rake-compiler-dock/blob/master/History.md
|
8
|
-
# * update RUBY_CC_VERSION in Rakefile
|
9
|
-
# * check Ruby dependency of released mswin gem details
|
2
|
+
VERSION = "1.4.3"
|
3
|
+
# Note for maintainers:
|
4
|
+
# Don't miss building/releasing the JRuby version (rake buld:java)
|
5
|
+
# See "How to build -java rubygems" in README for more details.
|
10
6
|
end
|
data/lib/msgpack.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require "msgpack/version"
|
2
2
|
|
3
3
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" # This is same with `/java/ =~ RUBY_VERSION`
|
4
|
-
require "java"
|
5
4
|
require "msgpack/msgpack.jar"
|
6
|
-
org.msgpack.jruby.MessagePackLibrary
|
5
|
+
JRuby::Util.load_ext("org.msgpack.jruby.MessagePackLibrary")
|
7
6
|
else
|
8
7
|
require "msgpack/msgpack"
|
9
8
|
end
|
data/msgpack.gemspec
CHANGED
@@ -20,13 +20,11 @@ Gem::Specification.new do |s|
|
|
20
20
|
end
|
21
21
|
s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
|
22
22
|
|
23
|
+
s.required_ruby_version = ">= 2.4"
|
24
|
+
|
23
25
|
s.add_development_dependency 'bundler'
|
24
26
|
s.add_development_dependency 'rake'
|
25
|
-
s.add_development_dependency 'rake-compiler'
|
26
|
-
if /java/ !~ RUBY_PLATFORM
|
27
|
-
# NOTE: rake-compiler-dock SHOULD be updated for new Ruby versions
|
28
|
-
s.add_development_dependency 'rake-compiler-dock', ['~> 1.0']
|
29
|
-
end
|
27
|
+
s.add_development_dependency 'rake-compiler'
|
30
28
|
s.add_development_dependency 'rspec', ['~> 3.3']
|
31
29
|
s.add_development_dependency 'yard'
|
32
30
|
s.add_development_dependency 'json'
|
data/spec/factory_spec.rb
CHANGED
@@ -280,6 +280,23 @@ describe MessagePack::Factory do
|
|
280
280
|
unpacker.feed(packed_symbol).unpack
|
281
281
|
end
|
282
282
|
|
283
|
+
context 'using the optimized symbol unpacker' do
|
284
|
+
before do
|
285
|
+
skip if IS_JRUBY # JRuby implementation doesn't support the optimized symbols unpacker for now
|
286
|
+
subject.register_type(
|
287
|
+
0x00,
|
288
|
+
::Symbol,
|
289
|
+
packer: :to_msgpack_ext,
|
290
|
+
unpacker: :from_msgpack_ext,
|
291
|
+
optimized_symbols_parsing: true,
|
292
|
+
)
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'lets symbols survive a roundtrip' do
|
296
|
+
expect(symbol_after_roundtrip).to be :symbol
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
283
300
|
context 'if no ext type is registered for symbols' do
|
284
301
|
it 'converts symbols to string' do
|
285
302
|
expect(symbol_after_roundtrip).to eq 'symbol'
|
data/spec/msgpack_spec.rb
CHANGED
@@ -115,7 +115,7 @@ describe MessagePack do
|
|
115
115
|
expect { MessagePack.pack(self) }.to raise_error(NoMethodError, /^undefined method `to_msgpack'/)
|
116
116
|
end
|
117
117
|
|
118
|
-
it '
|
118
|
+
it 'raises an error on #unpack with garbage' do
|
119
119
|
skip "but nothing was raised. why?"
|
120
120
|
expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
|
121
121
|
end
|
data/spec/packer_spec.rb
CHANGED
@@ -488,6 +488,24 @@ describe MessagePack::Packer do
|
|
488
488
|
it { is_expected.to eq "\xC7\x0F\x01value_msgpacked" }
|
489
489
|
end
|
490
490
|
|
491
|
+
shared_examples_for 'extension subclasses core type' do |klass|
|
492
|
+
before { stub_const('Value', Class.new(klass)) }
|
493
|
+
let(:object) { Value.new }
|
494
|
+
subject { packer.pack(object).to_s }
|
495
|
+
|
496
|
+
it "defaults to #{klass.name} packer if no extension is present" do
|
497
|
+
expect(subject).to eq(MessagePack.dump(klass.new))
|
498
|
+
end
|
499
|
+
|
500
|
+
it "uses core type extension for #{klass.name}" do
|
501
|
+
packer.register_type(0x01, Value, ->(_) { 'value_msgpacked' })
|
502
|
+
expect(subject).to eq("\xC7\x0F\x01value_msgpacked")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
it_behaves_like 'extension subclasses core type', Hash
|
506
|
+
it_behaves_like 'extension subclasses core type', Array
|
507
|
+
it_behaves_like 'extension subclasses core type', String
|
508
|
+
|
491
509
|
context 'when registering a type for symbols' do
|
492
510
|
before { packer.register_type(0x00, ::Symbol, :to_msgpack_ext) }
|
493
511
|
|
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,16 @@ end
|
|
15
15
|
|
16
16
|
require 'msgpack'
|
17
17
|
|
18
|
+
if GC.respond_to?(:verify_compaction_references)
|
19
|
+
# This method was added in Ruby 3.0.0. Calling it this way asks the GC to
|
20
|
+
# move objects around, helping to find object movement bugs.
|
21
|
+
GC.verify_compaction_references(double_heap: true, toward: :empty)
|
22
|
+
end
|
23
|
+
|
24
|
+
if GC.respond_to?(:auto_compact=)
|
25
|
+
GC.auto_compact = true
|
26
|
+
end
|
27
|
+
|
18
28
|
def java?
|
19
29
|
/java/ =~ RUBY_PLATFORM
|
20
30
|
end
|
@@ -30,6 +40,12 @@ def automatic_string_keys_deduplication?
|
|
30
40
|
x.keys[0].equal?(h.keys[0])
|
31
41
|
end
|
32
42
|
|
43
|
+
def string_deduplication?
|
44
|
+
r1 = rand.to_s
|
45
|
+
r2 = r1.dup
|
46
|
+
(-r1).equal?(-r2)
|
47
|
+
end
|
48
|
+
|
33
49
|
if java?
|
34
50
|
RSpec.configure do |c|
|
35
51
|
c.treat_symbols_as_metadata_keys_with_true_values = true
|