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.
@@ -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
- void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
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
- } else {
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
- msgpack_packer_write_string_value(pk, v);
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
- msgpack_packer_write_array_value(pk, v);
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
- msgpack_packer_write_hash_value(pk, v);
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);
@@ -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
  }
@@ -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 object_complete_string(msgpack_unpacker_t* uk, VALUE str)
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
- #ifdef COMPAT_HAVE_ENCODING
161
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
162
- #endif
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
- #ifdef COMPAT_HAVE_ENCODING
169
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
170
- #endif
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
- ret = object_complete_string(uk, uk->reading_raw);
275
- } else if(uk->reading_raw_type == RAW_TYPE_BINARY) {
276
- ret = object_complete_binary(uk, uk->reading_raw);
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(raw_type == RAW_TYPE_STRING) {
297
- ret = object_complete_string(uk, string);
298
- } else if(raw_type == RAW_TYPE_BINARY) {
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
- ret = object_complete_ext(uk, raw_type, string);
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
- if(will_freeze) {
306
- rb_obj_freeze(string);
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 object_complete_string(uk, rb_str_buf_new(0));
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 object_complete_string(uk, rb_str_buf_new(0));
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 object_complete_string(uk, rb_str_buf_new(0));
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 object_complete_string(uk, rb_str_buf_new(0));
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 object_complete_binary(uk, rb_str_buf_new(0));
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 object_complete_binary(uk, rb_str_buf_new(0));
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 object_complete_binary(uk, rb_str_buf_new(0));
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 rb_intern_str instead of rb_intern so that Ruby VM can GC unused symbols */
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
  }
@@ -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);
@@ -1,9 +1,19 @@
1
1
  class Symbol
2
- def to_msgpack_ext
3
- [to_s].pack('A*')
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
- data.unpack('A*').first.to_sym
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
@@ -18,7 +18,7 @@ module MessagePack
18
18
  else
19
19
  lambda do |payload|
20
20
  tv = MessagePack::Timestamp.from_msgpack_ext(payload)
21
- ::Time.at(tv.sec, tv.nsec / 1000.0)
21
+ ::Time.at(tv.sec, tv.nsec / 1000.0r)
22
22
  end
23
23
  end
24
24
 
@@ -1,10 +1,6 @@
1
1
  module MessagePack
2
- VERSION = "1.4.0.pre1"
3
-
4
- # NOTE for msgpack-ruby maintainer:
5
- # Check these things to release new binaryes for new Ruby versions (especially for Windows):
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.new.load(JRuby.runtime, false)
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', ['~> 1.0']
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 'rasies an error on #unpack with garbage' do
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