msgpack 1.4.0.pre1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/ext/msgpack/buffer.h CHANGED
@@ -49,11 +49,11 @@
49
49
 
50
50
  #define NO_MAPPED_STRING ((VALUE)0)
51
51
 
52
- #ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
53
52
  extern int msgpack_rb_encindex_utf8;
54
53
  extern int msgpack_rb_encindex_usascii;
55
54
  extern int msgpack_rb_encindex_ascii8bit;
56
- #endif
55
+
56
+ extern ID s_uminus;
57
57
 
58
58
  struct msgpack_buffer_chunk_t;
59
59
  typedef struct msgpack_buffer_chunk_t msgpack_buffer_chunk_t;
@@ -438,7 +438,7 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
438
438
  return rb_str_substr(b->head->mapped_string, offset, length);
439
439
  }
440
440
 
441
- static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen)
441
+ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool utf8)
442
442
  {
443
443
  #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
444
444
  /* optimize */
@@ -446,16 +446,52 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
446
446
  b->head->mapped_string != NO_MAPPED_STRING &&
447
447
  length >= b->read_reference_threshold) {
448
448
  VALUE result = _msgpack_buffer_refer_head_mapped_string(b, length);
449
+ if (utf8) ENCODING_SET(result, msgpack_rb_encindex_utf8);
449
450
  _msgpack_buffer_consumed(b, length);
450
451
  return result;
451
452
  }
452
453
  #endif
453
454
 
454
- VALUE result = rb_str_new(b->read_buffer, length);
455
+ VALUE result;
456
+
457
+ #ifdef HAVE_RB_ENC_INTERNED_STR
458
+ if (will_be_frozen) {
459
+ result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
460
+ } else {
461
+ if (utf8) {
462
+ result = rb_utf8_str_new(b->read_buffer, length);
463
+ } else {
464
+ result = rb_str_new(b->read_buffer, length);
465
+ }
466
+ }
455
467
  _msgpack_buffer_consumed(b, length);
456
468
  return result;
457
- }
458
469
 
470
+ #else
459
471
 
460
- #endif
472
+ if (utf8) {
473
+ result = rb_utf8_str_new(b->read_buffer, length);
474
+ } else {
475
+ result = rb_str_new(b->read_buffer, length);
476
+ }
477
+
478
+ #if STR_UMINUS_DEDUPE
479
+ if (will_be_frozen) {
480
+ #if STR_UMINUS_DEDUPE_FROZEN
481
+ // Starting from MRI 2.8 it is preferable to freeze the string
482
+ // before deduplication so that it can be interned directly
483
+ // otherwise it would be duplicated first which is wasteful.
484
+ rb_str_freeze(result);
485
+ #endif //STR_UMINUS_DEDUPE_FROZEN
486
+ // MRI 2.5 and older do not deduplicate strings that are already
487
+ // frozen.
488
+ result = rb_funcall(result, s_uminus, 0);
489
+ }
490
+ #endif // STR_UMINUS_DEDUPE
491
+ _msgpack_buffer_consumed(b, length);
492
+ return result;
493
+
494
+ #endif // HAVE_RB_ENC_INTERNED_STR
495
+ }
461
496
 
497
+ #endif
data/ext/msgpack/compat.h CHANGED
@@ -20,6 +20,7 @@
20
20
 
21
21
  #include <stdbool.h>
22
22
  #include "ruby.h"
23
+ #include "ruby/encoding.h"
23
24
 
24
25
  #if defined(HAVE_RUBY_ST_H)
25
26
  # include "ruby/st.h" /* ruby hash on Ruby 1.9 */
@@ -38,18 +39,6 @@
38
39
  # define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
39
40
  #endif
40
41
 
41
- /*
42
- * COMPAT_HAVE_ENCODING
43
- */
44
- #ifdef HAVE_RUBY_ENCODING_H
45
- # include "ruby/encoding.h"
46
- # define COMPAT_HAVE_ENCODING
47
- #endif
48
-
49
- #if defined(__MACRUBY__) /* MacRuby */
50
- # undef COMPAT_HAVE_ENCODING
51
- #endif
52
-
53
42
 
54
43
  /*
55
44
  * define STR_DUP_LIKELY_DOES_COPY
@@ -4,6 +4,7 @@ have_header("ruby/st.h")
4
4
  have_header("st.h")
5
5
  have_func("rb_str_replace", ["ruby.h"])
6
6
  have_func("rb_intern_str", ["ruby.h"])
7
+ have_func("rb_enc_interned_str", "ruby.h")
7
8
  have_func("rb_sym2str", ["ruby.h"])
8
9
  have_func("rb_str_intern", ["ruby.h"])
9
10
  have_func("rb_block_lambda", ["ruby.h"])
@@ -37,6 +38,32 @@ else
37
38
  $CFLAGS << ' -DHASH_ASET_DEDUPE=0 '
38
39
  end
39
40
 
41
+
42
+ # checking if String#-@ (str_uminus) dedupes... '
43
+ begin
44
+ a = -(%w(t e s t).join)
45
+ b = -(%w(t e s t).join)
46
+ if a.equal?(b)
47
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
48
+ else
49
+ $CFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
50
+ end
51
+ rescue NoMethodError
52
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
53
+ end
54
+
55
+ # checking if String#-@ (str_uminus) directly interns frozen strings... '
56
+ begin
57
+ s = rand.to_s.freeze
58
+ if (-s).equal?(s) && (-s.dup).equal?(s)
59
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
60
+ else
61
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
62
+ end
63
+ rescue NoMethodError
64
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
65
+ end
66
+
40
67
  if warnflags = CONFIG['warnflags']
41
68
  warnflags.slice!(/ -Wdeclaration-after-statement/)
42
69
  end
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,10 +440,6 @@ 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)
@@ -142,33 +142,17 @@ 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)
159
- {
160
- #ifdef COMPAT_HAVE_ENCODING
161
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
162
- #endif
163
- return object_complete(uk, str);
164
- }
165
-
166
154
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
167
155
  {
168
- #ifdef COMPAT_HAVE_ENCODING
169
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
170
- #endif
171
-
172
156
  VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
173
157
  if(proc != Qnil) {
174
158
  VALUE obj = rb_funcall(proc, s_call, 1, str);
@@ -271,9 +255,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
271
255
 
272
256
  int ret;
273
257
  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);
258
+ ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
259
+ ret = object_complete(uk, uk->reading_raw);
260
+ } else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
261
+ ret = object_complete(uk, uk->reading_raw);
277
262
  } else {
278
263
  ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
279
264
  }
@@ -290,13 +275,11 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
290
275
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
291
276
  /* don't use zerocopy for hash keys but get a frozen string directly
292
277
  * 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);
278
+ bool will_freeze = uk->freeze || is_reading_map_key(uk);
279
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
295
280
  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);
281
+ if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
282
+ ret = object_complete(uk, string);
300
283
  } else {
301
284
  ret = object_complete_ext(uk, raw_type, string);
302
285
  }
@@ -335,7 +318,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
335
318
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
336
319
  int count = b & 0x1f;
337
320
  if(count == 0) {
338
- return object_complete_string(uk, rb_str_buf_new(0));
321
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
339
322
  }
340
323
  /* read_raw_body_begin sets uk->reading_raw */
341
324
  uk->reading_raw_remaining = count;
@@ -520,7 +503,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
520
503
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
521
504
  uint8_t count = cb->u8;
522
505
  if(count == 0) {
523
- return object_complete_string(uk, rb_str_buf_new(0));
506
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
524
507
  }
525
508
  /* read_raw_body_begin sets uk->reading_raw */
526
509
  uk->reading_raw_remaining = count;
@@ -532,7 +515,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
532
515
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
533
516
  uint16_t count = _msgpack_be16(cb->u16);
534
517
  if(count == 0) {
535
- return object_complete_string(uk, rb_str_buf_new(0));
518
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
536
519
  }
537
520
  /* read_raw_body_begin sets uk->reading_raw */
538
521
  uk->reading_raw_remaining = count;
@@ -544,7 +527,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
544
527
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
545
528
  uint32_t count = _msgpack_be32(cb->u32);
546
529
  if(count == 0) {
547
- return object_complete_string(uk, rb_str_buf_new(0));
530
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
548
531
  }
549
532
  /* read_raw_body_begin sets uk->reading_raw */
550
533
  uk->reading_raw_remaining = count;
@@ -556,7 +539,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
556
539
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
557
540
  uint8_t count = cb->u8;
558
541
  if(count == 0) {
559
- return object_complete_binary(uk, rb_str_buf_new(0));
542
+ return object_complete(uk, rb_str_new_static("", 0));
560
543
  }
561
544
  /* read_raw_body_begin sets uk->reading_raw */
562
545
  uk->reading_raw_remaining = count;
@@ -568,7 +551,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
568
551
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
569
552
  uint16_t count = _msgpack_be16(cb->u16);
570
553
  if(count == 0) {
571
- return object_complete_binary(uk, rb_str_buf_new(0));
554
+ return object_complete(uk, rb_str_new_static("", 0));
572
555
  }
573
556
  /* read_raw_body_begin sets uk->reading_raw */
574
557
  uk->reading_raw_remaining = count;
@@ -580,7 +563,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
580
563
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
581
564
  uint32_t count = _msgpack_be32(cb->u32);
582
565
  if(count == 0) {
583
- return object_complete_binary(uk, rb_str_buf_new(0));
566
+ return object_complete(uk, rb_str_new_static("", 0));
584
567
  }
585
568
  /* read_raw_body_begin sets uk->reading_raw */
586
569
  uk->reading_raw_remaining = count;
@@ -64,6 +64,7 @@ struct msgpack_unpacker_t {
64
64
 
65
65
  /* options */
66
66
  bool symbolize_keys;
67
+ bool freeze;
67
68
  bool allow_unknown_ext;
68
69
  };
69
70
 
@@ -96,6 +97,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
96
97
  uk->symbolize_keys = enable;
97
98
  }
98
99
 
100
+ static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
101
+ {
102
+ uk->freeze = enable;
103
+ }
104
+
99
105
  static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
100
106
  {
101
107
  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);
@@ -438,6 +447,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
438
447
 
439
448
  rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
440
449
  rb_define_method(cMessagePack_Unpacker, "symbolize_keys?", Unpacker_symbolized_keys_p, 0);
450
+ rb_define_method(cMessagePack_Unpacker, "freeze?", Unpacker_freeze_p, 0);
441
451
  rb_define_method(cMessagePack_Unpacker, "allow_unknown_ext?", Unpacker_allow_unknown_ext_p, 0);
442
452
  rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
443
453
  rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
@@ -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.2"
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/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/spec_helper.rb CHANGED
@@ -30,6 +30,12 @@ def automatic_string_keys_deduplication?
30
30
  x.keys[0].equal?(h.keys[0])
31
31
  end
32
32
 
33
+ def string_deduplication?
34
+ r1 = rand.to_s
35
+ r2 = r1.dup
36
+ (-r1).equal?(-r2)
37
+ end
38
+
33
39
  if java?
34
40
  RSpec.configure do |c|
35
41
  c.treat_symbols_as_metadata_keys_with_true_values = true
@@ -18,10 +18,12 @@ describe MessagePack::Unpacker do
18
18
  it 'gets options to specify how to unpack values' do
19
19
  u1 = MessagePack::Unpacker.new
20
20
  u1.symbolize_keys?.should == false
21
+ u1.freeze?.should == false
21
22
  u1.allow_unknown_ext?.should == false
22
23
 
23
- u2 = MessagePack::Unpacker.new(symbolize_keys: true, allow_unknown_ext: true)
24
+ u2 = MessagePack::Unpacker.new(symbolize_keys: true, freeze: true, allow_unknown_ext: true)
24
25
  u2.symbolize_keys?.should == true
26
+ u2.freeze?.should == true
25
27
  u2.allow_unknown_ext?.should == true
26
28
  end
27
29
 
@@ -632,6 +634,14 @@ describe MessagePack::Unpacker do
632
634
  array = ['foo'] * 10_000
633
635
  MessagePack.unpack(MessagePack.pack(array)).size.should == 10_000
634
636
  end
637
+
638
+ it 'preserve string encoding (issue #200)' do
639
+ string = 'a'.force_encoding(Encoding::UTF_8)
640
+ MessagePack.unpack(MessagePack.pack(string)).encoding.should == string.encoding
641
+
642
+ string *= 256
643
+ MessagePack.unpack(MessagePack.pack(string)).encoding.should == string.encoding
644
+ end
635
645
  end
636
646
 
637
647
  context 'extensions' do
@@ -662,6 +672,88 @@ describe MessagePack::Unpacker do
662
672
  end
663
673
  end
664
674
 
675
+ context 'freeze' do
676
+ let :struct do
677
+ {'hello' => 'world', 'nested' => ['object', {'structure' => true}]}
678
+ end
679
+
680
+ let :buffer do
681
+ MessagePack.pack(struct)
682
+ end
683
+
684
+ let :unpacker do
685
+ described_class.new(:freeze => true)
686
+ end
687
+
688
+ it 'can freeze objects when using .unpack' do
689
+ parsed_struct = MessagePack.unpack(buffer, freeze: true)
690
+ parsed_struct.should == struct
691
+
692
+ parsed_struct.should be_frozen
693
+ parsed_struct['hello'].should be_frozen
694
+ parsed_struct['nested'].should be_frozen
695
+ parsed_struct['nested'][0].should be_frozen
696
+ parsed_struct['nested'][1].should be_frozen
697
+
698
+ if string_deduplication?
699
+ parsed_struct.keys[0].should be_equal('hello'.freeze)
700
+ parsed_struct.keys[1].should be_equal('nested'.freeze)
701
+ parsed_struct.values[0].should be_equal('world'.freeze)
702
+ parsed_struct.values[1][0].should be_equal('object'.freeze)
703
+ parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
704
+ end
705
+ end
706
+
707
+ it 'can freeze objects when using #each' do
708
+ objs = []
709
+ unpacker.feed(buffer)
710
+ unpacker.each do |obj|
711
+ objs << obj
712
+ end
713
+
714
+ parsed_struct = objs.first
715
+ parsed_struct.should == struct
716
+
717
+ parsed_struct.should be_frozen
718
+ parsed_struct['hello'].should be_frozen
719
+ parsed_struct['nested'].should be_frozen
720
+ parsed_struct['nested'][0].should be_frozen
721
+ parsed_struct['nested'][1].should be_frozen
722
+
723
+ if string_deduplication?
724
+ parsed_struct.keys[0].should be_equal('hello'.freeze)
725
+ parsed_struct.keys[1].should be_equal('nested'.freeze)
726
+ parsed_struct.values[0].should be_equal('world'.freeze)
727
+ parsed_struct.values[1][0].should be_equal('object'.freeze)
728
+ parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
729
+ end
730
+ end
731
+
732
+ it 'can freeze objects when using #feed_each' do
733
+ objs = []
734
+ unpacker.feed_each(buffer) do |obj|
735
+ objs << obj
736
+ end
737
+
738
+ parsed_struct = objs.first
739
+ parsed_struct.should == struct
740
+
741
+ parsed_struct.should be_frozen
742
+ parsed_struct['hello'].should be_frozen
743
+ parsed_struct['nested'].should be_frozen
744
+ parsed_struct['nested'][0].should be_frozen
745
+ parsed_struct['nested'][1].should be_frozen
746
+
747
+ if string_deduplication?
748
+ parsed_struct.keys[0].should be_equal('hello'.freeze)
749
+ parsed_struct.keys[1].should be_equal('nested'.freeze)
750
+ parsed_struct.values[0].should be_equal('world'.freeze)
751
+ parsed_struct.values[1][0].should be_equal('object'.freeze)
752
+ parsed_struct.values[1][1].keys[0].should be_equal('structure'.freeze)
753
+ end
754
+ end
755
+ end
756
+
665
757
  context 'binary encoding', :encodings do
666
758
  let :buffer do
667
759
  MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})