msgpack 1.5.1 → 1.5.6

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.
@@ -34,6 +34,13 @@ static ID s_call;
34
34
  static msgpack_rmem_t s_stack_rmem;
35
35
  #endif
36
36
 
37
+ #if !defined(HAVE_RB_HASH_NEW_CAPA)
38
+ static inline VALUE rb_hash_new_capa(long capa)
39
+ {
40
+ return rb_hash_new();
41
+ }
42
+ #endif
43
+
37
44
  void msgpack_unpacker_static_init()
38
45
  {
39
46
  #ifdef UNPACKER_STACK_RMEM
@@ -53,13 +60,16 @@ void msgpack_unpacker_static_destroy()
53
60
  #define HEAD_BYTE_REQUIRED 0xc1
54
61
 
55
62
  static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
+ msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
64
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
56
65
  #ifdef UNPACKER_STACK_RMEM
57
- return msgpack_rmem_alloc(&s_stack_rmem);
66
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
58
67
  /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
59
68
  #else
60
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
61
- return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
69
+ /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
70
+ stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
62
71
  #endif
72
+ return stack;
63
73
  }
64
74
 
65
75
  msgpack_unpacker_t* _msgpack_unpacker_new(void)
@@ -74,17 +84,17 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
74
84
  uk->reading_raw = Qnil;
75
85
 
76
86
  uk->stack = _msgpack_unpacker_new_stack();
77
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
78
87
 
79
88
  return uk;
80
89
  }
81
90
 
82
91
  static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
83
92
  #ifdef UNPACKER_STACK_RMEM
84
- msgpack_rmem_free(&s_stack_rmem, stack);
93
+ msgpack_rmem_free(&s_stack_rmem, stack->data);
85
94
  #else
86
- xfree(stack);
95
+ xfree(stack->data);
87
96
  #endif
97
+ xfree(stack);
88
98
  }
89
99
 
90
100
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
@@ -93,18 +103,24 @@ void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
93
103
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
94
104
  }
95
105
 
106
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
107
+ {
108
+ while (stack) {
109
+ msgpack_unpacker_stack_entry_t* s = stack->data;
110
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
111
+ for(; s < send; s++) {
112
+ rb_gc_mark(s->object);
113
+ rb_gc_mark(s->key);
114
+ }
115
+ stack = stack->parent;
116
+ }
117
+ }
118
+
96
119
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
97
120
  {
98
121
  rb_gc_mark(uk->last_object);
99
122
  rb_gc_mark(uk->reading_raw);
100
-
101
- msgpack_unpacker_stack_t* s = uk->stack;
102
- msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
103
- for(; s < send; s++) {
104
- rb_gc_mark(s->object);
105
- rb_gc_mark(s->key);
106
- }
107
-
123
+ msgpack_unpacker_mark_stack(uk->stack);
108
124
  /* See MessagePack_Buffer_wrap */
109
125
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
110
126
  rb_gc_mark(uk->buffer_ref);
@@ -116,9 +132,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
116
132
 
117
133
  uk->head_byte = HEAD_BYTE_REQUIRED;
118
134
 
119
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
120
- uk->stack_depth = 0;
121
-
135
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
136
+ uk->stack->depth = 0;
122
137
  uk->last_object = Qnil;
123
138
  uk->reading_raw = Qnil;
124
139
  uk->reading_raw_remaining = 0;
@@ -170,6 +185,9 @@ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
170
185
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
171
186
  {
172
187
  if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
188
+ if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
189
+ return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
190
+ }
173
191
  return object_complete_symbol(uk, rb_str_intern(str));
174
192
  }
175
193
 
@@ -191,37 +209,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
191
209
  }
192
210
 
193
211
  /* stack funcs */
194
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
212
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
195
213
  {
196
- return &uk->stack[uk->stack_depth-1];
214
+ return &uk->stack->data[uk->stack->depth-1];
197
215
  }
198
216
 
199
217
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
200
218
  {
201
219
  reset_head_byte(uk);
202
220
 
203
- if(uk->stack_capacity - uk->stack_depth <= 0) {
221
+ if(uk->stack->capacity - uk->stack->depth <= 0) {
204
222
  return PRIMITIVE_STACK_TOO_DEEP;
205
223
  }
206
224
 
207
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
225
+ msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
208
226
  next->count = count;
209
227
  next->type = type;
210
228
  next->object = object;
211
229
  next->key = Qnil;
212
230
 
213
- uk->stack_depth++;
231
+ uk->stack->depth++;
214
232
  return PRIMITIVE_CONTAINER_START;
215
233
  }
216
234
 
217
235
  static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
218
236
  {
219
- return --uk->stack_depth;
237
+ return --uk->stack->depth;
220
238
  }
221
239
 
222
240
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
223
241
  {
224
- return uk->stack_depth == 0;
242
+ return uk->stack->depth == 0;
225
243
  }
226
244
 
227
245
  #ifdef USE_CASE_RANGE
@@ -249,8 +267,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
249
267
 
250
268
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
251
269
  {
252
- if(uk->stack_depth > 0) {
253
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
270
+ if(uk->stack->depth > 0) {
271
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
254
272
  if(top->type == STACK_TYPE_MAP_KEY) {
255
273
  return true;
256
274
  }
@@ -302,25 +320,17 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
302
320
  VALUE obj;
303
321
  uk->last_object = Qnil;
304
322
  reset_head_byte(uk);
305
- size_t ext_size = uk->reading_raw_remaining;
306
323
  uk->reading_raw_remaining = 0;
307
324
 
308
- msgpack_unpacker_stack_t* stack = uk->stack;
309
- size_t stack_depth = uk->stack_depth;
310
- size_t stack_capacity = uk->stack_capacity;
311
-
312
- uk->stack = _msgpack_unpacker_new_stack();
313
- uk->stack_depth = 0;
314
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
325
+ msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
326
+ child_stack->parent = uk->stack;
327
+ uk->stack = child_stack;
315
328
 
316
329
  obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
317
330
 
318
- _msgpack_unpacker_free_stack(uk->stack);
319
- uk->stack = stack;
320
- uk->stack_depth = stack_depth;
321
- uk->stack_capacity = stack_capacity;
331
+ uk->stack = child_stack->parent;
332
+ _msgpack_unpacker_free_stack(child_stack);
322
333
 
323
- msgpack_buffer_skip(UNPACKER_BUFFER_(uk), ext_size);
324
334
  return object_complete(uk, obj);
325
335
  }
326
336
  }
@@ -373,9 +383,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
373
383
 
374
384
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
375
385
  int count = b & 0x1f;
376
- if(count == 0) {
377
- return object_complete(uk, rb_utf8_str_new_static("", 0));
378
- }
379
386
  /* read_raw_body_begin sets uk->reading_raw */
380
387
  uk->reading_raw_remaining = count;
381
388
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -392,7 +399,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
392
399
  if(count == 0) {
393
400
  return object_complete(uk, rb_hash_new());
394
401
  }
395
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
402
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
396
403
 
397
404
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
398
405
  switch(b) {
@@ -475,7 +482,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
475
482
  {
476
483
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
477
484
  uint32_t u32 = _msgpack_be32(cb->u32);
478
- return object_complete(uk, ULONG2NUM((unsigned long)u32));
485
+ return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
479
486
  }
480
487
 
481
488
  case 0xcf: // unsigned int 64
@@ -503,7 +510,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
503
510
  {
504
511
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
505
512
  int32_t i32 = _msgpack_be32(cb->i32);
506
- return object_complete(uk, LONG2NUM((long)i32));
513
+ return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
507
514
  }
508
515
 
509
516
  case 0xd3: // signed int 64
@@ -558,9 +565,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
558
565
  {
559
566
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
560
567
  uint8_t count = cb->u8;
561
- if(count == 0) {
562
- return object_complete(uk, rb_utf8_str_new_static("", 0));
563
- }
564
568
  /* read_raw_body_begin sets uk->reading_raw */
565
569
  uk->reading_raw_remaining = count;
566
570
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -570,9 +574,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
570
574
  {
571
575
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
572
576
  uint16_t count = _msgpack_be16(cb->u16);
573
- if(count == 0) {
574
- return object_complete(uk, rb_utf8_str_new_static("", 0));
575
- }
576
577
  /* read_raw_body_begin sets uk->reading_raw */
577
578
  uk->reading_raw_remaining = count;
578
579
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -582,9 +583,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
582
583
  {
583
584
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
584
585
  uint32_t count = _msgpack_be32(cb->u32);
585
- if(count == 0) {
586
- return object_complete(uk, rb_utf8_str_new_static("", 0));
587
- }
588
586
  /* read_raw_body_begin sets uk->reading_raw */
589
587
  uk->reading_raw_remaining = count;
590
588
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -594,9 +592,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
594
592
  {
595
593
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
596
594
  uint8_t count = cb->u8;
597
- if(count == 0) {
598
- return object_complete(uk, rb_str_new_static("", 0));
599
- }
600
595
  /* read_raw_body_begin sets uk->reading_raw */
601
596
  uk->reading_raw_remaining = count;
602
597
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -606,9 +601,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
606
601
  {
607
602
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
608
603
  uint16_t count = _msgpack_be16(cb->u16);
609
- if(count == 0) {
610
- return object_complete(uk, rb_str_new_static("", 0));
611
- }
612
604
  /* read_raw_body_begin sets uk->reading_raw */
613
605
  uk->reading_raw_remaining = count;
614
606
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -618,9 +610,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
618
610
  {
619
611
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
620
612
  uint32_t count = _msgpack_be32(cb->u32);
621
- if(count == 0) {
622
- return object_complete(uk, rb_str_new_static("", 0));
623
- }
624
613
  /* read_raw_body_begin sets uk->reading_raw */
625
614
  uk->reading_raw_remaining = count;
626
615
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -653,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
653
642
  if(count == 0) {
654
643
  return object_complete(uk, rb_hash_new());
655
644
  }
656
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
645
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
657
646
  }
658
647
 
659
648
  case 0xdf: // map 32
@@ -663,7 +652,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
663
652
  if(count == 0) {
664
653
  return object_complete(uk, rb_hash_new());
665
654
  }
666
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
655
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
667
656
  }
668
657
 
669
658
  default:
@@ -750,7 +739,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
750
739
 
751
740
  container_completed:
752
741
  {
753
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
742
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
754
743
  switch(top->type) {
755
744
  case STACK_TYPE_ARRAY:
756
745
  rb_ary_push(top->object, uk->last_object);
@@ -800,7 +789,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
800
789
 
801
790
  container_completed:
802
791
  {
803
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
792
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
804
793
 
805
794
  /* this section optimized out */
806
795
  // TODO object_complete still creates objects which should be optimized out
@@ -27,6 +27,7 @@
27
27
 
28
28
  struct msgpack_unpacker_t;
29
29
  typedef struct msgpack_unpacker_t msgpack_unpacker_t;
30
+ typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
30
31
 
31
32
  enum stack_type_t {
32
33
  STACK_TYPE_ARRAY,
@@ -39,19 +40,22 @@ typedef struct {
39
40
  enum stack_type_t type;
40
41
  VALUE object;
41
42
  VALUE key;
42
- } msgpack_unpacker_stack_t;
43
+ } msgpack_unpacker_stack_entry_t;
44
+
45
+ struct msgpack_unpacker_stack_t {
46
+ size_t depth;
47
+ size_t capacity;
48
+ msgpack_unpacker_stack_entry_t *data;
49
+ msgpack_unpacker_stack_t *parent;
50
+ };
43
51
 
44
52
  #define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
45
53
 
46
54
  struct msgpack_unpacker_t {
47
55
  msgpack_buffer_t buffer;
48
-
56
+ msgpack_unpacker_stack_t *stack;
49
57
  unsigned int head_byte;
50
58
 
51
- msgpack_unpacker_stack_t* stack;
52
- size_t stack_depth;
53
- size_t stack_capacity;
54
-
55
59
  VALUE last_object;
56
60
 
57
61
  VALUE reading_raw;
@@ -209,7 +209,7 @@ static VALUE Unpacker_read_array_header(VALUE self)
209
209
  raise_unpacker_error(r);
210
210
  }
211
211
 
212
- return ULONG2NUM(size);
212
+ return ULONG2NUM(size); // long at least 32 bits
213
213
  }
214
214
 
215
215
  static VALUE Unpacker_read_map_header(VALUE self)
@@ -222,7 +222,7 @@ static VALUE Unpacker_read_map_header(VALUE self)
222
222
  raise_unpacker_error((int)r);
223
223
  }
224
224
 
225
- return ULONG2NUM(size);
225
+ return ULONG2NUM(size); // long at least 32 bits
226
226
  }
227
227
 
228
228
 
@@ -450,4 +450,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
450
450
 
451
451
  rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
452
452
  }
453
-
@@ -1,5 +1,5 @@
1
1
  module MessagePack
2
- VERSION = "1.5.1"
2
+ VERSION = "1.5.6"
3
3
  # Note for maintainers:
4
4
  # Don't miss building/releasing the JRuby version (rake buld:java)
5
5
  # See "How to build -java rubygems" in README for more details.
data/msgpack.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
27
27
  s.add_development_dependency 'rspec', ['~> 3.3']
28
28
  s.add_development_dependency 'yard'
29
29
  s.add_development_dependency 'json'
30
+ s.add_development_dependency 'benchmark-ips', ['~> 2.10.0']
30
31
  end
data/spec/factory_spec.rb CHANGED
@@ -422,6 +422,12 @@ describe MessagePack::Factory do
422
422
  MessagePack::ExtensionValue.new(1, factory.dump(x: 1, y: 2, z: 3)),
423
423
  3,
424
424
  ]
425
+
426
+ expect(factory.load(payload)).to be == [
427
+ 1,
428
+ Point.new(1, 2, 3),
429
+ 3,
430
+ ]
425
431
  end
426
432
 
427
433
  it 'can be nested' do
@@ -468,6 +474,10 @@ describe MessagePack::Factory do
468
474
  expect(roundtrip(:symbol)).to be :symbol
469
475
  end
470
476
 
477
+ it 'works with empty symbol' do
478
+ expect(roundtrip(:"")).to be :""
479
+ end
480
+
471
481
  it 'preserves encoding for ASCII symbols' do
472
482
  expect(:symbol.encoding).to be Encoding::US_ASCII
473
483
  expect(roundtrip(:symbol)).to be :symbol
@@ -577,6 +587,30 @@ describe MessagePack::Factory do
577
587
  GC.stress = false
578
588
  end
579
589
  end
590
+
591
+ it 'does not crash in recursive extensions' do
592
+ my_hash_type = Class.new(Hash)
593
+ factory = MessagePack::Factory.new
594
+ factory.register_type(7,
595
+ my_hash_type,
596
+ packer: ->(value, packer) do
597
+ packer.write(value.to_h)
598
+ end,
599
+ unpacker: ->(unpacker) { my_hash_type.new(unpacker.read) },
600
+ recursive: true,
601
+ )
602
+
603
+ payload = factory.dump(
604
+ [my_hash_type.new]
605
+ )
606
+
607
+ begin
608
+ GC.stress = true
609
+ factory.load(payload)
610
+ ensure
611
+ GC.stress = false
612
+ end
613
+ end
580
614
  end
581
615
 
582
616
  describe 'DefaultFactory' do
data/spec/spec_helper.rb CHANGED
@@ -20,7 +20,11 @@ require "msgpack/bigint"
20
20
  if GC.respond_to?(:verify_compaction_references)
21
21
  # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
22
22
  # move objects around, helping to find object movement bugs.
23
- GC.verify_compaction_references(double_heap: true, toward: :empty)
23
+ begin
24
+ GC.verify_compaction_references(double_heap: true, toward: :empty)
25
+ rescue NotImplementedError
26
+ # Some platforms don't support compaction
27
+ end
24
28
  end
25
29
 
26
30
  if GC.respond_to?(:auto_compact=)
@@ -29,6 +33,8 @@ end
29
33
 
30
34
  IS_JRUBY = RUBY_ENGINE == 'jruby'
31
35
 
36
+ IS_TRUFFLERUBY = RUBY_ENGINE == 'truffleruby'
37
+
32
38
  # checking if Hash#[]= (rb_hash_aset) dedupes string keys
33
39
  def automatic_string_keys_deduplication?
34
40
  h = {}
@@ -87,14 +87,14 @@ describe MessagePack::Timestamp do
87
87
 
88
88
  let(:time96_min) { Time.at(-2**63).utc }
89
89
  it 'is serialized into timestamp96' do
90
- skip if IS_JRUBY # JRuby cannot handle numerics larger than long
90
+ skip if IS_JRUBY || IS_TRUFFLERUBY # JRuby and TruffleRuby both use underlying Java time classes that do not support |year| >= 1 billion
91
91
  expect(factory.pack(time96_min).size).to be 15
92
92
  expect(factory.unpack(factory.pack(time96_min)).utc).to eq(time96_min)
93
93
  end
94
94
 
95
95
  let(:time96_max) { Time.at(2**63 - 1).utc }
96
96
  it 'is serialized into timestamp96' do
97
- skip if IS_JRUBY # JRuby cannot handle numerics larger than long
97
+ skip if IS_JRUBY || IS_TRUFFLERUBY # JRuby and TruffleRuby both use underlying Java time classes that do not support |year| >= 1 billion
98
98
  expect(factory.pack(time96_max).size).to be 15
99
99
  expect(factory.unpack(factory.pack(time96_max)).utc).to eq(time96_max)
100
100
  end
@@ -707,6 +707,18 @@ describe MessagePack::Unpacker do
707
707
  described_class.new(:freeze => true)
708
708
  end
709
709
 
710
+ if (-"test").equal?(-"test") # RUBY_VERSION >= "2.5"
711
+ it 'dedups strings' do
712
+ interned_str = -"test"
713
+ roundtrip = MessagePack.unpack(MessagePack.pack(interned_str), freeze: true)
714
+ expect(roundtrip).to be interned_str
715
+
716
+ interned_str = -""
717
+ roundtrip = MessagePack.unpack(MessagePack.pack(interned_str), freeze: true)
718
+ expect(roundtrip).to be interned_str
719
+ end
720
+ end
721
+
710
722
  it 'can freeze objects when using .unpack' do
711
723
  parsed_struct = MessagePack.unpack(buffer, freeze: true)
712
724
  parsed_struct.should == struct
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msgpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-04-07 00:00:00.000000000 Z
13
+ date: 2022-08-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -96,6 +96,20 @@ dependencies:
96
96
  - - ">="
97
97
  - !ruby/object:Gem::Version
98
98
  version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: benchmark-ips
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 2.10.0
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: 2.10.0
99
113
  description: MessagePack is a binary-based efficient object serialization library.
100
114
  It enables to exchange structured objects between many languages like JSON. But
101
115
  unlike JSON, it is very fast and small.
@@ -117,16 +131,7 @@ files:
117
131
  - README.md
118
132
  - Rakefile
119
133
  - appveyor.yml
120
- - bench/pack.rb
121
- - bench/pack_log.rb
122
- - bench/pack_log_long.rb
123
- - bench/pack_symbols.rb
124
- - bench/run.sh
125
- - bench/run_long.sh
126
- - bench/run_symbols.sh
127
- - bench/unpack.rb
128
- - bench/unpack_log.rb
129
- - bench/unpack_log_long.rb
134
+ - bench/bench.rb
130
135
  - doclib/msgpack.rb
131
136
  - doclib/msgpack/buffer.rb
132
137
  - doclib/msgpack/core_ext.rb
@@ -231,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
236
  - !ruby/object:Gem::Version
232
237
  version: '0'
233
238
  requirements: []
234
- rubygems_version: 3.3.3
239
+ rubygems_version: 3.1.2
235
240
  signing_key:
236
241
  specification_version: 4
237
242
  summary: MessagePack, a binary-based efficient data interchange format.
data/bench/pack.rb DELETED
@@ -1,23 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data = { 'hello' => 'world', 'nested' => ['structure', {value: 42}] }
5
- data_sym = { hello: 'world', nested: ['structure', {value: 42}] }
6
-
7
- data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
8
-
9
- Viiite.bench do |b|
10
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
11
- b.report(:strings) do
12
- runs.times do
13
- MessagePack.pack(data)
14
- end
15
- end
16
-
17
- b.report(:symbols) do
18
- runs.times do
19
- MessagePack.pack(data_sym)
20
- end
21
- end
22
- end
23
- end
data/bench/pack_log.rb DELETED
@@ -1,33 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data_plain = { 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' }
5
- data_structure = {
6
- 'remote_host' => '127.0.0.1',
7
- 'remote_user' => '-',
8
- 'date' => '10/Oct/2000:13:55:36 -0700',
9
- 'request' => 'GET /apache_pb.gif HTTP/1.0',
10
- 'method' => 'GET',
11
- 'path' => '/apache_pb.gif',
12
- 'protocol' => 'HTTP/1.0',
13
- 'status' => 200,
14
- 'bytes' => 2326,
15
- 'referer' => 'http://www.example.com/start.html',
16
- 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
17
- }
18
-
19
- Viiite.bench do |b|
20
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
21
- b.report(:plain) do
22
- runs.times do
23
- MessagePack.pack(data_plain)
24
- end
25
- end
26
-
27
- b.report(:structure) do
28
- runs.times do
29
- MessagePack.pack(data_structure)
30
- end
31
- end
32
- end
33
- end