msgpack 1.4.5 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +5 -5
  3. data/ChangeLog +32 -0
  4. data/README.md +25 -1
  5. data/bench/bench.rb +78 -0
  6. data/doclib/msgpack/factory.rb +45 -2
  7. data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
  8. data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
  9. data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
  10. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +24 -31
  11. data/ext/java/org/msgpack/jruby/Factory.java +40 -5
  12. data/ext/java/org/msgpack/jruby/Packer.java +21 -11
  13. data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
  14. data/ext/msgpack/buffer.c +9 -36
  15. data/ext/msgpack/buffer.h +9 -1
  16. data/ext/msgpack/buffer_class.c +18 -9
  17. data/ext/msgpack/compat.h +0 -99
  18. data/ext/msgpack/extconf.rb +9 -11
  19. data/ext/msgpack/factory_class.c +62 -5
  20. data/ext/msgpack/packer.c +42 -29
  21. data/ext/msgpack/packer.h +25 -7
  22. data/ext/msgpack/packer_class.c +23 -20
  23. data/ext/msgpack/packer_ext_registry.c +13 -4
  24. data/ext/msgpack/packer_ext_registry.h +10 -5
  25. data/ext/msgpack/unpacker.c +99 -68
  26. data/ext/msgpack/unpacker.h +10 -6
  27. data/ext/msgpack/unpacker_class.c +16 -8
  28. data/ext/msgpack/unpacker_ext_registry.c +3 -2
  29. data/ext/msgpack/unpacker_ext_registry.h +5 -2
  30. data/lib/msgpack/bigint.rb +69 -0
  31. data/lib/msgpack/factory.rb +103 -0
  32. data/lib/msgpack/version.rb +1 -1
  33. data/lib/msgpack.rb +4 -5
  34. data/msgpack.gemspec +1 -0
  35. data/spec/bigint_spec.rb +26 -0
  36. data/spec/factory_spec.rb +248 -0
  37. data/spec/spec_helper.rb +9 -1
  38. data/spec/timestamp_spec.rb +2 -2
  39. data/spec/unpacker_spec.rb +12 -0
  40. metadata +20 -13
  41. data/bench/pack.rb +0 -23
  42. data/bench/pack_log.rb +0 -33
  43. data/bench/pack_log_long.rb +0 -65
  44. data/bench/pack_symbols.rb +0 -28
  45. data/bench/run.sh +0 -14
  46. data/bench/run_long.sh +0 -35
  47. data/bench/run_symbols.sh +0 -26
  48. data/bench/unpack.rb +0 -21
  49. data/bench/unpack_log.rb +0 -34
  50. data/bench/unpack_log_long.rb +0 -67
@@ -31,6 +31,7 @@ typedef struct msgpack_factory_t msgpack_factory_t;
31
31
  struct msgpack_factory_t {
32
32
  msgpack_packer_ext_registry_t pkrg;
33
33
  msgpack_unpacker_ext_registry_t *ukrg;
34
+ bool has_bigint_ext_type;
34
35
  bool has_symbol_ext_type;
35
36
  bool optimized_symbol_ext_type;
36
37
  int symbol_ext_type;
@@ -87,6 +88,41 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
87
88
  return Qnil;
88
89
  }
89
90
 
91
+ static VALUE Factory_dup(VALUE self)
92
+ {
93
+ VALUE clone = Factory_alloc(rb_obj_class(self));
94
+
95
+ FACTORY(self, fc);
96
+ FACTORY(clone, cloned_fc);
97
+
98
+ cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
99
+ cloned_fc->pkrg = fc->pkrg;
100
+ msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
101
+ msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
102
+
103
+ return clone;
104
+ }
105
+
106
+ static VALUE Factory_freeze(VALUE self) {
107
+ if(!rb_obj_frozen_p(self)) {
108
+ FACTORY(self, fc);
109
+
110
+ if (RTEST(fc->pkrg.hash)) {
111
+ rb_hash_freeze(fc->pkrg.hash);
112
+ if (!RTEST(fc->pkrg.cache)) {
113
+ // If the factory is frozen, we can safely share the packer cache between
114
+ // all packers. So we eagerly create it now so it's available when #packer
115
+ // is called.
116
+ fc->pkrg.cache = rb_hash_new();
117
+ }
118
+ }
119
+
120
+ rb_obj_freeze(self);
121
+ }
122
+
123
+ return self;
124
+ }
125
+
90
126
  VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
91
127
  {
92
128
  FACTORY(self, fc);
@@ -99,6 +135,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
99
135
 
100
136
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
101
137
  msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
138
+ pk->has_bigint_ext_type = fc->has_bigint_ext_type;
102
139
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
103
140
 
104
141
  return packer;
@@ -145,6 +182,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
145
182
  FACTORY(self, fc);
146
183
 
147
184
  int ext_type;
185
+ int flags = 0;
148
186
  VALUE ext_module;
149
187
  VALUE options = Qnil;
150
188
  VALUE packer_arg, unpacker_arg;
@@ -173,6 +211,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
173
211
  rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
174
212
  }
175
213
 
214
+ if (options != Qnil) {
215
+ Check_Type(options, T_HASH);
216
+ }
217
+
176
218
  ext_type = NUM2INT(argv[0]);
177
219
  if(ext_type < -128 || ext_type > 127) {
178
220
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
@@ -200,16 +242,29 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
200
242
  }
201
243
  }
202
244
 
203
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, packer_proc, packer_arg);
204
-
205
- if (ext_module == rb_cSymbol) {
245
+ if(ext_module == rb_cSymbol) {
206
246
  fc->has_symbol_ext_type = true;
207
- if(RB_TEST(options) && RB_TEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
247
+ if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
208
248
  fc->optimized_symbol_ext_type = true;
209
249
  }
210
250
  }
211
251
 
212
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, unpacker_proc, unpacker_arg);
252
+ if(RTEST(options)) {
253
+ if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("oversized_integer_extension"))))) {
254
+ if(ext_module == rb_cInteger) {
255
+ fc->has_bigint_ext_type = true;
256
+ } else {
257
+ rb_raise(rb_eArgError, "oversized_integer_extension: true is only for Integer class");
258
+ }
259
+ }
260
+
261
+ if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("recursive"))))) {
262
+ flags |= MSGPACK_EXT_RECURSIVE;
263
+ }
264
+ }
265
+
266
+ msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
267
+ msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
213
268
 
214
269
  return Qnil;
215
270
  }
@@ -221,6 +276,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
221
276
  rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
222
277
 
223
278
  rb_define_method(cMessagePack_Factory, "initialize", Factory_initialize, -1);
279
+ rb_define_method(cMessagePack_Factory, "dup", Factory_dup, 0);
280
+ rb_define_method(cMessagePack_Factory, "freeze", Factory_freeze, 0);
224
281
 
225
282
  rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
226
283
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
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,32 +94,59 @@ 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
98
+ }
99
+
100
+ struct msgpack_call_proc_args_t;
101
+ typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
102
+ struct msgpack_call_proc_args_t {
103
+ VALUE proc;
104
+ VALUE arg;
105
+ VALUE packer;
106
+ };
107
+
108
+ VALUE msgpack_packer_try_calling_proc(VALUE value)
109
+ {
110
+ msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
111
+ return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
122
112
  }
123
113
 
124
114
  bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
125
115
  {
126
- int ext_type;
116
+ int ext_type, ext_flags;
117
+
118
+ VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
127
119
 
128
- VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type);
120
+ if(proc == Qnil) {
121
+ return false;
122
+ }
129
123
 
130
- if(proc != Qnil) {
124
+ if(ext_flags & MSGPACK_EXT_RECURSIVE) {
125
+ msgpack_buffer_t parent_buffer = pk->buffer;
126
+ msgpack_buffer_init(PACKER_BUFFER_(pk));
127
+
128
+ int exception_occured = 0;
129
+ msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
130
+ rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
131
+
132
+ if (exception_occured) {
133
+ msgpack_buffer_destroy(PACKER_BUFFER_(pk));
134
+ pk->buffer = parent_buffer;
135
+ rb_jump_tag(exception_occured); // re-raise the exception
136
+ } else {
137
+ VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
138
+ StringValue(payload);
139
+ msgpack_buffer_destroy(PACKER_BUFFER_(pk));
140
+ pk->buffer = parent_buffer;
141
+ msgpack_packer_write_ext(pk, ext_type, payload);
142
+ }
143
+ } else {
131
144
  VALUE payload = rb_funcall(proc, s_call, 1, v);
132
145
  StringValue(payload);
133
146
  msgpack_packer_write_ext(pk, ext_type, payload);
134
- return true;
135
147
  }
136
- return false;
148
+
149
+ return true;
137
150
  }
138
151
 
139
152
  void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
data/ext/msgpack/packer.h CHANGED
@@ -32,6 +32,7 @@ struct msgpack_packer_t {
32
32
  msgpack_buffer_t buffer;
33
33
 
34
34
  bool compatibility_mode;
35
+ bool has_bigint_ext_type;
35
36
  bool has_symbol_ext_type;
36
37
 
37
38
  ID to_msgpack_method;
@@ -56,6 +57,8 @@ void msgpack_packer_destroy(msgpack_packer_t* pk);
56
57
 
57
58
  void msgpack_packer_mark(msgpack_packer_t* pk);
58
59
 
60
+ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v);
61
+
59
62
  static inline void msgpack_packer_set_to_msgpack_method(msgpack_packer_t* pk,
60
63
  ID to_msgpack_method, VALUE to_msgpack_arg)
61
64
  {
@@ -405,13 +408,7 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
405
408
  {
406
409
  return encindex == msgpack_rb_encindex_utf8
407
410
  || encindex == msgpack_rb_encindex_usascii
408
- #ifdef ENC_CODERANGE_ASCIIONLY
409
- /* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
410
- /* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
411
- /* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
412
- || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
413
- #endif
414
- ;
411
+ || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
415
412
  }
416
413
 
417
414
  static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
@@ -469,9 +466,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
469
466
 
470
467
  static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
471
468
  {
469
+ int leading_zero_bits;
470
+ size_t required_size = rb_absint_size(v, &leading_zero_bits);
471
+
472
472
  if(RBIGNUM_POSITIVE_P(v)) {
473
+ if(required_size > 8 && pk->has_bigint_ext_type) {
474
+ if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
475
+ return;
476
+ }
477
+ // if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
478
+ }
479
+
473
480
  msgpack_packer_write_u64(pk, rb_big2ull(v));
474
481
  } else {
482
+ if(leading_zero_bits == 0) {
483
+ required_size += 1;
484
+ }
485
+
486
+ if(required_size > 8 && pk->has_bigint_ext_type) {
487
+ if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
488
+ return;
489
+ }
490
+ // if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
491
+ }
492
+
475
493
  msgpack_packer_write_long_long(pk, rb_big2ll(v));
476
494
  }
477
495
  }
@@ -28,6 +28,8 @@ VALUE cMessagePack_Packer;
28
28
  static ID s_to_msgpack;
29
29
  static ID s_write;
30
30
 
31
+ static VALUE sym_compatibility_mode;
32
+
31
33
  //static VALUE s_packer_value;
32
34
  //static msgpack_packer_t* s_packer;
33
35
 
@@ -68,29 +70,28 @@ VALUE MessagePack_Packer_alloc(VALUE klass)
68
70
 
69
71
  VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
70
72
  {
73
+ if(argc > 2) {
74
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
75
+ }
76
+
71
77
  VALUE io = Qnil;
72
78
  VALUE options = Qnil;
73
79
 
74
- if(argc == 0 || (argc == 1 && argv[0] == Qnil)) {
75
- /* Qnil */
76
-
77
- } else if(argc == 1) {
78
- VALUE v = argv[0];
79
- if(rb_type(v) == T_HASH) {
80
- options = v;
81
- } else {
82
- io = v;
83
- }
84
-
85
- } else if(argc == 2) {
80
+ if(argc >= 1) {
86
81
  io = argv[0];
82
+ }
83
+
84
+ if(argc == 2) {
87
85
  options = argv[1];
88
- if(rb_type(options) != T_HASH) {
89
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
90
- }
86
+ }
91
87
 
92
- } else {
93
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
88
+ if (options == Qnil && rb_type(io) == T_HASH) {
89
+ options = io;
90
+ io = Qnil;
91
+ }
92
+
93
+ if(options != Qnil) {
94
+ Check_Type(options, T_HASH);
94
95
  }
95
96
 
96
97
  PACKER(self, pk);
@@ -103,7 +104,7 @@ VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
103
104
  if(options != Qnil) {
104
105
  VALUE v;
105
106
 
106
- v = rb_hash_aref(options, ID2SYM(rb_intern("compatibility_mode")));
107
+ v = rb_hash_aref(options, sym_compatibility_mode);
107
108
  msgpack_packer_set_compat(pk, RTEST(v));
108
109
  }
109
110
 
@@ -321,7 +322,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
321
322
  {
322
323
  PACKER(self, pk);
323
324
  size_t sz = msgpack_buffer_flush_to_io(PACKER_BUFFER_(pk), io, s_write, true);
324
- return ULONG2NUM(sz);
325
+ return SIZET2NUM(sz);
325
326
  }
326
327
 
327
328
  //static VALUE Packer_append(VALUE self, VALUE string_or_buffer)
@@ -380,7 +381,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
380
381
  rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
381
382
  }
382
383
 
383
- msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, proc, arg);
384
+ msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
384
385
 
385
386
  if (ext_module == rb_cSymbol) {
386
387
  pk->has_symbol_ext_type = true;
@@ -412,6 +413,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
412
413
  s_to_msgpack = rb_intern("to_msgpack");
413
414
  s_write = rb_intern("write");
414
415
 
416
+ sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
417
+
415
418
  msgpack_packer_static_init();
416
419
  msgpack_packer_ext_registry_static_init();
417
420
 
@@ -43,12 +43,18 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
43
43
  void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
44
44
  msgpack_packer_ext_registry_t* dst)
45
45
  {
46
- dst->hash = RTEST(src->hash) ? rb_hash_dup(src->hash) : Qnil;
47
- dst->cache = RTEST(src->cache) ? rb_hash_dup(src->cache): Qnil;
46
+ if(RTEST(src->hash) && !rb_obj_frozen_p(src->hash)) {
47
+ dst->hash = rb_hash_dup(src->hash);
48
+ dst->cache = RTEST(src->cache) ? rb_hash_dup(src->cache) : Qnil;
49
+ } else {
50
+ // If the type registry is frozen we can safely share it, and share the cache as well.
51
+ dst->hash = src->hash;
52
+ dst->cache = src->cache;
53
+ }
48
54
  }
49
55
 
50
56
  VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
51
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
57
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
52
58
  {
53
59
  if (!RTEST(pkrg->hash)) {
54
60
  pkrg->hash = rb_hash_new();
@@ -58,5 +64,8 @@ VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
58
64
  /* clear lookup cache not to miss added type */
59
65
  rb_hash_clear(pkrg->cache);
60
66
  }
61
- return rb_hash_aset(pkrg->hash, ext_module, rb_ary_new3(3, INT2FIX(ext_type), proc, arg));
67
+
68
+ // TODO: Ruby embeded array limit is 3, merging `proc` and `arg` would be good.
69
+ VALUE entry = rb_ary_new3(4, INT2FIX(ext_type), proc, arg, INT2FIX(flags));
70
+ return rb_hash_aset(pkrg->hash, ext_module, entry);
62
71
  }
@@ -21,6 +21,8 @@
21
21
  #include "compat.h"
22
22
  #include "ruby.h"
23
23
 
24
+ #define MSGPACK_EXT_RECURSIVE 0b0001
25
+
24
26
  struct msgpack_packer_ext_registry_t;
25
27
  typedef struct msgpack_packer_ext_registry_t msgpack_packer_ext_registry_t;
26
28
 
@@ -44,7 +46,7 @@ void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
44
46
  msgpack_packer_ext_registry_t* dst);
45
47
 
46
48
  VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
47
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
49
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
48
50
 
49
51
  static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
50
52
  {
@@ -60,12 +62,13 @@ static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
60
62
  }
61
63
 
62
64
  static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registry_t* pkrg,
63
- VALUE lookup_class, int* ext_type_result)
65
+ VALUE lookup_class, int* ext_type_result, int* ext_flags_result)
64
66
  {
65
67
  // fetch lookup_class from hash, which is a hash to register classes
66
68
  VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
67
69
  if(type != Qnil) {
68
70
  *ext_type_result = FIX2INT(rb_ary_entry(type, 0));
71
+ *ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
69
72
  return rb_ary_entry(type, 1);
70
73
  }
71
74
 
@@ -74,6 +77,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
74
77
  VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
75
78
  if(type_inht != Qnil) {
76
79
  *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
80
+ *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
77
81
  return rb_ary_entry(type_inht, 1);
78
82
  }
79
83
  }
@@ -82,7 +86,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
82
86
  }
83
87
 
84
88
  static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_registry_t* pkrg,
85
- VALUE instance, int* ext_type_result)
89
+ VALUE instance, int* ext_type_result, int* ext_flags_result)
86
90
  {
87
91
  VALUE type;
88
92
 
@@ -97,7 +101,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
97
101
  * `rb_class_of` returns the singleton_class if the object has one, or the "real class" otherwise.
98
102
  */
99
103
  VALUE lookup_class = rb_class_of(instance);
100
- type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result);
104
+ type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result, ext_flags_result);
101
105
  if(type != Qnil) {
102
106
  return type;
103
107
  }
@@ -108,7 +112,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
108
112
  */
109
113
  VALUE real_class = rb_obj_class(instance);
110
114
  if(lookup_class != real_class) {
111
- type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result);
115
+ type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result, ext_flags_result);
112
116
  if(type != Qnil) {
113
117
  return type;
114
118
  }
@@ -130,6 +134,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
130
134
  }
131
135
  rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
132
136
  *ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
137
+ *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
133
138
  return rb_ary_entry(superclass_type, 1);
134
139
  }
135
140