msgpack 1.7.1 → 1.7.2

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: c2caf680ff4cafade89a14da270f52528ba2a862cea237ad028ba27fa6a93e9b
4
- data.tar.gz: 01d8cc906d925acbd32a88c22f6ace7f5534a0b447be1736ea58cfdf9abb85b6
3
+ metadata.gz: 2f5b1af6b3a51f5ccc6bcf67c94c1fc6193b02fe01b123e2cfb06a6df9607116
4
+ data.tar.gz: cc057f24e1ffa4cdc3e331499eb04de4c2383b0657dcf0baeba08300fd20862e
5
5
  SHA512:
6
- metadata.gz: 48fcd12bfb13741d88a17e1a261cd742c903ba53cb1959a88b7083c2344817d90cfa898e775c136d785fbfcdd76be14b6dc5fc8ba3638a13ecabbb2d1387dbee
7
- data.tar.gz: 310f3ea573cf41b15c47bc0033121496bd8ab7a723ef3667a96a38bc286feb79536ac5aeb8d27c3c71568149f93c8f36cc9ca8e050595e27ff87762cbccfe2dd
6
+ metadata.gz: 3eb06321a534ca9b16e321cc4a71458532578dafe7967314a662223b1fbf4aa93449c98177fa982aa532ce3732ddda4a6d497704df0e9c874da07f378c73595c
7
+ data.tar.gz: 8e540755e3db9e21d7dfa4354854e8b0486f5a1bbf82c3994c6095022205f7873153d364df9310d8072c481de38ca2b4c3e088e4221c3451ceb9438312489419
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ 2023-07-18 1.7.2:
2
+
3
+ * Fix a potential GC bug when packing data using recursive extensions and buffers containing over 512KkiB of data (See #341).
4
+ * Fix a regression where feeding an empty string to an Unpacker would be considered like the end of the buffer.
5
+
1
6
  2023-05-19 1.7.1:
2
7
 
3
8
  * Fix JRuby 9.4 compatibility.
@@ -54,8 +54,8 @@ public class ExtensionRegistry {
54
54
  return hash;
55
55
  }
56
56
 
57
- public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
58
- ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
57
+ public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
58
+ ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, unpackerProc);
59
59
  extensionsByModule.put(mod, entry);
60
60
  extensionsByTypeId[typeId + 128] = entry;
61
61
  extensionsByAncestor.clear();
@@ -114,18 +114,14 @@ public class ExtensionRegistry {
114
114
  private final int typeId;
115
115
  private final boolean recursive;
116
116
  private final IRubyObject packerProc;
117
- private final IRubyObject packerArg;
118
117
  private final IRubyObject unpackerProc;
119
- private final IRubyObject unpackerArg;
120
118
 
121
- public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
119
+ public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
122
120
  this.mod = mod;
123
121
  this.typeId = typeId;
124
122
  this.recursive = recursive;
125
123
  this.packerProc = packerProc;
126
- this.packerArg = packerArg;
127
124
  this.unpackerProc = unpackerProc;
128
- this.unpackerArg = unpackerArg;
129
125
  }
130
126
 
131
127
  public RubyModule getExtensionModule() {
@@ -157,11 +153,11 @@ public class ExtensionRegistry {
157
153
  }
158
154
 
159
155
  public RubyArray<?> toPackerTuple(ThreadContext ctx) {
160
- return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc, packerArg});
156
+ return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc});
161
157
  }
162
158
 
163
159
  public RubyArray<?> toUnpackerTuple(ThreadContext ctx) {
164
- return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc, unpackerArg});
160
+ return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc});
165
161
  }
166
162
 
167
163
  public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {
@@ -80,43 +80,15 @@ public class Factory extends RubyObject {
80
80
  });
81
81
  }
82
82
 
83
- @JRubyMethod(name = "register_type", required = 2, optional = 1)
84
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
83
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
84
+ public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject opts) {
85
85
  testFrozen("MessagePack::Factory");
86
86
 
87
87
  Ruby runtime = ctx.runtime;
88
- IRubyObject type = args[0];
89
- IRubyObject mod = args[1];
90
-
91
- IRubyObject packerArg;
92
- IRubyObject unpackerArg;
93
-
94
- RubyHash options = null;
95
-
96
- if (args.length == 2) {
97
- packerArg = runtime.newSymbol("to_msgpack_ext");
98
- unpackerArg = runtime.newSymbol("from_msgpack_ext");
99
- } else if (args.length == 3) {
100
- if (args[args.length - 1] instanceof RubyHash) {
101
- options = (RubyHash) args[args.length - 1];
102
- packerArg = options.fastARef(runtime.newSymbol("packer"));
103
- if (packerArg != null && packerArg.isNil()) {
104
- packerArg = null;
105
- }
106
- unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
107
- if (unpackerArg != null && unpackerArg.isNil()) {
108
- unpackerArg = null;
109
- }
110
- IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
111
- if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
112
- throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
113
- }
114
- } else {
115
- throw runtime.newArgumentError(String.format("expected Hash but found %s.", args[args.length - 1].getType().getName()));
116
- }
117
- } else {
118
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
119
- }
88
+ RubyHash options = (RubyHash) opts;
89
+
90
+ IRubyObject packerProc = options.fastARef(runtime.newSymbol("packer"));
91
+ IRubyObject unpackerProc = options.fastARef(runtime.newSymbol("unpacker"));
120
92
 
121
93
  long typeId = ((RubyFixnum) type).getLongValue();
122
94
  if (typeId < -128 || typeId > 127) {
@@ -128,21 +100,6 @@ public class Factory extends RubyObject {
128
100
  }
129
101
  RubyModule extModule = (RubyModule) mod;
130
102
 
131
- IRubyObject packerProc = runtime.getNil();
132
- IRubyObject unpackerProc = runtime.getNil();
133
- if (packerArg != null) {
134
- packerProc = packerArg.callMethod(ctx, "to_proc");
135
- }
136
- if (unpackerArg != null) {
137
- if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
138
- unpackerProc = extModule.method(unpackerArg.callMethod(ctx, "to_sym"));
139
- } else if (unpackerArg instanceof RubyProc || unpackerArg instanceof RubyMethod) {
140
- unpackerProc = unpackerArg;
141
- } else {
142
- unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
143
- }
144
- }
145
-
146
103
  boolean recursive = false;
147
104
  if (options != null) {
148
105
  IRubyObject recursiveExtensionArg = options.fastARef(runtime.newSymbol("recursive"));
@@ -151,7 +108,7 @@ public class Factory extends RubyObject {
151
108
  }
152
109
  }
153
110
 
154
- extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
111
+ extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, unpackerProc);
155
112
 
156
113
  if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
157
114
  hasSymbolExtType = true;
@@ -93,28 +93,11 @@ public class Packer extends RubyObject {
93
93
  return registry.toInternalPackerRegistry(ctx);
94
94
  }
95
95
 
96
- @JRubyMethod(name = "register_type", required = 2, optional = 1)
97
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
96
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
97
+ public IRubyObject registerType(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
98
98
  testFrozen("MessagePack::Packer");
99
99
 
100
100
  Ruby runtime = ctx.runtime;
101
- IRubyObject type = args[0];
102
- IRubyObject mod = args[1];
103
-
104
- IRubyObject arg;
105
- IRubyObject proc;
106
- if (args.length == 2) {
107
- if (! block.isGiven()) {
108
- throw runtime.newLocalJumpErrorNoBlock();
109
- }
110
- proc = block.getProcObject();
111
- arg = proc;
112
- } else if (args.length == 3) {
113
- arg = args[2];
114
- proc = arg.callMethod(ctx, "to_proc");
115
- } else {
116
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
117
- }
118
101
 
119
102
  long typeId = ((RubyFixnum) type).getLongValue();
120
103
  if (typeId < -128 || typeId > 127) {
@@ -126,7 +109,7 @@ public class Packer extends RubyObject {
126
109
  }
127
110
  RubyModule extModule = (RubyModule) mod;
128
111
 
129
- registry.put(extModule, (int) typeId, false, proc, arg, null, null);
112
+ registry.put(extModule, (int) typeId, false, proc, null);
130
113
 
131
114
  if (extModule == runtime.getSymbol() && !proc.isNil()) {
132
115
  encoder.hasSymbolExtType = true;
@@ -126,39 +126,23 @@ public class Unpacker extends RubyObject {
126
126
  return registry.toInternalUnpackerRegistry(ctx);
127
127
  }
128
128
 
129
- @JRubyMethod(name = "register_type", required = 1, optional = 2)
130
- public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
129
+ @JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
130
+ public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
131
131
  testFrozen("MessagePack::Unpacker");
132
132
 
133
133
  Ruby runtime = ctx.runtime;
134
- IRubyObject type = args[0];
135
-
136
- RubyModule extModule;
137
- IRubyObject arg;
138
- IRubyObject proc;
139
- if (args.length == 1) {
140
- if (! block.isGiven()) {
141
- throw runtime.newLocalJumpErrorNoBlock();
142
- }
143
- proc = RubyProc.newProc(runtime, block, block.type);
144
- if (proc == null)
145
- System.err.println("proc from Block is null");
146
- arg = proc;
147
- extModule = null;
148
- } else if (args.length == 3) {
149
- extModule = (RubyModule) args[1];
150
- arg = args[2];
151
- proc = extModule.method(arg);
152
- } else {
153
- throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
154
- }
155
134
 
156
135
  long typeId = ((RubyFixnum) type).getLongValue();
157
136
  if (typeId < -128 || typeId > 127) {
158
137
  throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
159
138
  }
160
139
 
161
- registry.put(extModule, (int) typeId, false, null, null, proc, arg);
140
+ RubyModule extModule = null;
141
+ if (mod != runtime.getNil()) {
142
+ extModule = (RubyModule)mod;
143
+ }
144
+
145
+ registry.put(extModule, (int) typeId, false, null, proc);
162
146
  return runtime.getNil();
163
147
  }
164
148
 
data/ext/msgpack/buffer.c CHANGED
@@ -251,12 +251,14 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
251
251
 
252
252
  static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
253
253
  {
254
- msgpack_buffer_chunk_t* reuse = b->free_list;
255
- if(reuse == NULL) {
256
- return xmalloc(sizeof(msgpack_buffer_chunk_t));
254
+ msgpack_buffer_chunk_t* chunk = b->free_list;
255
+ if (chunk) {
256
+ b->free_list = b->free_list->next;
257
+ } else {
258
+ chunk = xmalloc(sizeof(msgpack_buffer_chunk_t));
257
259
  }
258
- b->free_list = b->free_list->next;
259
- return reuse;
260
+ memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
261
+ return chunk;
260
262
  }
261
263
 
262
264
  static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
data/ext/msgpack/buffer.h CHANGED
@@ -268,7 +268,9 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
268
268
  static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
269
269
  {
270
270
  size_t length = RSTRING_LEN(string);
271
- _msgpack_buffer_append_long_string(b, string);
271
+ if (length > 0) {
272
+ _msgpack_buffer_append_long_string(b, string);
273
+ }
272
274
  return length;
273
275
  }
274
276
 
@@ -21,7 +21,8 @@
21
21
  #include "buffer.h"
22
22
  #include "buffer_class.h"
23
23
 
24
- VALUE cMessagePack_Buffer;
24
+ VALUE cMessagePack_Buffer = Qnil;
25
+ VALUE cMessagePack_HeldBuffer = Qnil;
25
26
 
26
27
  static ID s_read;
27
28
  static ID s_readpartial;
@@ -34,6 +35,73 @@ static VALUE sym_read_reference_threshold;
34
35
  static VALUE sym_write_reference_threshold;
35
36
  static VALUE sym_io_buffer_size;
36
37
 
38
+ typedef struct msgpack_held_buffer_t msgpack_held_buffer_t;
39
+ struct msgpack_held_buffer_t {
40
+ size_t size;
41
+ VALUE mapped_strings[];
42
+ };
43
+
44
+ static void HeldBuffer_mark(void *data)
45
+ {
46
+ msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
47
+ for (size_t index = 0; index < held_buffer->size; index++) {
48
+ rb_gc_mark(held_buffer->mapped_strings[index]);
49
+ }
50
+ }
51
+
52
+ static size_t HeldBuffer_memsize(const void *data)
53
+ {
54
+ const msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
55
+ return sizeof(size_t) + sizeof(VALUE) * held_buffer->size;
56
+ }
57
+
58
+ static const rb_data_type_t held_buffer_data_type = {
59
+ .wrap_struct_name = "msgpack:held_buffer",
60
+ .function = {
61
+ .dmark = HeldBuffer_mark,
62
+ .dfree = RUBY_TYPED_DEFAULT_FREE,
63
+ .dsize = HeldBuffer_memsize,
64
+ },
65
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
66
+ };
67
+
68
+ VALUE MessagePack_Buffer_hold(msgpack_buffer_t* buffer)
69
+ {
70
+ size_t mapped_strings_count = 0;
71
+ msgpack_buffer_chunk_t* c = buffer->head;
72
+ while (c != &buffer->tail) {
73
+ if (c->mapped_string != NO_MAPPED_STRING) {
74
+ mapped_strings_count++;
75
+ }
76
+ c = c->next;
77
+ }
78
+ if (c->mapped_string != NO_MAPPED_STRING) {
79
+ mapped_strings_count++;
80
+ }
81
+
82
+ if (mapped_strings_count == 0) {
83
+ return Qnil;
84
+ }
85
+
86
+ msgpack_held_buffer_t* held_buffer = xmalloc(sizeof(msgpack_held_buffer_t) + mapped_strings_count * sizeof(VALUE));
87
+
88
+ c = buffer->head;
89
+ mapped_strings_count = 0;
90
+ while (c != &buffer->tail) {
91
+ if (c->mapped_string != NO_MAPPED_STRING) {
92
+ held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
93
+ mapped_strings_count++;
94
+ }
95
+ c = c->next;
96
+ }
97
+ if (c->mapped_string != NO_MAPPED_STRING) {
98
+ held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
99
+ mapped_strings_count++;
100
+ }
101
+ held_buffer->size = mapped_strings_count;
102
+ return TypedData_Wrap_Struct(cMessagePack_HeldBuffer, &held_buffer_data_type, held_buffer);
103
+ }
104
+
37
105
 
38
106
  #define CHECK_STRING_TYPE(value) \
39
107
  value = rb_check_string_type(value); \
@@ -520,6 +588,9 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
520
588
 
521
589
  msgpack_buffer_static_init();
522
590
 
591
+ cMessagePack_HeldBuffer = rb_define_class_under(mMessagePack, "HeldBuffer", rb_cBasicObject);
592
+ rb_undef_alloc_func(cMessagePack_HeldBuffer);
593
+
523
594
  cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
524
595
 
525
596
  rb_define_alloc_func(cMessagePack_Buffer, Buffer_alloc);
@@ -25,6 +25,7 @@ extern VALUE cMessagePack_Buffer;
25
25
  void MessagePack_Buffer_module_init(VALUE mMessagePack);
26
26
 
27
27
  VALUE MessagePack_Buffer_wrap(msgpack_buffer_t* b, VALUE owner);
28
+ VALUE MessagePack_Buffer_hold(msgpack_buffer_t* b);
28
29
 
29
30
  void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options);
30
31
 
@@ -1,9 +1,8 @@
1
1
  require 'mkmf'
2
2
 
3
- have_header("ruby/st.h")
4
- have_header("st.h")
5
3
  have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
4
  have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
5
+ have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
7
6
 
8
7
  append_cflags([
9
8
  "-fvisibility=hidden",
@@ -75,7 +75,7 @@ static const rb_data_type_t factory_data_type = {
75
75
  .dfree = Factory_free,
76
76
  .dsize = Factory_memsize,
77
77
  },
78
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
78
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
79
79
  };
80
80
 
81
81
  static inline msgpack_factory_t *Factory_get(VALUE object)
@@ -98,7 +98,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
98
98
  {
99
99
  msgpack_factory_t *fc = Factory_get(self);
100
100
 
101
- msgpack_packer_ext_registry_init(&fc->pkrg);
101
+ msgpack_packer_ext_registry_init(self, &fc->pkrg);
102
102
  // fc->ukrg is lazily initialized
103
103
 
104
104
  fc->has_symbol_ext_type = false;
@@ -124,7 +124,7 @@ static VALUE Factory_dup(VALUE self)
124
124
  cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
125
125
  cloned_fc->pkrg = fc->pkrg;
126
126
  msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
127
- msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
127
+ msgpack_packer_ext_registry_dup(clone, &fc->pkrg, &cloned_fc->pkrg);
128
128
 
129
129
  return clone;
130
130
  }
@@ -139,7 +139,7 @@ static VALUE Factory_freeze(VALUE self) {
139
139
  // If the factory is frozen, we can safely share the packer cache between
140
140
  // all packers. So we eagerly create it now so it's available when #packer
141
141
  // is called.
142
- fc->pkrg.cache = rb_hash_new();
142
+ RB_OBJ_WRITE(self, &fc->pkrg.cache, rb_hash_new());
143
143
  }
144
144
  }
145
145
 
@@ -158,7 +158,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
158
158
 
159
159
  msgpack_packer_t* pk = MessagePack_Packer_get(packer);
160
160
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
161
- msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
161
+ msgpack_packer_ext_registry_borrow(packer, &fc->pkrg, &pk->ext_registry);
162
162
  pk->has_bigint_ext_type = fc->has_bigint_ext_type;
163
163
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
164
164
 
@@ -187,7 +187,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
187
187
  VALUE uk_mapping = rb_hash_new();
188
188
  if (fc->ukrg) {
189
189
  for(int i=0; i < 256; i++) {
190
- if(fc->ukrg->array[i] != Qnil) {
190
+ if(!NIL_P(fc->ukrg->array[i])) {
191
191
  rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192
192
  }
193
193
  }
@@ -200,72 +200,35 @@ static VALUE Factory_registered_types_internal(VALUE self)
200
200
  );
201
201
  }
202
202
 
203
- static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
203
+ static VALUE Factory_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE options)
204
204
  {
205
205
  msgpack_factory_t *fc = Factory_get(self);
206
206
 
207
- int ext_type;
208
- int flags = 0;
209
- VALUE ext_module;
210
- VALUE options = Qnil;
211
- VALUE packer_arg, unpacker_arg;
212
- VALUE packer_proc, unpacker_proc;
207
+ Check_Type(rb_ext_type, T_FIXNUM);
213
208
 
214
- if (OBJ_FROZEN(self)) {
215
- rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
209
+ if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
210
+ rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
216
211
  }
217
212
 
218
- switch (argc) {
219
- case 2:
220
- /* register_type(0x7f, Time) */
221
- packer_arg = ID2SYM(rb_intern("to_msgpack_ext"));
222
- unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
223
- break;
224
- case 3:
225
- /* register_type(0x7f, Time, packer: proc-like, unpacker: proc-like) */
226
- options = argv[2];
227
- if(rb_type(options) != T_HASH) {
228
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
229
- }
213
+ int flags = 0;
230
214
 
231
- packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
232
- unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
233
- break;
234
- default:
235
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
215
+ VALUE packer_proc = Qnil;
216
+ VALUE unpacker_proc = Qnil;
217
+ if(!NIL_P(options)) {
218
+ Check_Type(options, T_HASH);
219
+ packer_proc = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
220
+ unpacker_proc = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
236
221
  }
237
222
 
238
- if (options != Qnil) {
239
- Check_Type(options, T_HASH);
223
+ if (OBJ_FROZEN(self)) {
224
+ rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
240
225
  }
241
226
 
242
- ext_type = NUM2INT(argv[0]);
227
+ int ext_type = NUM2INT(rb_ext_type);
243
228
  if(ext_type < -128 || ext_type > 127) {
244
229
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
245
230
  }
246
231
 
247
- ext_module = argv[1];
248
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
249
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
250
- }
251
-
252
- packer_proc = Qnil;
253
- unpacker_proc = Qnil;
254
-
255
- if(packer_arg != Qnil) {
256
- packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
257
- }
258
-
259
- if(unpacker_arg != Qnil) {
260
- if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
261
- unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
262
- } else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
263
- unpacker_proc = unpacker_arg;
264
- } else {
265
- unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
266
- }
267
- }
268
-
269
232
  if(ext_module == rb_cSymbol) {
270
233
  if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
271
234
  fc->has_symbol_ext_type = true;
@@ -289,8 +252,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
289
252
  }
290
253
  }
291
254
 
292
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
293
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
255
+ msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc);
256
+ msgpack_unpacker_ext_registry_put(self, &fc->ukrg, ext_module, ext_type, flags, unpacker_proc);
294
257
 
295
258
  return Qnil;
296
259
  }
@@ -309,5 +272,5 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
309
272
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
310
273
 
311
274
  rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
312
- rb_define_method(cMessagePack_Factory, "register_type", Factory_register_type, -1);
275
+ rb_define_private_method(cMessagePack_Factory, "register_type_internal", Factory_register_type_internal, 3);
313
276
  }
data/ext/msgpack/packer.c CHANGED
@@ -17,16 +17,11 @@
17
17
  */
18
18
 
19
19
  #include "packer.h"
20
+ #include "buffer_class.h"
20
21
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_static_destroy(void)
29
- { }
22
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
23
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
24
+ #endif
30
25
 
31
26
  void msgpack_packer_init(msgpack_packer_t* pk)
32
27
  {
@@ -100,14 +95,13 @@ struct msgpack_call_proc_args_t;
100
95
  typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
101
96
  struct msgpack_call_proc_args_t {
102
97
  VALUE proc;
103
- VALUE arg;
104
- VALUE packer;
98
+ VALUE args[2];
105
99
  };
106
100
 
107
101
  VALUE msgpack_packer_try_calling_proc(VALUE value)
108
102
  {
109
103
  msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
110
- return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
104
+ return rb_proc_call_with_block(args->proc, 2, args->args, Qnil);
111
105
  }
112
106
 
113
107
  bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
@@ -121,11 +115,13 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
121
115
  }
122
116
 
123
117
  if(ext_flags & MSGPACK_EXT_RECURSIVE) {
118
+ VALUE held_buffer = MessagePack_Buffer_hold(&pk->buffer);
119
+
124
120
  msgpack_buffer_t parent_buffer = pk->buffer;
125
121
  msgpack_buffer_init(PACKER_BUFFER_(pk));
126
122
 
127
123
  int exception_occured = 0;
128
- msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
124
+ msgpack_call_proc_args_t args = { proc, { v, pk->to_msgpack_arg } };
129
125
  rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
130
126
 
131
127
  if (exception_occured) {
@@ -139,8 +135,10 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
139
135
  pk->buffer = parent_buffer;
140
136
  msgpack_packer_write_ext(pk, ext_type, payload);
141
137
  }
138
+
139
+ RB_GC_GUARD(held_buffer);
142
140
  } else {
143
- VALUE payload = rb_funcall(proc, s_call, 1, v);
141
+ VALUE payload = rb_proc_call_with_block(proc, 1, &v, Qnil);
144
142
  StringValue(payload);
145
143
  msgpack_packer_write_ext(pk, ext_type, payload);
146
144
  }
data/ext/msgpack/packer.h CHANGED
@@ -47,10 +47,6 @@ struct msgpack_packer_t {
47
47
 
48
48
  #define PACKER_BUFFER_(pk) (&(pk)->buffer)
49
49
 
50
- void msgpack_packer_static_init(void);
51
-
52
- void msgpack_packer_static_destroy(void);
53
-
54
50
  void msgpack_packer_init(msgpack_packer_t* pk);
55
51
 
56
52
  void msgpack_packer_destroy(msgpack_packer_t* pk);
@@ -106,8 +106,8 @@ VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
106
106
 
107
107
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
108
108
 
109
- msgpack_packer_ext_registry_init(&pk->ext_registry);
110
- pk->buffer_ref = Qnil;
109
+ msgpack_packer_ext_registry_init(self, &pk->ext_registry);
110
+ pk->buffer_ref = MessagePack_Buffer_wrap(PACKER_BUFFER_(pk), self);
111
111
 
112
112
  MessagePack_Buffer_set_options(PACKER_BUFFER_(pk), io, options);
113
113
 
@@ -352,7 +352,7 @@ static VALUE Packer_registered_types_internal(VALUE self)
352
352
  return rb_hash_new();
353
353
  }
354
354
 
355
- static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
355
+ static VALUE Packer_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE proc)
356
356
  {
357
357
  if (OBJ_FROZEN(self)) {
358
358
  rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Packer");
@@ -360,38 +360,12 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
360
360
 
361
361
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
362
362
 
363
- int ext_type;
364
- VALUE ext_module;
365
- VALUE proc;
366
- VALUE arg;
367
-
368
- switch (argc) {
369
- case 2:
370
- /* register_type(0x7f, Time) {|obj| block... } */
371
- rb_need_block();
372
- proc = rb_block_lambda();
373
- arg = proc;
374
- break;
375
- case 3:
376
- /* register_type(0x7f, Time, :to_msgpack_ext) */
377
- arg = argv[2];
378
- proc = rb_funcall(arg, rb_intern("to_proc"), 0);
379
- break;
380
- default:
381
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
382
- }
383
-
384
- ext_type = NUM2INT(argv[0]);
363
+ int ext_type = NUM2INT(rb_ext_type);
385
364
  if(ext_type < -128 || ext_type > 127) {
386
365
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
387
366
  }
388
367
 
389
- ext_module = argv[1];
390
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
391
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
392
- }
393
-
394
- msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
368
+ msgpack_packer_ext_registry_put(self, &pk->ext_registry, ext_module, ext_type, 0, proc);
395
369
 
396
370
  if (ext_module == rb_cSymbol) {
397
371
  pk->has_symbol_ext_type = true;
@@ -424,10 +398,6 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
424
398
  s_write = rb_intern("write");
425
399
 
426
400
  sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
427
-
428
- msgpack_packer_static_init();
429
- msgpack_packer_ext_registry_static_init();
430
-
431
401
  cMessagePack_Packer = rb_define_class_under(mMessagePack, "Packer", rb_cObject);
432
402
 
433
403
  rb_define_alloc_func(cMessagePack_Packer, MessagePack_Packer_alloc);
@@ -466,7 +436,7 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
466
436
  rb_define_method(cMessagePack_Packer, "to_a", Packer_to_a, 0);
467
437
 
468
438
  rb_define_private_method(cMessagePack_Packer, "registered_types_internal", Packer_registered_types_internal, 0);
469
- rb_define_method(cMessagePack_Packer, "register_type", Packer_register_type, -1);
439
+ rb_define_method(cMessagePack_Packer, "register_type_internal", Packer_register_type_internal, 3);
470
440
 
471
441
  rb_define_method(cMessagePack_Packer, "full_pack", Packer_full_pack, 0);
472
442
  }
@@ -18,20 +18,10 @@
18
18
 
19
19
  #include "packer_ext_registry.h"
20
20
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_ext_registry_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_ext_registry_static_destroy(void)
29
- { }
30
-
31
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg)
21
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg)
32
22
  {
33
- pkrg->hash = Qnil;
34
- pkrg->cache = Qnil;
23
+ RB_OBJ_WRITE(owner, &pkrg->hash, Qnil);
24
+ RB_OBJ_WRITE(owner, &pkrg->cache, Qnil);
35
25
  }
36
26
 
37
27
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
@@ -40,32 +30,45 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
40
30
  rb_gc_mark(pkrg->cache);
41
31
  }
42
32
 
43
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
33
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
44
34
  msgpack_packer_ext_registry_t* dst)
45
35
  {
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;
36
+ if(RTEST(src->hash)) {
37
+ if(rb_obj_frozen_p(src->hash)) {
38
+ // If the type registry is frozen we can safely share it, and share the cache as well.
39
+ RB_OBJ_WRITE(owner, &dst->hash, src->hash);
40
+ RB_OBJ_WRITE(owner, &dst->cache, src->cache);
41
+ } else {
42
+ RB_OBJ_WRITE(owner, &dst->hash, rb_hash_dup(src->hash));
43
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
44
+ }
49
45
  } 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;
46
+ RB_OBJ_WRITE(owner, &dst->hash, Qnil);
47
+ RB_OBJ_WRITE(owner, &dst->cache, Qnil);
53
48
  }
54
49
  }
55
50
 
56
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
57
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
51
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
52
+ msgpack_packer_ext_registry_t* dst)
58
53
  {
59
- if (!RTEST(pkrg->hash)) {
60
- pkrg->hash = rb_hash_new();
54
+ RB_OBJ_WRITE(owner, &dst->hash, NIL_P(src->hash) ? Qnil : rb_hash_dup(src->hash));
55
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
56
+ }
57
+
58
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
59
+ VALUE ext_module, int ext_type, int flags, VALUE proc)
60
+ {
61
+ if(NIL_P(pkrg->hash)) {
62
+ RB_OBJ_WRITE(owner, &pkrg->hash, rb_hash_new());
61
63
  }
62
64
 
63
- if (RTEST(pkrg->cache)) {
65
+ if(NIL_P(pkrg->cache)) {
66
+ RB_OBJ_WRITE(owner, &pkrg->cache, rb_hash_new());
67
+ } else {
64
68
  /* clear lookup cache not to miss added type */
65
69
  rb_hash_clear(pkrg->cache);
66
70
  }
67
71
 
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);
72
+ VALUE entry = rb_ary_new3(3, INT2FIX(ext_type), proc, INT2FIX(flags));
73
+ rb_hash_aset(pkrg->hash, ext_module, entry);
71
74
  }
@@ -31,22 +31,21 @@ struct msgpack_packer_ext_registry_t {
31
31
  VALUE cache; // lookup cache for ext types inherited from a super class
32
32
  };
33
33
 
34
- void msgpack_packer_ext_registry_static_init(void);
35
-
36
- void msgpack_packer_ext_registry_static_destroy(void);
37
-
38
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg);
34
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg);
39
35
 
40
36
  static inline void msgpack_packer_ext_registry_destroy(msgpack_packer_ext_registry_t* pkrg)
41
37
  { }
42
38
 
43
39
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg);
44
40
 
45
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
41
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
46
42
  msgpack_packer_ext_registry_t* dst);
47
43
 
48
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
49
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
44
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
45
+ msgpack_packer_ext_registry_t* dst);
46
+
47
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
48
+ VALUE ext_module, int ext_type, int flags, VALUE proc);
50
49
 
51
50
  static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
52
51
  {
@@ -68,7 +67,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
68
67
  VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
69
68
  if(type != Qnil) {
70
69
  *ext_type_result = FIX2INT(rb_ary_entry(type, 0));
71
- *ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
70
+ *ext_flags_result = FIX2INT(rb_ary_entry(type, 2));
72
71
  return rb_ary_entry(type, 1);
73
72
  }
74
73
 
@@ -77,7 +76,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
77
76
  VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
78
77
  if(type_inht != Qnil) {
79
78
  *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
80
- *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
79
+ *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 2));
81
80
  return rb_ary_entry(type_inht, 1);
82
81
  }
83
82
  }
@@ -129,12 +128,9 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
129
128
  VALUE superclass = args[1];
130
129
  if(superclass != Qnil) {
131
130
  VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
132
- if (!RTEST(pkrg->cache)) {
133
- pkrg->cache = rb_hash_new();
134
- }
135
131
  rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
136
132
  *ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
137
- *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
133
+ *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 2));
138
134
  return rb_ary_entry(superclass_type, 1);
139
135
  }
140
136
 
@@ -21,11 +21,13 @@
21
21
  #include "extension_value_class.h"
22
22
  #include <assert.h>
23
23
 
24
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
25
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
26
+ #endif
27
+
24
28
  static int RAW_TYPE_STRING = 256;
25
29
  static int RAW_TYPE_BINARY = 257;
26
30
 
27
- static ID s_call;
28
-
29
31
  static msgpack_rmem_t s_stack_rmem;
30
32
 
31
33
  #if !defined(HAVE_RB_HASH_NEW_CAPA)
@@ -40,8 +42,6 @@ void msgpack_unpacker_static_init(void)
40
42
  assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
41
43
 
42
44
  msgpack_rmem_init(&s_stack_rmem);
43
-
44
- s_call = rb_intern("call");
45
45
  }
46
46
 
47
47
  void msgpack_unpacker_static_destroy(void)
@@ -178,7 +178,8 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
178
178
 
179
179
  if(proc != Qnil) {
180
180
  VALUE obj;
181
- obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
181
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
182
+ obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
182
183
  return object_complete(uk, obj);
183
184
  }
184
185
 
@@ -308,7 +309,7 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
308
309
  child_stack->parent = uk->stack;
309
310
  uk->stack = child_stack;
310
311
 
311
- obj = rb_funcall(proc, s_call, 1, uk->self);
312
+ obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
312
313
 
313
314
  uk->stack = child_stack->parent;
314
315
  _msgpack_unpacker_free_stack(child_stack);
@@ -346,43 +346,19 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
346
346
  return mapping;
347
347
  }
348
348
 
349
- static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
349
+ static VALUE Unpacker_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE proc)
350
350
  {
351
351
  if (OBJ_FROZEN(self)) {
352
352
  rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Unpacker");
353
353
  }
354
354
 
355
- msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
356
-
357
- int ext_type;
358
- VALUE proc;
359
- VALUE arg;
360
- VALUE ext_module;
361
-
362
- switch (argc) {
363
- case 1:
364
- /* register_type(0x7f) {|data| block... } */
365
- rb_need_block();
366
- proc = rb_block_lambda();
367
- arg = proc;
368
- ext_module = Qnil;
369
- break;
370
- case 3:
371
- /* register_type(0x7f, Time, :from_msgpack_ext) */
372
- ext_module = argv[1];
373
- arg = argv[2];
374
- proc = rb_obj_method(ext_module, arg);
375
- break;
376
- default:
377
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 3)", argc);
378
- }
379
-
380
- ext_type = NUM2INT(argv[0]);
355
+ int ext_type = NUM2INT(rb_ext_type);
381
356
  if(ext_type < -128 || ext_type > 127) {
382
357
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
383
358
  }
384
359
 
385
- msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
360
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
361
+ msgpack_unpacker_ext_registry_put(self, &uk->ext_registry, ext_module, ext_type, 0, proc);
386
362
 
387
363
  return Qnil;
388
364
  }
@@ -415,7 +391,6 @@ VALUE MessagePack_Unpacker_new(int argc, VALUE* argv)
415
391
  void MessagePack_Unpacker_module_init(VALUE mMessagePack)
416
392
  {
417
393
  msgpack_unpacker_static_init();
418
- msgpack_unpacker_ext_registry_static_init();
419
394
 
420
395
  mTypeError = rb_define_module_under(mMessagePack, "TypeError");
421
396
 
@@ -456,7 +431,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
456
431
  rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);
457
432
 
458
433
  rb_define_private_method(cMessagePack_Unpacker, "registered_types_internal", Unpacker_registered_types_internal, 0);
459
- rb_define_method(cMessagePack_Unpacker, "register_type", Unpacker_register_type, -1);
434
+ rb_define_private_method(cMessagePack_Unpacker, "register_type_internal", Unpacker_register_type_internal, 3);
460
435
 
461
436
  rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
462
437
  }
@@ -18,19 +18,6 @@
18
18
 
19
19
  #include "unpacker_ext_registry.h"
20
20
 
21
- static ID s_call;
22
- static ID s_dup;
23
-
24
- void msgpack_unpacker_ext_registry_static_init(void)
25
- {
26
- s_call = rb_intern("call");
27
- s_dup = rb_intern("dup");
28
- }
29
-
30
-
31
- void msgpack_unpacker_ext_registry_static_destroy(void)
32
- { }
33
-
34
21
  void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
35
22
  {
36
23
  if (ukrg) {
@@ -76,11 +63,12 @@ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg
76
63
  }
77
64
  }
78
65
 
79
- void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
80
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
66
+ void msgpack_unpacker_ext_registry_put(VALUE owner, msgpack_unpacker_ext_registry_t** ukrg,
67
+ VALUE ext_module, int ext_type, int flags, VALUE proc)
81
68
  {
82
69
  msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
83
70
 
84
- ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
71
+ VALUE entry = rb_ary_new3(3, ext_module, proc, INT2FIX(flags));
72
+ RB_OBJ_WRITE(owner, &ext_registry->array[ext_type + 128], entry);
85
73
  *ukrg = ext_registry;
86
74
  }
@@ -31,10 +31,6 @@ struct msgpack_unpacker_ext_registry_t {
31
31
  VALUE array[256];
32
32
  };
33
33
 
34
- void msgpack_unpacker_ext_registry_static_init(void);
35
-
36
- void msgpack_unpacker_ext_registry_static_destroy(void);
37
-
38
34
  void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg);
39
35
 
40
36
  static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_registry_t* src, msgpack_unpacker_ext_registry_t** dst)
@@ -47,8 +43,8 @@ static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_reg
47
43
 
48
44
  void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
49
45
 
50
- void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
51
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
46
+ void msgpack_unpacker_ext_registry_put(VALUE owner, msgpack_unpacker_ext_registry_t** ukrg,
47
+ VALUE ext_module, int ext_type, int flags, VALUE proc);
52
48
 
53
49
  static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
54
50
  int ext_type, int* ext_flags_result)
@@ -56,7 +52,7 @@ static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_re
56
52
  if (ukrg) {
57
53
  VALUE entry = ukrg->array[ext_type + 128];
58
54
  if (entry != Qnil) {
59
- *ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
55
+ *ext_flags_result = FIX2INT(rb_ary_entry(entry, 2));
60
56
  return rb_ary_entry(entry, 1);
61
57
  }
62
58
  }
@@ -2,11 +2,46 @@ module MessagePack
2
2
  class Factory
3
3
  # see ext for other methods
4
4
 
5
+ def register_type(type, klass, options = { packer: :to_msgpack_ext, unpacker: :from_msgpack_ext })
6
+ raise FrozenError, "can't modify frozen MessagePack::Factory" if frozen?
7
+
8
+ if options
9
+ options = options.dup
10
+ case packer = options[:packer]
11
+ when nil, Proc
12
+ # all good
13
+ when String, Symbol
14
+ options[:packer] = packer.to_sym.to_proc
15
+ when Method
16
+ options[:packer] = packer.to_proc
17
+ when packer.respond_to?(:call)
18
+ options[:packer] = packer.method(:call).to_proc
19
+ else
20
+ raise ::TypeError, "expected :packer argument to be a callable object, got: #{packer.inspect}"
21
+ end
22
+
23
+ case unpacker = options[:unpacker]
24
+ when nil, Proc
25
+ # all good
26
+ when String, Symbol
27
+ options[:unpacker] = klass.method(unpacker).to_proc
28
+ when Method
29
+ options[:unpacker] = unpacker.to_proc
30
+ when packer.respond_to?(:call)
31
+ options[:unpacker] = unpacker.method(:call).to_proc
32
+ else
33
+ raise ::TypeError, "expected :unpacker argument to be a callable object, got: #{unpacker.inspect}"
34
+ end
35
+ end
36
+
37
+ register_type_internal(type, klass, options)
38
+ end
39
+
5
40
  # [ {type: id, class: Class(or nil), packer: arg, unpacker: arg}, ... ]
6
41
  def registered_types(selector=:both)
7
42
  packer, unpacker = registered_types_internal
8
- # packer: Class -> [tid, proc, arg]
9
- # unpacker: tid -> [klass, proc, arg]
43
+ # packer: Class -> [tid, proc, _flags]
44
+ # unpacker: tid -> [klass, proc, _flags]
10
45
 
11
46
  list = []
12
47
 
@@ -14,27 +49,31 @@ module MessagePack
14
49
  when :both
15
50
  packer.each_pair do |klass, ary|
16
51
  type = ary[0]
17
- packer_arg = ary[2]
18
- unpacker_arg = nil
19
- if unpacker.has_key?(type) && unpacker[type][0] == klass
20
- unpacker_arg = unpacker.delete(type)[2]
52
+ packer_proc = ary[1]
53
+ unpacker_proc = nil
54
+ if unpacker.has_key?(type)
55
+ unpacker_proc = unpacker.delete(type)[1]
21
56
  end
22
- list << {type: type, class: klass, packer: packer_arg, unpacker: unpacker_arg}
57
+ list << {type: type, class: klass, packer: packer_proc, unpacker: unpacker_proc}
23
58
  end
24
59
 
25
60
  # unpacker definition only
26
61
  unpacker.each_pair do |type, ary|
27
- list << {type: type, class: ary[0], packer: nil, unpacker: ary[2]}
62
+ list << {type: type, class: ary[0], packer: nil, unpacker: ary[1]}
28
63
  end
29
64
 
30
65
  when :packer
31
66
  packer.each_pair do |klass, ary|
32
- list << {type: ary[0], class: klass, packer: ary[2]}
67
+ if ary[1]
68
+ list << {type: ary[0], class: klass, packer: ary[1]}
69
+ end
33
70
  end
34
71
 
35
72
  when :unpacker
36
73
  unpacker.each_pair do |type, ary|
37
- list << {type: type, class: ary[0], unpacker: ary[2]}
74
+ if ary[1]
75
+ list << {type: type, class: ary[0], unpacker: ary[1]}
76
+ end
38
77
  end
39
78
 
40
79
  else
@@ -6,11 +6,16 @@ module MessagePack
6
6
  undef_method :dup
7
7
  undef_method :clone
8
8
 
9
+ def register_type(type, klass, method_name = nil, &block)
10
+ raise ArgumentError, "expected Module/Class got: #{klass.inspect}" unless klass.is_a?(Module)
11
+ register_type_internal(type, klass, block || method_name.to_proc)
12
+ end
13
+
9
14
  def registered_types
10
15
  list = []
11
16
 
12
17
  registered_types_internal.each_pair do |klass, ary|
13
- list << {type: ary[0], class: klass, packer: ary[2]}
18
+ list << {type: ary[0], class: klass, packer: ary[1]}
14
19
  end
15
20
 
16
21
  list.sort{|a, b| a[:type] <=> b[:type] }
@@ -6,11 +6,20 @@ module MessagePack
6
6
  undef_method :dup
7
7
  undef_method :clone
8
8
 
9
+ def register_type(type, klass = nil, method_name = nil, &block)
10
+ if klass && method_name
11
+ block = klass.method(method_name).to_proc
12
+ elsif !block_given?
13
+ raise ArgumentError, "register_type takes either 3 arguments or a block"
14
+ end
15
+ register_type_internal(type, klass, block)
16
+ end
17
+
9
18
  def registered_types
10
19
  list = []
11
20
 
12
21
  registered_types_internal.each_pair do |type, ary|
13
- list << {type: type, class: ary[0], unpacker: ary[2]}
22
+ list << {type: type, class: ary[0], unpacker: ary[1]}
14
23
  end
15
24
 
16
25
  list.sort{|a, b| a[:type] <=> b[:type] }
@@ -1,5 +1,5 @@
1
1
  module MessagePack
2
- VERSION = "1.7.1"
2
+ VERSION = "1.7.2"
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.
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.7.1
4
+ version: 1.7.2
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: 2023-05-19 00:00:00.000000000 Z
13
+ date: 2023-07-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -208,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
208
208
  - !ruby/object:Gem::Version
209
209
  version: '0'
210
210
  requirements: []
211
- rubygems_version: 3.1.2
211
+ rubygems_version: 3.3.7
212
212
  signing_key:
213
213
  specification_version: 4
214
214
  summary: MessagePack, a binary-based efficient data interchange format.