msgpack 1.2.6 → 1.4.4
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 +56 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +4 -1
- data/ChangeLog +59 -0
- data/Gemfile +3 -0
- data/README.md +242 -0
- data/Rakefile +3 -8
- data/doclib/msgpack/factory.rb +1 -0
- data/doclib/msgpack/packer.rb +20 -0
- data/doclib/msgpack/time.rb +22 -0
- data/doclib/msgpack/timestamp.rb +44 -0
- data/doclib/msgpack.rb +2 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +21 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -10
- data/ext/java/org/msgpack/jruby/Encoder.java +38 -19
- 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 +8 -3
- data/ext/java/org/msgpack/jruby/Packer.java +31 -8
- data/ext/java/org/msgpack/jruby/Unpacker.java +40 -27
- data/ext/msgpack/buffer.c +4 -16
- data/ext/msgpack/buffer.h +60 -5
- data/ext/msgpack/compat.h +1 -12
- data/ext/msgpack/extconf.rb +39 -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 +21 -9
- data/ext/msgpack/packer_ext_registry.c +0 -22
- data/ext/msgpack/unpacker.c +41 -49
- data/ext/msgpack/unpacker.h +8 -0
- data/ext/msgpack/unpacker_class.c +23 -13
- data/lib/msgpack/symbol.rb +14 -4
- data/lib/msgpack/time.rb +29 -0
- data/lib/msgpack/timestamp.rb +76 -0
- data/lib/msgpack/version.rb +4 -7
- data/lib/msgpack.rb +8 -10
- data/msgpack.gemspec +3 -7
- data/spec/cruby/buffer_spec.rb +6 -1
- data/spec/factory_spec.rb +17 -0
- data/spec/msgpack_spec.rb +44 -1
- data/spec/packer_spec.rb +54 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/timestamp_spec.rb +161 -0
- data/spec/unpacker_spec.rb +113 -1
- metadata +19 -51
- data/.travis.yml +0 -41
- data/README.rdoc +0 -201
data/ext/msgpack/packer_class.c
CHANGED
@@ -165,6 +165,18 @@ static VALUE Packer_write_string(VALUE self, VALUE obj)
|
|
165
165
|
return self;
|
166
166
|
}
|
167
167
|
|
168
|
+
static VALUE Packer_write_bin(VALUE self, VALUE obj)
|
169
|
+
{
|
170
|
+
PACKER(self, pk);
|
171
|
+
Check_Type(obj, T_STRING);
|
172
|
+
|
173
|
+
VALUE enc = rb_enc_from_encoding(rb_ascii8bit_encoding());
|
174
|
+
obj = rb_str_encode(obj, enc, 0, Qnil);
|
175
|
+
|
176
|
+
msgpack_packer_write_string_value(pk, obj);
|
177
|
+
return self;
|
178
|
+
}
|
179
|
+
|
168
180
|
static VALUE Packer_write_array(VALUE self, VALUE obj)
|
169
181
|
{
|
170
182
|
PACKER(self, pk);
|
@@ -232,6 +244,13 @@ static VALUE Packer_write_map_header(VALUE self, VALUE n)
|
|
232
244
|
return self;
|
233
245
|
}
|
234
246
|
|
247
|
+
static VALUE Packer_write_bin_header(VALUE self, VALUE n)
|
248
|
+
{
|
249
|
+
PACKER(self, pk);
|
250
|
+
msgpack_packer_write_bin_header(pk, NUM2UINT(n));
|
251
|
+
return self;
|
252
|
+
}
|
253
|
+
|
235
254
|
static VALUE Packer_write_float32(VALUE self, VALUE numeric)
|
236
255
|
{
|
237
256
|
if(!rb_obj_is_kind_of(numeric, rb_cNumeric)) {
|
@@ -320,11 +339,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
320
339
|
static VALUE Packer_registered_types_internal(VALUE self)
|
321
340
|
{
|
322
341
|
PACKER(self, pk);
|
323
|
-
#ifdef HAVE_RB_HASH_DUP
|
324
342
|
return rb_hash_dup(pk->ext_registry.hash);
|
325
|
-
#else
|
326
|
-
return rb_funcall(pk->ext_registry.hash, rb_intern("dup"), 0);
|
327
|
-
#endif
|
328
343
|
}
|
329
344
|
|
330
345
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -340,12 +355,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
340
355
|
case 2:
|
341
356
|
/* register_type(0x7f, Time) {|obj| block... } */
|
342
357
|
rb_need_block();
|
343
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
344
358
|
proc = rb_block_lambda();
|
345
|
-
#else
|
346
|
-
/* MRI 1.8 */
|
347
|
-
proc = rb_block_proc();
|
348
|
-
#endif
|
349
359
|
arg = proc;
|
350
360
|
break;
|
351
361
|
case 3:
|
@@ -416,6 +426,7 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
416
426
|
rb_define_method(cMessagePack_Packer, "write_false", Packer_write_false, 0);
|
417
427
|
rb_define_method(cMessagePack_Packer, "write_float", Packer_write_float, 1);
|
418
428
|
rb_define_method(cMessagePack_Packer, "write_string", Packer_write_string, 1);
|
429
|
+
rb_define_method(cMessagePack_Packer, "write_bin", Packer_write_bin, 1);
|
419
430
|
rb_define_method(cMessagePack_Packer, "write_array", Packer_write_array, 1);
|
420
431
|
rb_define_method(cMessagePack_Packer, "write_hash", Packer_write_hash, 1);
|
421
432
|
rb_define_method(cMessagePack_Packer, "write_symbol", Packer_write_symbol, 1);
|
@@ -423,6 +434,7 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
423
434
|
rb_define_method(cMessagePack_Packer, "write_extension", Packer_write_extension, 1);
|
424
435
|
rb_define_method(cMessagePack_Packer, "write_array_header", Packer_write_array_header, 1);
|
425
436
|
rb_define_method(cMessagePack_Packer, "write_map_header", Packer_write_map_header, 1);
|
437
|
+
rb_define_method(cMessagePack_Packer, "write_bin_header", Packer_write_bin_header, 1);
|
426
438
|
rb_define_method(cMessagePack_Packer, "write_ext", Packer_write_ext, 2);
|
427
439
|
rb_define_method(cMessagePack_Packer, "write_float32", Packer_write_float32, 1);
|
428
440
|
rb_define_method(cMessagePack_Packer, "flush", Packer_flush, 0);
|
@@ -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,20 +284,26 @@ 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
|
-
|
303
|
-
|
304
|
-
|
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
|
+
}
|
301
|
+
|
302
|
+
# if !HASH_ASET_DEDUPE
|
303
|
+
if(will_freeze) {
|
304
|
+
rb_obj_freeze(string);
|
305
|
+
}
|
306
|
+
# endif
|
305
307
|
}
|
306
308
|
uk->reading_raw_remaining = 0;
|
307
309
|
return ret;
|
@@ -332,7 +334,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
332
334
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
333
335
|
int count = b & 0x1f;
|
334
336
|
if(count == 0) {
|
335
|
-
return
|
337
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
336
338
|
}
|
337
339
|
/* read_raw_body_begin sets uk->reading_raw */
|
338
340
|
uk->reading_raw_remaining = count;
|
@@ -517,7 +519,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
517
519
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
518
520
|
uint8_t count = cb->u8;
|
519
521
|
if(count == 0) {
|
520
|
-
return
|
522
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
521
523
|
}
|
522
524
|
/* read_raw_body_begin sets uk->reading_raw */
|
523
525
|
uk->reading_raw_remaining = count;
|
@@ -529,7 +531,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
529
531
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
530
532
|
uint16_t count = _msgpack_be16(cb->u16);
|
531
533
|
if(count == 0) {
|
532
|
-
return
|
534
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
533
535
|
}
|
534
536
|
/* read_raw_body_begin sets uk->reading_raw */
|
535
537
|
uk->reading_raw_remaining = count;
|
@@ -541,7 +543,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
541
543
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
542
544
|
uint32_t count = _msgpack_be32(cb->u32);
|
543
545
|
if(count == 0) {
|
544
|
-
return
|
546
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
545
547
|
}
|
546
548
|
/* read_raw_body_begin sets uk->reading_raw */
|
547
549
|
uk->reading_raw_remaining = count;
|
@@ -553,7 +555,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
553
555
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
554
556
|
uint8_t count = cb->u8;
|
555
557
|
if(count == 0) {
|
556
|
-
return
|
558
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
557
559
|
}
|
558
560
|
/* read_raw_body_begin sets uk->reading_raw */
|
559
561
|
uk->reading_raw_remaining = count;
|
@@ -565,7 +567,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
565
567
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
566
568
|
uint16_t count = _msgpack_be16(cb->u16);
|
567
569
|
if(count == 0) {
|
568
|
-
return
|
570
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
569
571
|
}
|
570
572
|
/* read_raw_body_begin sets uk->reading_raw */
|
571
573
|
uk->reading_raw_remaining = count;
|
@@ -577,7 +579,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
577
579
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
578
580
|
uint32_t count = _msgpack_be32(cb->u32);
|
579
581
|
if(count == 0) {
|
580
|
-
return
|
582
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
581
583
|
}
|
582
584
|
/* read_raw_body_begin sets uk->reading_raw */
|
583
585
|
uk->reading_raw_remaining = count;
|
@@ -719,18 +721,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
719
721
|
break;
|
720
722
|
case STACK_TYPE_MAP_VALUE:
|
721
723
|
if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
|
722
|
-
/* here uses
|
723
|
-
#ifdef HAVE_RB_STR_INTERN
|
724
|
-
/* 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 */
|
725
725
|
rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
|
726
|
-
#else
|
727
|
-
#ifndef HAVE_RB_INTERN_STR
|
728
|
-
/* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
|
729
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
|
730
|
-
#else
|
731
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
|
732
|
-
#endif
|
733
|
-
#endif
|
734
726
|
} else {
|
735
727
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
736
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;
|
@@ -77,9 +77,6 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
77
77
|
VALUE v = argv[0];
|
78
78
|
if(rb_type(v) == T_HASH) {
|
79
79
|
options = v;
|
80
|
-
if(rb_type(options) != T_HASH) {
|
81
|
-
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
82
|
-
}
|
83
80
|
} else {
|
84
81
|
io = v;
|
85
82
|
}
|
@@ -108,6 +105,9 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
108
105
|
v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
|
109
106
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
110
107
|
|
108
|
+
v = rb_hash_aref(options, ID2SYM(rb_intern("freeze")));
|
109
|
+
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
110
|
+
|
111
111
|
v = rb_hash_aref(options, ID2SYM(rb_intern("allow_unknown_ext")));
|
112
112
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
113
113
|
}
|
@@ -121,6 +121,12 @@ static VALUE Unpacker_symbolized_keys_p(VALUE self)
|
|
121
121
|
return uk->symbolize_keys ? Qtrue : Qfalse;
|
122
122
|
}
|
123
123
|
|
124
|
+
static VALUE Unpacker_freeze_p(VALUE self)
|
125
|
+
{
|
126
|
+
UNPACKER(self, uk);
|
127
|
+
return uk->freeze ? Qtrue : Qfalse;
|
128
|
+
}
|
129
|
+
|
124
130
|
static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
|
125
131
|
{
|
126
132
|
UNPACKER(self, uk);
|
@@ -256,6 +262,17 @@ static VALUE Unpacker_feed(VALUE self, VALUE data)
|
|
256
262
|
return self;
|
257
263
|
}
|
258
264
|
|
265
|
+
static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
|
266
|
+
{
|
267
|
+
UNPACKER(self, uk);
|
268
|
+
|
269
|
+
StringValue(data);
|
270
|
+
|
271
|
+
msgpack_buffer_append_string_reference(UNPACKER_BUFFER_(uk), data);
|
272
|
+
|
273
|
+
return self;
|
274
|
+
}
|
275
|
+
|
259
276
|
static VALUE Unpacker_each_impl(VALUE self)
|
260
277
|
{
|
261
278
|
UNPACKER(self, uk);
|
@@ -312,8 +329,7 @@ static VALUE Unpacker_feed_each(VALUE self, VALUE data)
|
|
312
329
|
}
|
313
330
|
#endif
|
314
331
|
|
315
|
-
|
316
|
-
Unpacker_feed(self, data);
|
332
|
+
Unpacker_feed_reference(self, data);
|
317
333
|
return Unpacker_each(self);
|
318
334
|
}
|
319
335
|
|
@@ -353,12 +369,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
353
369
|
case 1:
|
354
370
|
/* register_type(0x7f) {|data| block... } */
|
355
371
|
rb_need_block();
|
356
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
357
372
|
proc = rb_block_lambda();
|
358
|
-
#else
|
359
|
-
/* MRI 1.8 */
|
360
|
-
proc = rb_block_proc();
|
361
|
-
#endif
|
362
373
|
arg = proc;
|
363
374
|
ext_module = Qnil;
|
364
375
|
break;
|
@@ -386,9 +397,6 @@ static VALUE Unpacker_full_unpack(VALUE self)
|
|
386
397
|
{
|
387
398
|
UNPACKER(self, uk);
|
388
399
|
|
389
|
-
/* prefer reference than copying; see MessagePack_Unpacker_module_init */
|
390
|
-
msgpack_buffer_set_write_reference_threshold(UNPACKER_BUFFER_(uk), 0);
|
391
|
-
|
392
400
|
int r = msgpack_unpacker_read(uk, 0);
|
393
401
|
if(r < 0) {
|
394
402
|
raise_unpacker_error(r);
|
@@ -434,6 +442,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
434
442
|
|
435
443
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
436
444
|
rb_define_method(cMessagePack_Unpacker, "symbolize_keys?", Unpacker_symbolized_keys_p, 0);
|
445
|
+
rb_define_method(cMessagePack_Unpacker, "freeze?", Unpacker_freeze_p, 0);
|
437
446
|
rb_define_method(cMessagePack_Unpacker, "allow_unknown_ext?", Unpacker_allow_unknown_ext_p, 0);
|
438
447
|
rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
|
439
448
|
rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
|
@@ -444,6 +453,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
444
453
|
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
|
445
454
|
//rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
|
446
455
|
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
|
456
|
+
rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
|
447
457
|
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
|
448
458
|
rb_define_method(cMessagePack_Unpacker, "feed_each", Unpacker_feed_each, 1);
|
449
459
|
rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 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
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# MessagePack extention packer and unpacker for built-in Time class
|
4
|
+
module MessagePack
|
5
|
+
module Time
|
6
|
+
# 3-arg Time.at is available Ruby >= 2.5
|
7
|
+
TIME_AT_3_AVAILABLE = begin
|
8
|
+
!!::Time.at(0, 0, :nanosecond)
|
9
|
+
rescue ArgumentError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
Unpacker = if TIME_AT_3_AVAILABLE
|
14
|
+
lambda do |payload|
|
15
|
+
tv = MessagePack::Timestamp.from_msgpack_ext(payload)
|
16
|
+
::Time.at(tv.sec, tv.nsec, :nanosecond)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
lambda do |payload|
|
20
|
+
tv = MessagePack::Timestamp.from_msgpack_ext(payload)
|
21
|
+
::Time.at(tv.sec, tv.nsec / 1000.0r)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Packer = lambda { |time|
|
26
|
+
MessagePack::Timestamp.to_msgpack_ext(time.tv_sec, time.tv_nsec)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MessagePack
|
4
|
+
class Timestamp # a.k.a. "TimeSpec"
|
5
|
+
# Because the byte-order of MessagePack is big-endian in,
|
6
|
+
# pack() and unpack() specifies ">".
|
7
|
+
# See https://docs.ruby-lang.org/en/trunk/Array.html#method-i-pack for details.
|
8
|
+
|
9
|
+
# The timestamp extension type defined in the MessagePack spec.
|
10
|
+
# See https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type for details.
|
11
|
+
TYPE = -1
|
12
|
+
|
13
|
+
TIMESTAMP32_MAX_SEC = (1 << 32) - 1
|
14
|
+
TIMESTAMP64_MAX_SEC = (1 << 34) - 1
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
attr_reader :sec
|
18
|
+
|
19
|
+
# @return [Integer]
|
20
|
+
attr_reader :nsec
|
21
|
+
|
22
|
+
# @param [Integer] sec
|
23
|
+
# @param [Integer] nsec
|
24
|
+
def initialize(sec, nsec)
|
25
|
+
@sec = sec
|
26
|
+
@nsec = nsec
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.from_msgpack_ext(data)
|
30
|
+
case data.length
|
31
|
+
when 4
|
32
|
+
# timestamp32 (sec: uint32be)
|
33
|
+
sec, = data.unpack('L>')
|
34
|
+
new(sec, 0)
|
35
|
+
when 8
|
36
|
+
# timestamp64 (nsec: uint30be, sec: uint34be)
|
37
|
+
n, s = data.unpack('L>2')
|
38
|
+
sec = ((n & 0b11) << 32) | s
|
39
|
+
nsec = n >> 2
|
40
|
+
new(sec, nsec)
|
41
|
+
when 12
|
42
|
+
# timestam96 (nsec: uint32be, sec: int64be)
|
43
|
+
nsec, sec = data.unpack('L>q>')
|
44
|
+
new(sec, nsec)
|
45
|
+
else
|
46
|
+
raise MalformedFormatError, "Invalid timestamp data size: #{data.length}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.to_msgpack_ext(sec, nsec)
|
51
|
+
if sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC
|
52
|
+
if nsec === 0 && sec <= TIMESTAMP32_MAX_SEC
|
53
|
+
# timestamp32 = (sec: uint32be)
|
54
|
+
[sec].pack('L>')
|
55
|
+
else
|
56
|
+
# timestamp64 (nsec: uint30be, sec: uint34be)
|
57
|
+
nsec30 = nsec << 2
|
58
|
+
sec_high2 = sec >> 32 # high 2 bits (`x & 0b11` is redandunt)
|
59
|
+
sec_low32 = sec & 0xffffffff # low 32 bits
|
60
|
+
[nsec30 | sec_high2, sec_low32].pack('L>2')
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# timestamp96 (nsec: uint32be, sec: int64be)
|
64
|
+
[nsec, sec].pack('L>q>')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_msgpack_ext
|
69
|
+
self.class.to_msgpack_ext(sec, nsec)
|
70
|
+
end
|
71
|
+
|
72
|
+
def ==(other)
|
73
|
+
other.class == self.class && sec == other.sec && nsec == other.nsec
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/msgpack/version.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
module MessagePack
|
2
|
-
VERSION = "1.
|
3
|
-
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# * versions/supports of rake-compiler & rake-compiler-dock
|
7
|
-
# * update RUBY_CC_VERSION in Rakefile
|
8
|
-
# * check Ruby dependency of released mswin gem details
|
2
|
+
VERSION = "1.4.4"
|
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.
|
9
6
|
end
|
data/lib/msgpack.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
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
|
-
|
9
|
-
require "msgpack/#{RUBY_VERSION[/\d+.\d+/]}/msgpack"
|
10
|
-
rescue LoadError
|
11
|
-
require "msgpack/msgpack"
|
12
|
-
end
|
7
|
+
require "msgpack/msgpack"
|
13
8
|
end
|
14
9
|
|
15
10
|
require "msgpack/packer"
|
@@ -17,18 +12,21 @@ require "msgpack/unpacker"
|
|
17
12
|
require "msgpack/factory"
|
18
13
|
require "msgpack/symbol"
|
19
14
|
require "msgpack/core_ext"
|
15
|
+
require "msgpack/timestamp"
|
16
|
+
require "msgpack/time"
|
20
17
|
|
21
18
|
module MessagePack
|
22
19
|
DefaultFactory = MessagePack::Factory.new
|
20
|
+
DEFAULT_EMPTY_PARAMS = {}.freeze
|
23
21
|
|
24
22
|
def load(src, param = nil)
|
25
23
|
unpacker = nil
|
26
24
|
|
27
25
|
if src.is_a? String
|
28
|
-
unpacker = DefaultFactory.unpacker param
|
29
|
-
unpacker.
|
26
|
+
unpacker = DefaultFactory.unpacker param || DEFAULT_EMPTY_PARAMS
|
27
|
+
unpacker.feed_reference src
|
30
28
|
else
|
31
|
-
unpacker = DefaultFactory.unpacker src, param
|
29
|
+
unpacker = DefaultFactory.unpacker src, param || DEFAULT_EMPTY_PARAMS
|
32
30
|
end
|
33
31
|
|
34
32
|
unpacker.full_unpack
|
data/msgpack.gemspec
CHANGED
@@ -10,7 +10,6 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.email = ["frsyuki@gmail.com", "theo@iconara.net", "tagomoris@gmail.com"]
|
11
11
|
s.license = "Apache 2.0"
|
12
12
|
s.homepage = "http://msgpack.org/"
|
13
|
-
s.rubyforge_project = "msgpack"
|
14
13
|
s.require_paths = ["lib"]
|
15
14
|
if /java/ =~ RUBY_PLATFORM
|
16
15
|
s.files = Dir['lib/**/*.rb', 'lib/**/*.jar']
|
@@ -19,15 +18,12 @@ Gem::Specification.new do |s|
|
|
19
18
|
s.files = `git ls-files`.split("\n")
|
20
19
|
s.extensions = ["ext/msgpack/extconf.rb"]
|
21
20
|
end
|
22
|
-
|
21
|
+
|
22
|
+
s.required_ruby_version = ">= 2.4"
|
23
23
|
|
24
24
|
s.add_development_dependency 'bundler'
|
25
25
|
s.add_development_dependency 'rake'
|
26
|
-
s.add_development_dependency 'rake-compiler', ['
|
27
|
-
if /java/ !~ RUBY_PLATFORM
|
28
|
-
# NOTE: rake-compiler-dock SHOULD be updated for new Ruby versions
|
29
|
-
s.add_development_dependency 'rake-compiler-dock', ['~> 0.7.0']
|
30
|
-
end
|
26
|
+
s.add_development_dependency 'rake-compiler', ['>= 1.1.9']
|
31
27
|
s.add_development_dependency 'rspec', ['~> 3.3']
|
32
28
|
s.add_development_dependency 'yard'
|
33
29
|
s.add_development_dependency 'json'
|
data/spec/cruby/buffer_spec.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'random_compat'
|
3
3
|
|
4
|
+
require 'stringio'
|
5
|
+
if defined?(Encoding)
|
6
|
+
Encoding.default_external = 'ASCII-8BIT'
|
7
|
+
end
|
8
|
+
|
4
9
|
describe Buffer do
|
5
10
|
STATIC_EXAMPLES = {}
|
6
11
|
STATIC_EXAMPLES[:empty01] = ''
|
@@ -45,7 +50,7 @@ describe Buffer do
|
|
45
50
|
b.read(n)
|
46
51
|
s.slice!(0, n)
|
47
52
|
end
|
48
|
-
key = :"random#{"%02d"%i}"
|
53
|
+
key = :"random#{"%02d" % i}"
|
49
54
|
cases[key] = b
|
50
55
|
examples[key] = s
|
51
56
|
end
|
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'
|