msgpack 1.5.0 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9e04f0f240684f2b81a5f00f9afd951feac68ee06cf4dd6e229fa8d5925c5b0
4
- data.tar.gz: 8bf61d049bcf041bcff6e33631dbc3a821de096aca8b1c5069478934a49cd2e6
3
+ metadata.gz: 6c335ddbadfa205f9fabd011bdcbe768924a532e762550a8c974035eb2b6ca59
4
+ data.tar.gz: 24abdf9bb3b34484ded41acc0ac4291ba25ee48660cca66968b265453b35ed96
5
5
  SHA512:
6
- metadata.gz: 58acbb7f3c139dfa153b21445242d202335dea3b1dab6f3f8cd6eac9d427122ea6ec9d4629a5f82674dda53fd9f8b546051d704555c1e1db40c566d9cb617ff9
7
- data.tar.gz: cb3ec4aba6ef01722ef39fc3188ed43f1f3305daae900dc7bab2a15ff1e074512f75b482331c9d962f8e9ce258bee93bf2d6dbfb29cd2a0c8abccd3fcff58fd8
6
+ metadata.gz: d0ebbe1cca5508d5a1fe4b28d7558e1cbe35e82bdf3b4596e3998feb86298e4bba718153a275ab808bf83651225f20cea52e1117df816e629cc05fbf2513f53c
7
+ data.tar.gz: 17ed1e47c07f1388a78b844ff2621414531eea6287b020a1568c9f2b6c2d3e8cbacff6e18a00159604fc241676cdd7a1542af4c4a41f1fc0795945912e885d6f
@@ -25,12 +25,12 @@ jobs:
25
25
  bundler-cache: true # 'bundle install' and cache
26
26
  - run: bundle exec rake
27
27
 
28
- jruby:
28
+ other:
29
29
  strategy:
30
30
  fail-fast: false
31
31
  matrix:
32
32
  os: [ubuntu]
33
- ruby: ['jruby-9.2.19.0', 'jruby-9.3.3.0']
33
+ ruby: ['jruby-9.2.19.0', 'jruby-9.3.3.0', 'truffleruby']
34
34
  runs-on: ${{ matrix.os }}-latest
35
35
  steps:
36
36
  - uses: actions/checkout@v2
@@ -38,7 +38,7 @@ jobs:
38
38
  with:
39
39
  ruby-version: ${{ matrix.ruby }}
40
40
  bundler-cache: true # 'bundle install' and cache
41
- - run: bundle exec rake
41
+ - run: bundle exec rake spec
42
42
 
43
43
  head-versions:
44
44
  continue-on-error: true
@@ -46,7 +46,7 @@ jobs:
46
46
  fail-fast: false
47
47
  matrix:
48
48
  os: [ubuntu]
49
- ruby: ['ruby-head', 'jruby-head', 'truffleruby']
49
+ ruby: ['ruby-head', 'jruby-head']
50
50
  runs-on: ${{ matrix.os }}-latest
51
51
  steps:
52
52
  - uses: actions/checkout@v2
@@ -54,4 +54,4 @@ jobs:
54
54
  with:
55
55
  ruby-version: ${{ matrix.ruby }}
56
56
  bundler-cache: true # 'bundle install' and cache
57
- - run: bundle exec rake || echo "failed, but ignore it"
57
+ - run: bundle exec rake spec || echo "failed, but ignore it"
data/ChangeLog CHANGED
@@ -1,3 +1,16 @@
1
+ 2022-05-30 version 1.5.3:
2
+
3
+ * Fix deduplication of empty strings when using the `freeze: true` option.
4
+ * Use `rb_hash_new_capa` when available (Ruby 3.2) for improved performance when parsing large hashes.
5
+
6
+ 2022-05-27 version 1.5.2:
7
+
8
+ * Fix bug about unpacking ext type objects with the recursive option
9
+
10
+ 2022-04-07 version 1.5.1:
11
+
12
+ * Fix bug about packing/unpacking ext type objects with the recursive option
13
+
1
14
  2022-04-06 version 1.5.0:
2
15
 
3
16
  * Add recursive option on Factory#register_type to operate Packer/Unpacker manually
@@ -415,6 +415,7 @@ public class Encoder {
415
415
  if (entry.isRecursive()) {
416
416
  ByteBuffer oldBuffer = buffer;
417
417
  buffer = ByteBuffer.allocate(CACHE_LINE_SIZE - ARRAY_HEADER_SIZE);
418
+ boolean previousRecursiveExtension = recursiveExtension;
418
419
  recursiveExtension = true;
419
420
 
420
421
  ByteList payload;
@@ -423,7 +424,7 @@ public class Encoder {
423
424
  proc.callMethod(runtime.getCurrentContext(), "call", args);
424
425
  payload = new ByteList(buffer.array(), 0, buffer.position(), binaryEncoding, false);
425
426
  } finally {
426
- recursiveExtension = false;
427
+ recursiveExtension = previousRecursiveExtension;
427
428
  buffer = oldBuffer;
428
429
  }
429
430
  appendExt(type, payload);
data/ext/msgpack/buffer.c CHANGED
@@ -300,30 +300,6 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
300
300
  }
301
301
  }
302
302
 
303
- static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
304
- {
305
- VALUE mapped_string = rb_str_dup(string);
306
- ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
307
-
308
- _msgpack_buffer_add_new_chunk(b);
309
-
310
- char* data = RSTRING_PTR(mapped_string);
311
- size_t length = RSTRING_LEN(mapped_string);
312
-
313
- b->tail.first = (char*) data;
314
- b->tail.last = (char*) data + length;
315
- b->tail.mapped_string = mapped_string;
316
- b->tail.mem = NULL;
317
-
318
- /* msgpack_buffer_writable_size should return 0 for mapped chunk */
319
- b->tail_buffer_end = b->tail.last;
320
-
321
- /* consider read_buffer */
322
- if(b->head == &b->tail) {
323
- b->read_buffer = b->tail.first;
324
- }
325
- }
326
-
327
303
  void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
328
304
  {
329
305
  size_t length = RSTRING_LEN(string);
@@ -332,16 +308,9 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
332
308
  msgpack_buffer_flush(b);
333
309
  if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
334
310
  rb_funcall(b->io, b->io_write_all_method, 1, string);
335
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
336
- VALUE s = rb_str_dup(string);
337
- ENCODING_SET(s, msgpack_rb_encindex_ascii8bit);
338
- rb_funcall(b->io, b->io_write_all_method, 1, s);
339
311
  } else {
340
312
  msgpack_buffer_append(b, RSTRING_PTR(string), length);
341
313
  }
342
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
343
- _msgpack_buffer_append_reference(b, string);
344
-
345
314
  } else {
346
315
  msgpack_buffer_append(b, RSTRING_PTR(string), length);
347
316
  }
data/ext/msgpack/buffer.h CHANGED
@@ -49,6 +49,10 @@
49
49
 
50
50
  #define NO_MAPPED_STRING ((VALUE)0)
51
51
 
52
+ #ifndef RB_ENC_INTERNED_STR_NULL_CHECK
53
+ #define RB_ENC_INTERNED_STR_NULL_CHECK 0
54
+ #endif
55
+
52
56
  extern int msgpack_rb_encindex_utf8;
53
57
  extern int msgpack_rb_encindex_usascii;
54
58
  extern int msgpack_rb_encindex_ascii8bit;
@@ -456,7 +460,11 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
456
460
 
457
461
  #ifdef HAVE_RB_ENC_INTERNED_STR
458
462
  if (will_be_frozen) {
459
- result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
463
+ if (RB_ENC_INTERNED_STR_NULL_CHECK && length == 0) {
464
+ result = rb_enc_interned_str("", length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
465
+ } else {
466
+ result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
467
+ }
460
468
  } else {
461
469
  if (utf8) {
462
470
  result = rb_utf8_str_new(b->read_buffer, length);
data/ext/msgpack/compat.h CHANGED
@@ -22,104 +22,5 @@
22
22
  #include "ruby.h"
23
23
  #include "ruby/encoding.h"
24
24
 
25
- #if defined(HAVE_RUBY_ST_H)
26
- # include "ruby/st.h" /* ruby hash on Ruby 1.9 */
27
- #elif defined(HAVE_ST_H)
28
- # include "st.h" /* ruby hash on Ruby 1.8 */
29
- #endif
30
-
31
-
32
- /*
33
- * ZALLOC_N (ruby 2.2 or later)
34
- */
35
- #ifndef RB_ZALLOC_N
36
- # define RB_ZALLOC_N(type,n) ((type*)ruby_xcalloc((size_t)(n),sizeof(type)))
37
- #endif
38
- #ifndef ZALLOC_N
39
- # define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
40
- #endif
41
-
42
-
43
- /*
44
- * define STR_DUP_LIKELY_DOES_COPY
45
- * check rb_str_dup actually copies the string or not
46
- */
47
- #if defined(RUBY_VM) && defined(FL_ALL) && defined(FL_USER1) && defined(FL_USER3) /* MRI 1.9 */
48
- # define STR_DUP_LIKELY_DOES_COPY(str) FL_ALL(str, FL_USER1|FL_USER3) /* same as STR_ASSOC_P(str) */
49
-
50
- #elif defined(FL_TEST) && defined(ELTS_SHARED) /* MRI 1.8 */
51
- # define STR_DUP_LIKELY_DOES_COPY(str) (!FL_TEST(str, ELTS_SHARED))
52
-
53
- //#elif defined(RUBINIUS) || defined(JRUBY) /* Rubinius and JRuby */
54
- #else
55
- # define STR_DUP_LIKELY_DOES_COPY(str) (1)
56
-
57
- #endif
58
-
59
-
60
- /*
61
- * SIZET2NUM
62
- */
63
- #ifndef SIZET2NUM /* MRI 1.8 */
64
- # define SIZET2NUM(v) ULL2NUM(v)
65
- #endif
66
-
67
-
68
- /*
69
- * rb_errinfo()
70
- */
71
- #if defined(RUBY_VM) /* MRI 1.9 */
72
- # define COMPAT_RERAISE rb_exc_raise(rb_errinfo())
73
-
74
- #elif defined(JRUBY) /* JRuby */
75
- # define COMPAT_RERAISE rb_exc_raise(rb_gv_get("$!"))
76
-
77
- #else /* MRI 1.8 and Rubinius */
78
- # define COMPAT_RERAISE rb_exc_raise(ruby_errinfo)
79
- #endif
80
-
81
-
82
- /*
83
- * RBIGNUM_POSITIVE_P
84
- */
85
- #ifndef RBIGNUM_POSITIVE_P
86
- # if defined(RUBINIUS) /* Rubinius <= v1.2.3 */
87
- # define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue)
88
-
89
- # elif defined(JRUBY) /* JRuby */
90
- # define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue)
91
- # define rb_big2ull(b) rb_num2ull(b)
92
- /*#define rb_big2ll(b) rb_num2ll(b)*/
93
-
94
- # else /* MRI 1.8 */
95
- # define RBIGNUM_POSITIVE_P(b) (RBIGNUM(b)->sign)
96
- # endif
97
- #endif
98
-
99
-
100
- /*
101
- * RSTRING_PTR, RSTRING_LEN
102
- */
103
- #ifndef RSTRING_PTR /* MRI 1.8.5 */
104
- # define RSTRING_PTR(s) (RSTRING(s)->ptr)
105
- #endif
106
-
107
- #ifndef RSTRING_LEN /* MRI 1.8.5 */
108
- # define RSTRING_LEN(s) (RSTRING(s)->len)
109
- #endif
110
-
111
-
112
- /*
113
- * RSTRUCT_GET
114
- */
115
- #ifndef RSTRUCT_GET
116
- # ifdef RSTRUCT_PTR /* MRI <= 2.0.0 */
117
- # define RSTRUCT_GET(st, idx) (RSTRUCT_PTR(st)[idx])
118
- # else /* Rubinius */
119
- # define RSTRUCT_GET(st, idx) (rb_struct_aref(st, INT2FIX(idx)))
120
- # endif
121
- #endif
122
-
123
-
124
25
  #endif
125
26
 
@@ -2,7 +2,8 @@ require 'mkmf'
2
2
 
3
3
  have_header("ruby/st.h")
4
4
  have_header("st.h")
5
- have_func("rb_enc_interned_str", "ruby.h")
5
+ have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
+ have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
6
7
 
7
8
  unless RUBY_PLATFORM.include? 'mswin'
8
9
  $CFLAGS << %[ -I.. -Wall -O3 -g -std=gnu99]
@@ -12,14 +13,12 @@ end
12
13
  #$CFLAGS << %[ -DDISABLE_BUFFER_READ_REFERENCE_OPTIMIZE]
13
14
  #$CFLAGS << %[ -DDISABLE_BUFFER_READ_TO_S_OPTIMIZE]
14
15
 
15
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
16
- # msgpack-ruby doesn't modify data came from RSTRING_PTR(str)
17
- $CFLAGS << %[ -DRSTRING_NOT_MODIFIED]
18
- # Rubinius C extensions don't grab GVL while rmem is not thread safe
19
- $CFLAGS << %[ -DDISABLE_RMEM]
16
+ if RUBY_VERSION.start_with?('3.0.')
17
+ # https://bugs.ruby-lang.org/issues/18772
18
+ $CFLAGS << ' -DRB_ENC_INTERNED_STR_NULL_CHECK=1 '
20
19
  end
21
20
 
22
- # checking if Hash#[]= (rb_hash_aset) dedupes string keys
21
+ # checking if Hash#[]= (rb_hash_aset) dedupes string keys (Ruby 2.6+)
23
22
  h = {}
24
23
  x = {}
25
24
  r = rand.to_s
@@ -32,7 +31,7 @@ else
32
31
  end
33
32
 
34
33
 
35
- # checking if String#-@ (str_uminus) dedupes... '
34
+ # checking if String#-@ (str_uminus) dedupes... ' (Ruby 2.5+)
36
35
  begin
37
36
  a = -(%w(t e s t).join)
38
37
  b = -(%w(t e s t).join)
@@ -45,7 +44,7 @@ rescue NoMethodError
45
44
  $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
46
45
  end
47
46
 
48
- # checking if String#-@ (str_uminus) directly interns frozen strings... '
47
+ # checking if String#-@ (str_uminus) directly interns frozen strings... ' (Ruby 3.0+)
49
48
  begin
50
49
  s = rand.to_s.freeze
51
50
  if (-s).equal?(s) && (-s.dup).equal?(s)
@@ -62,4 +61,3 @@ if warnflags = CONFIG['warnflags']
62
61
  end
63
62
 
64
63
  create_makefile('msgpack/msgpack')
65
-
data/ext/msgpack/packer.c CHANGED
@@ -18,24 +18,10 @@
18
18
 
19
19
  #include "packer.h"
20
20
 
21
- #ifdef RUBINIUS
22
- static ID s_to_iter;
23
- static ID s_next;
24
- static ID s_key;
25
- static ID s_value;
26
- #endif
27
-
28
21
  static ID s_call;
29
22
 
30
23
  void msgpack_packer_static_init()
31
24
  {
32
- #ifdef RUBINIUS
33
- s_to_iter = rb_intern("to_iter");
34
- s_next = rb_intern("next");
35
- s_key = rb_intern("key");
36
- s_value = rb_intern("value");
37
- #endif
38
-
39
25
  s_call = rb_intern("call");
40
26
  }
41
27
 
@@ -108,17 +94,7 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
108
94
  unsigned int len32 = (unsigned int)len;
109
95
  msgpack_packer_write_map_header(pk, len32);
110
96
 
111
- #ifdef RUBINIUS
112
- VALUE iter = rb_funcall(v, s_to_iter, 0);
113
- VALUE entry = Qnil;
114
- while(RTEST(entry = rb_funcall(iter, s_next, 1, entry))) {
115
- VALUE key = rb_funcall(entry, s_key, 0);
116
- VALUE val = rb_funcall(entry, s_value, 0);
117
- write_hash_foreach(key, val, (VALUE) pk);
118
- }
119
- #else
120
97
  rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
121
- #endif
122
98
  }
123
99
 
124
100
  struct msgpack_call_proc_args_t;
data/ext/msgpack/packer.h CHANGED
@@ -408,13 +408,7 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
408
408
  {
409
409
  return encindex == msgpack_rb_encindex_utf8
410
410
  || encindex == msgpack_rb_encindex_usascii
411
- #ifdef ENC_CODERANGE_ASCIIONLY
412
- /* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
413
- /* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
414
- /* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
415
- || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
416
- #endif
417
- ;
411
+ || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
418
412
  }
419
413
 
420
414
  static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
@@ -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
@@ -52,6 +59,16 @@ void msgpack_unpacker_static_destroy()
52
59
 
53
60
  #define HEAD_BYTE_REQUIRED 0xc1
54
61
 
62
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
+ #ifdef UNPACKER_STACK_RMEM
64
+ return msgpack_rmem_alloc(&s_stack_rmem);
65
+ /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
66
+ #else
67
+ /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
68
+ return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
69
+ #endif
70
+ }
71
+
55
72
  msgpack_unpacker_t* _msgpack_unpacker_new(void)
56
73
  {
57
74
  msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
@@ -63,26 +80,23 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
63
80
  uk->last_object = Qnil;
64
81
  uk->reading_raw = Qnil;
65
82
 
66
- #ifdef UNPACKER_STACK_RMEM
67
- uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
68
- /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
69
- #else
70
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
71
- uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
72
- #endif
83
+ uk->stack = _msgpack_unpacker_new_stack();
73
84
  uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
74
85
 
75
86
  return uk;
76
87
  }
77
88
 
89
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
90
+ #ifdef UNPACKER_STACK_RMEM
91
+ msgpack_rmem_free(&s_stack_rmem, stack);
92
+ #else
93
+ xfree(stack);
94
+ #endif
95
+ }
96
+
78
97
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
79
98
  {
80
- #ifdef UNPACKER_STACK_RMEM
81
- msgpack_rmem_free(&s_stack_rmem, uk->stack);
82
- #else
83
- xfree(uk->stack);
84
- #endif
85
-
99
+ _msgpack_unpacker_free_stack(uk->stack);
86
100
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
87
101
  }
88
102
 
@@ -295,10 +309,23 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
295
309
  VALUE obj;
296
310
  uk->last_object = Qnil;
297
311
  reset_head_byte(uk);
298
- size_t ext_size = uk->reading_raw_remaining;
299
312
  uk->reading_raw_remaining = 0;
313
+
314
+ msgpack_unpacker_stack_t* stack = uk->stack;
315
+ size_t stack_depth = uk->stack_depth;
316
+ size_t stack_capacity = uk->stack_capacity;
317
+
318
+ uk->stack = _msgpack_unpacker_new_stack();
319
+ uk->stack_depth = 0;
320
+ uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
321
+
300
322
  obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
301
- msgpack_buffer_skip(UNPACKER_BUFFER_(uk), ext_size);
323
+
324
+ _msgpack_unpacker_free_stack(uk->stack);
325
+ uk->stack = stack;
326
+ uk->stack_depth = stack_depth;
327
+ uk->stack_capacity = stack_capacity;
328
+
302
329
  return object_complete(uk, obj);
303
330
  }
304
331
  }
@@ -351,9 +378,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
351
378
 
352
379
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
353
380
  int count = b & 0x1f;
354
- if(count == 0) {
355
- return object_complete(uk, rb_utf8_str_new_static("", 0));
356
- }
357
381
  /* read_raw_body_begin sets uk->reading_raw */
358
382
  uk->reading_raw_remaining = count;
359
383
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -370,7 +394,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
370
394
  if(count == 0) {
371
395
  return object_complete(uk, rb_hash_new());
372
396
  }
373
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
397
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
374
398
 
375
399
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
376
400
  switch(b) {
@@ -536,9 +560,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
536
560
  {
537
561
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
538
562
  uint8_t count = cb->u8;
539
- if(count == 0) {
540
- return object_complete(uk, rb_utf8_str_new_static("", 0));
541
- }
542
563
  /* read_raw_body_begin sets uk->reading_raw */
543
564
  uk->reading_raw_remaining = count;
544
565
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -548,9 +569,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
548
569
  {
549
570
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
550
571
  uint16_t count = _msgpack_be16(cb->u16);
551
- if(count == 0) {
552
- return object_complete(uk, rb_utf8_str_new_static("", 0));
553
- }
554
572
  /* read_raw_body_begin sets uk->reading_raw */
555
573
  uk->reading_raw_remaining = count;
556
574
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -560,9 +578,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
560
578
  {
561
579
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
562
580
  uint32_t count = _msgpack_be32(cb->u32);
563
- if(count == 0) {
564
- return object_complete(uk, rb_utf8_str_new_static("", 0));
565
- }
566
581
  /* read_raw_body_begin sets uk->reading_raw */
567
582
  uk->reading_raw_remaining = count;
568
583
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -572,9 +587,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
572
587
  {
573
588
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
574
589
  uint8_t count = cb->u8;
575
- if(count == 0) {
576
- return object_complete(uk, rb_str_new_static("", 0));
577
- }
578
590
  /* read_raw_body_begin sets uk->reading_raw */
579
591
  uk->reading_raw_remaining = count;
580
592
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -584,9 +596,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
584
596
  {
585
597
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
586
598
  uint16_t count = _msgpack_be16(cb->u16);
587
- if(count == 0) {
588
- return object_complete(uk, rb_str_new_static("", 0));
589
- }
590
599
  /* read_raw_body_begin sets uk->reading_raw */
591
600
  uk->reading_raw_remaining = count;
592
601
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -596,9 +605,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
596
605
  {
597
606
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
598
607
  uint32_t count = _msgpack_be32(cb->u32);
599
- if(count == 0) {
600
- return object_complete(uk, rb_str_new_static("", 0));
601
- }
602
608
  /* read_raw_body_begin sets uk->reading_raw */
603
609
  uk->reading_raw_remaining = count;
604
610
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -631,7 +637,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
631
637
  if(count == 0) {
632
638
  return object_complete(uk, rb_hash_new());
633
639
  }
634
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
640
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
635
641
  }
636
642
 
637
643
  case 0xdf: // map 32
@@ -641,7 +647,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
641
647
  if(count == 0) {
642
648
  return object_complete(uk, rb_hash_new());
643
649
  }
644
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
650
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
645
651
  }
646
652
 
647
653
  default:
@@ -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.0"
2
+ VERSION = "1.5.3"
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/spec/factory_spec.rb CHANGED
@@ -422,6 +422,33 @@ 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
+ ]
431
+ end
432
+
433
+ it 'can be nested' do
434
+ factory = MessagePack::Factory.new
435
+ factory.register_type(
436
+ 0x02,
437
+ Set,
438
+ packer: ->(set, packer) do
439
+ packer.write(set.to_a)
440
+ nil
441
+ end,
442
+ unpacker: ->(unpacker) do
443
+ unpacker.read.to_set
444
+ end,
445
+ recursive: true,
446
+ )
447
+
448
+ expected = Set[1, Set[2, Set[3]]]
449
+ payload = factory.dump(expected)
450
+ expect(payload).to be == "\xC7\v\x02\x92\x01\xC7\x06\x02\x92\x02\xD5\x02\x91\x03".b
451
+ expect(factory.load(factory.dump(expected))).to be == expected
425
452
  end
426
453
  end
427
454
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "set"
1
2
 
2
3
  if ENV['SIMPLE_COV']
3
4
  require 'simplecov'
@@ -19,7 +20,11 @@ require "msgpack/bigint"
19
20
  if GC.respond_to?(:verify_compaction_references)
20
21
  # This method was added in Ruby 3.0.0. Calling it this way asks the GC to
21
22
  # move objects around, helping to find object movement bugs.
22
- 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
23
28
  end
24
29
 
25
30
  if GC.respond_to?(:auto_compact=)
@@ -28,6 +33,8 @@ end
28
33
 
29
34
  IS_JRUBY = RUBY_ENGINE == 'jruby'
30
35
 
36
+ IS_TRUFFLERUBY = RUBY_ENGINE == 'truffleruby'
37
+
31
38
  # checking if Hash#[]= (rb_hash_aset) dedupes string keys
32
39
  def automatic_string_keys_deduplication?
33
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.0
4
+ version: 1.5.3
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-06 00:00:00.000000000 Z
13
+ date: 2022-07-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -231,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
231
  - !ruby/object:Gem::Version
232
232
  version: '0'
233
233
  requirements: []
234
- rubygems_version: 3.3.3
234
+ rubygems_version: 3.1.2
235
235
  signing_key:
236
236
  specification_version: 4
237
237
  summary: MessagePack, a binary-based efficient data interchange format.