msgpack 1.2.6 → 1.4.4
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/.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'
|