msgpack 1.5.0 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
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.