msgpack 1.4.4 → 1.5.1
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 +4 -4
- data/.github/workflows/ci.yaml +4 -3
- data/ChangeLog +18 -0
- data/README.md +22 -0
- data/doclib/msgpack/factory.rb +46 -3
- data/doclib/msgpack/packer.rb +5 -4
- data/doclib/msgpack/unpacker.rb +2 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
- data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +28 -40
- data/ext/java/org/msgpack/jruby/Factory.java +40 -5
- data/ext/java/org/msgpack/jruby/Packer.java +21 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
- data/ext/msgpack/buffer.h +2 -2
- data/ext/msgpack/buffer_class.c +23 -15
- data/ext/msgpack/factory_class.c +78 -16
- data/ext/msgpack/packer.c +42 -5
- data/ext/msgpack/packer.h +24 -0
- data/ext/msgpack/packer_class.c +29 -22
- data/ext/msgpack/packer_ext_registry.c +23 -9
- data/ext/msgpack/packer_ext_registry.h +38 -31
- data/ext/msgpack/unpacker.c +72 -32
- data/ext/msgpack/unpacker.h +2 -2
- data/ext/msgpack/unpacker_class.c +26 -45
- data/ext/msgpack/unpacker_ext_registry.c +40 -16
- data/ext/msgpack/unpacker_ext_registry.h +21 -14
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/symbol.rb +8 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +284 -14
- data/spec/spec_helper.rb +4 -4
- data/spec/timestamp_spec.rb +0 -2
- data/spec/unpacker_spec.rb +22 -3
- metadata +4 -2
@@ -32,17 +32,19 @@ public class Packer extends RubyObject {
|
|
32
32
|
private Buffer buffer;
|
33
33
|
private Encoder encoder;
|
34
34
|
private boolean hasSymbolExtType;
|
35
|
+
private boolean hasBigintExtType;
|
35
36
|
private Encoding binaryEncoding;
|
36
37
|
|
37
|
-
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType) {
|
38
|
+
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType, boolean hasBigintExtType) {
|
38
39
|
super(runtime, type);
|
39
40
|
this.registry = registry;
|
40
41
|
this.hasSymbolExtType = hasSymbolExtType;
|
42
|
+
this.hasBigintExtType = hasBigintExtType;
|
41
43
|
}
|
42
44
|
|
43
45
|
static class PackerAllocator implements ObjectAllocator {
|
44
46
|
public IRubyObject allocate(Ruby runtime, RubyClass type) {
|
45
|
-
return new Packer(runtime, type, null, false);
|
47
|
+
return new Packer(runtime, type, null, false, false);
|
46
48
|
}
|
47
49
|
}
|
48
50
|
|
@@ -50,25 +52,33 @@ public class Packer extends RubyObject {
|
|
50
52
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
51
53
|
boolean compatibilityMode = false;
|
52
54
|
Ruby runtime = ctx.runtime;
|
53
|
-
if (args.length > 0
|
54
|
-
RubyHash options =
|
55
|
-
|
56
|
-
|
55
|
+
if (args.length > 0) {
|
56
|
+
RubyHash options = null;
|
57
|
+
if (args[args.length - 1] instanceof RubyHash) {
|
58
|
+
options = (RubyHash) args[args.length - 1];
|
59
|
+
} else if (args.length > 1 && args[args.length - 2] instanceof RubyHash) {
|
60
|
+
options = (RubyHash) args[args.length - 2];
|
61
|
+
}
|
62
|
+
|
63
|
+
if (options != null) {
|
64
|
+
IRubyObject mode = options.fastARef(runtime.newSymbol("compatibility_mode"));
|
65
|
+
compatibilityMode = (mode != null) && mode.isTrue();
|
66
|
+
}
|
57
67
|
}
|
58
68
|
if (registry == null) {
|
59
69
|
// registry is null when allocate -> initialize
|
60
70
|
// registry is already initialized (and somthing might be registered) when newPacker from Factory
|
61
71
|
this.registry = new ExtensionRegistry();
|
62
72
|
}
|
63
|
-
this.encoder = new Encoder(runtime, compatibilityMode, registry, hasSymbolExtType);
|
73
|
+
this.encoder = new Encoder(runtime, this, compatibilityMode, registry, hasSymbolExtType, hasBigintExtType);
|
64
74
|
this.buffer = new Buffer(runtime, runtime.getModule("MessagePack").getClass("Buffer"));
|
65
75
|
this.buffer.initialize(ctx, args);
|
66
76
|
this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
|
67
77
|
return this;
|
68
78
|
}
|
69
79
|
|
70
|
-
public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, boolean hasSymbolExtType, IRubyObject[] args) {
|
71
|
-
Packer packer = new Packer(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Packer"), extRegistry, hasSymbolExtType);
|
80
|
+
public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, boolean hasSymbolExtType, boolean hasBigintExtType, IRubyObject[] args) {
|
81
|
+
Packer packer = new Packer(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Packer"), extRegistry, hasSymbolExtType, hasBigintExtType);
|
72
82
|
packer.initialize(ctx, args);
|
73
83
|
return packer;
|
74
84
|
}
|
@@ -114,7 +124,7 @@ public class Packer extends RubyObject {
|
|
114
124
|
}
|
115
125
|
RubyModule extModule = (RubyModule) mod;
|
116
126
|
|
117
|
-
registry.put(extModule, (int) typeId, proc, arg, null, null);
|
127
|
+
registry.put(extModule, (int) typeId, false, proc, arg, null, null);
|
118
128
|
|
119
129
|
if (extModule == runtime.getSymbol()) {
|
120
130
|
encoder.hasSymbolExtType = true;
|
@@ -257,7 +267,7 @@ public class Packer extends RubyObject {
|
|
257
267
|
return buffer.size(ctx);
|
258
268
|
}
|
259
269
|
|
260
|
-
@JRubyMethod(name = "clear")
|
270
|
+
@JRubyMethod(name = "clear", alias = { "reset" })
|
261
271
|
public IRubyObject clear(ThreadContext ctx) {
|
262
272
|
return buffer.clear(ctx);
|
263
273
|
}
|
@@ -56,30 +56,48 @@ public class Unpacker extends RubyObject {
|
|
56
56
|
|
57
57
|
@JRubyMethod(name = "initialize", optional = 2, visibility = PRIVATE)
|
58
58
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
59
|
+
Ruby runtime = ctx.runtime;
|
60
|
+
|
59
61
|
symbolizeKeys = false;
|
60
62
|
allowUnknownExt = false;
|
61
63
|
freeze = false;
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
64
|
+
|
65
|
+
IRubyObject io = null;
|
66
|
+
RubyHash options = null;
|
67
|
+
|
68
|
+
if (args.length >= 1) {
|
69
|
+
io = args[0];
|
70
|
+
}
|
71
|
+
|
72
|
+
if (args.length >= 2 && args[1] != runtime.getNil()) {
|
73
|
+
options = (RubyHash)args[1];
|
74
|
+
}
|
75
|
+
|
76
|
+
if (options == null && io != null && io instanceof RubyHash) {
|
77
|
+
options = (RubyHash)io;
|
78
|
+
io = null;
|
79
|
+
}
|
80
|
+
|
81
|
+
if (options != null) {
|
82
|
+
IRubyObject sk = options.fastARef(runtime.newSymbol("symbolize_keys"));
|
83
|
+
if (sk != null) {
|
84
|
+
symbolizeKeys = sk.isTrue();
|
78
85
|
}
|
79
|
-
|
80
|
-
|
86
|
+
IRubyObject f = options.fastARef(runtime.newSymbol("freeze"));
|
87
|
+
if (f != null) {
|
88
|
+
freeze = f.isTrue();
|
81
89
|
}
|
90
|
+
IRubyObject au = options.fastARef(runtime.newSymbol("allow_unknown_ext"));
|
91
|
+
if (au != null) {
|
92
|
+
allowUnknownExt = au.isTrue();
|
93
|
+
}
|
94
|
+
|
82
95
|
}
|
96
|
+
|
97
|
+
if (io != null && io != runtime.getNil()) {
|
98
|
+
setStream(ctx, io);
|
99
|
+
}
|
100
|
+
|
83
101
|
return this;
|
84
102
|
}
|
85
103
|
|
@@ -139,7 +157,7 @@ public class Unpacker extends RubyObject {
|
|
139
157
|
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
140
158
|
}
|
141
159
|
|
142
|
-
registry.put(extModule, (int) typeId, null, null, proc, arg);
|
160
|
+
registry.put(extModule, (int) typeId, false, null, null, proc, arg);
|
143
161
|
return runtime.getNil();
|
144
162
|
}
|
145
163
|
|
@@ -157,7 +175,7 @@ public class Unpacker extends RubyObject {
|
|
157
175
|
if (limit == -1) {
|
158
176
|
limit = byteList.length() - offset;
|
159
177
|
}
|
160
|
-
Decoder decoder = new Decoder(ctx.runtime,
|
178
|
+
Decoder decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
|
161
179
|
try {
|
162
180
|
data = null;
|
163
181
|
data = decoder.next();
|
@@ -187,7 +205,7 @@ public class Unpacker extends RubyObject {
|
|
187
205
|
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
188
206
|
ByteList byteList = data.asString().getByteList();
|
189
207
|
if (decoder == null) {
|
190
|
-
decoder = new Decoder(ctx.runtime,
|
208
|
+
decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
191
209
|
} else {
|
192
210
|
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
193
211
|
}
|
@@ -325,7 +343,11 @@ public class Unpacker extends RubyObject {
|
|
325
343
|
ByteList byteList = str.getByteList();
|
326
344
|
this.stream = stream;
|
327
345
|
this.decoder = null;
|
328
|
-
this.decoder = new Decoder(ctx.runtime,
|
346
|
+
this.decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
329
347
|
return getStream(ctx);
|
330
348
|
}
|
349
|
+
|
350
|
+
public ExtensionRegistry.ExtensionEntry lookupExtensionByTypeId(int typeId) {
|
351
|
+
return registry.lookupExtensionByTypeId(typeId);
|
352
|
+
}
|
331
353
|
}
|
data/ext/msgpack/buffer.h
CHANGED
@@ -494,9 +494,9 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
494
494
|
#endif // HAVE_RB_ENC_INTERNED_STR
|
495
495
|
}
|
496
496
|
|
497
|
-
static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_t length)
|
497
|
+
static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_t length, bool utf8)
|
498
498
|
{
|
499
|
-
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true,
|
499
|
+
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
|
500
500
|
}
|
501
501
|
|
502
502
|
#endif
|
data/ext/msgpack/buffer_class.c
CHANGED
@@ -29,6 +29,11 @@ static ID s_write;
|
|
29
29
|
static ID s_append;
|
30
30
|
static ID s_close;
|
31
31
|
|
32
|
+
static VALUE sym_read_reference_threshold;
|
33
|
+
static VALUE sym_write_reference_threshold;
|
34
|
+
static VALUE sym_io_buffer_size;
|
35
|
+
|
36
|
+
|
32
37
|
#define BUFFER(from, name) \
|
33
38
|
msgpack_buffer_t *name = NULL; \
|
34
39
|
Data_Get_Struct(from, msgpack_buffer_t, name); \
|
@@ -62,24 +67,22 @@ static VALUE Buffer_alloc(VALUE klass)
|
|
62
67
|
|
63
68
|
static ID get_partial_read_method(VALUE io)
|
64
69
|
{
|
65
|
-
if(rb_respond_to(io, s_readpartial)) {
|
70
|
+
if(io != Qnil && rb_respond_to(io, s_readpartial)) {
|
66
71
|
return s_readpartial;
|
67
|
-
} else if(rb_respond_to(io, s_read)) {
|
68
|
-
return s_read;
|
69
|
-
} else {
|
70
|
-
return s_read;
|
71
72
|
}
|
73
|
+
return s_read;
|
72
74
|
}
|
73
75
|
|
74
76
|
static ID get_write_all_method(VALUE io)
|
75
77
|
{
|
76
|
-
if(
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
if(io != Qnil) {
|
79
|
+
if(rb_respond_to(io, s_write)) {
|
80
|
+
return s_write;
|
81
|
+
} else if(rb_respond_to(io, s_append)) {
|
82
|
+
return s_append;
|
83
|
+
}
|
82
84
|
}
|
85
|
+
return s_write;
|
83
86
|
}
|
84
87
|
|
85
88
|
void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options)
|
@@ -91,17 +94,17 @@ void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options
|
|
91
94
|
if(options != Qnil) {
|
92
95
|
VALUE v;
|
93
96
|
|
94
|
-
v = rb_hash_aref(options,
|
97
|
+
v = rb_hash_aref(options, sym_read_reference_threshold);
|
95
98
|
if(v != Qnil) {
|
96
99
|
msgpack_buffer_set_read_reference_threshold(b, NUM2ULONG(v));
|
97
100
|
}
|
98
101
|
|
99
|
-
v = rb_hash_aref(options,
|
102
|
+
v = rb_hash_aref(options, sym_write_reference_threshold);
|
100
103
|
if(v != Qnil) {
|
101
104
|
msgpack_buffer_set_write_reference_threshold(b, NUM2ULONG(v));
|
102
105
|
}
|
103
106
|
|
104
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_io_buffer_size);
|
105
108
|
if(v != Qnil) {
|
106
109
|
msgpack_buffer_set_io_buffer_size(b, NUM2ULONG(v));
|
107
110
|
}
|
@@ -245,10 +248,11 @@ static VALUE read_until_eof_rescue(VALUE args)
|
|
245
248
|
return Qnil;
|
246
249
|
}
|
247
250
|
|
248
|
-
static VALUE read_until_eof_error(VALUE args)
|
251
|
+
static VALUE read_until_eof_error(VALUE args, VALUE error)
|
249
252
|
{
|
250
253
|
/* ignore EOFError */
|
251
254
|
UNUSED(args);
|
255
|
+
UNUSED(error);
|
252
256
|
return Qnil;
|
253
257
|
}
|
254
258
|
|
@@ -480,6 +484,10 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
|
|
480
484
|
s_append = rb_intern("<<");
|
481
485
|
s_close = rb_intern("close");
|
482
486
|
|
487
|
+
sym_read_reference_threshold = ID2SYM(rb_intern("read_reference_threshold"));
|
488
|
+
sym_write_reference_threshold = ID2SYM(rb_intern("write_reference_threshold"));
|
489
|
+
sym_io_buffer_size = ID2SYM(rb_intern("io_buffer_size"));
|
490
|
+
|
483
491
|
msgpack_buffer_static_init();
|
484
492
|
|
485
493
|
cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
|
data/ext/msgpack/factory_class.c
CHANGED
@@ -30,7 +30,8 @@ typedef struct msgpack_factory_t msgpack_factory_t;
|
|
30
30
|
|
31
31
|
struct msgpack_factory_t {
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
33
|
-
msgpack_unpacker_ext_registry_t ukrg;
|
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;
|
@@ -49,14 +50,14 @@ static void Factory_free(msgpack_factory_t* fc)
|
|
49
50
|
return;
|
50
51
|
}
|
51
52
|
msgpack_packer_ext_registry_destroy(&fc->pkrg);
|
52
|
-
|
53
|
+
msgpack_unpacker_ext_registry_release(fc->ukrg);
|
53
54
|
xfree(fc);
|
54
55
|
}
|
55
56
|
|
56
57
|
void Factory_mark(msgpack_factory_t* fc)
|
57
58
|
{
|
58
59
|
msgpack_packer_ext_registry_mark(&fc->pkrg);
|
59
|
-
msgpack_unpacker_ext_registry_mark(
|
60
|
+
msgpack_unpacker_ext_registry_mark(fc->ukrg);
|
60
61
|
}
|
61
62
|
|
62
63
|
static VALUE Factory_alloc(VALUE klass)
|
@@ -72,7 +73,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
|
72
73
|
FACTORY(self, fc);
|
73
74
|
|
74
75
|
msgpack_packer_ext_registry_init(&fc->pkrg);
|
75
|
-
|
76
|
+
// fc->ukrg is lazily initialized
|
76
77
|
|
77
78
|
fc->has_symbol_ext_type = false;
|
78
79
|
|
@@ -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;
|
@@ -113,9 +150,7 @@ VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
|
113
150
|
|
114
151
|
msgpack_unpacker_t* uk;
|
115
152
|
Data_Get_Struct(unpacker, msgpack_unpacker_t, uk);
|
116
|
-
|
117
|
-
msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
|
118
|
-
msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
|
153
|
+
msgpack_unpacker_ext_registry_borrow(fc->ukrg, &uk->ext_registry);
|
119
154
|
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
120
155
|
uk->symbol_ext_type = fc->symbol_ext_type;
|
121
156
|
|
@@ -127,12 +162,19 @@ static VALUE Factory_registered_types_internal(VALUE self)
|
|
127
162
|
FACTORY(self, fc);
|
128
163
|
|
129
164
|
VALUE uk_mapping = rb_hash_new();
|
130
|
-
|
131
|
-
|
132
|
-
|
165
|
+
if (fc->ukrg) {
|
166
|
+
for(int i=0; i < 256; i++) {
|
167
|
+
if(fc->ukrg->array[i] != Qnil) {
|
168
|
+
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
|
169
|
+
}
|
133
170
|
}
|
134
171
|
}
|
135
|
-
|
172
|
+
|
173
|
+
return rb_ary_new3(
|
174
|
+
2,
|
175
|
+
RTEST(fc->pkrg.hash) ? rb_hash_dup(fc->pkrg.hash) : rb_hash_new(),
|
176
|
+
uk_mapping
|
177
|
+
);
|
136
178
|
}
|
137
179
|
|
138
180
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -140,6 +182,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
140
182
|
FACTORY(self, fc);
|
141
183
|
|
142
184
|
int ext_type;
|
185
|
+
int flags = 0;
|
143
186
|
VALUE ext_module;
|
144
187
|
VALUE options = Qnil;
|
145
188
|
VALUE packer_arg, unpacker_arg;
|
@@ -168,6 +211,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
168
211
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
169
212
|
}
|
170
213
|
|
214
|
+
if (options != Qnil) {
|
215
|
+
Check_Type(options, T_HASH);
|
216
|
+
}
|
217
|
+
|
171
218
|
ext_type = NUM2INT(argv[0]);
|
172
219
|
if(ext_type < -128 || ext_type > 127) {
|
173
220
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
@@ -195,16 +242,29 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
195
242
|
}
|
196
243
|
}
|
197
244
|
|
198
|
-
|
199
|
-
|
200
|
-
if (ext_module == rb_cSymbol) {
|
245
|
+
if(ext_module == rb_cSymbol) {
|
201
246
|
fc->has_symbol_ext_type = true;
|
202
|
-
if(
|
247
|
+
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
203
248
|
fc->optimized_symbol_ext_type = true;
|
204
249
|
}
|
205
250
|
}
|
206
251
|
|
207
|
-
|
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);
|
208
268
|
|
209
269
|
return Qnil;
|
210
270
|
}
|
@@ -216,6 +276,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
|
|
216
276
|
rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
|
217
277
|
|
218
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);
|
219
281
|
|
220
282
|
rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
|
221
283
|
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
|
data/ext/msgpack/packer.c
CHANGED
@@ -121,19 +121,56 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
121
121
|
#endif
|
122
122
|
}
|
123
123
|
|
124
|
+
struct msgpack_call_proc_args_t;
|
125
|
+
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
|
126
|
+
struct msgpack_call_proc_args_t {
|
127
|
+
VALUE proc;
|
128
|
+
VALUE arg;
|
129
|
+
VALUE packer;
|
130
|
+
};
|
131
|
+
|
132
|
+
VALUE msgpack_packer_try_calling_proc(VALUE value)
|
133
|
+
{
|
134
|
+
msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
|
135
|
+
return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
|
136
|
+
}
|
137
|
+
|
124
138
|
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
125
139
|
{
|
126
|
-
int ext_type;
|
140
|
+
int ext_type, ext_flags;
|
127
141
|
|
128
|
-
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type);
|
142
|
+
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
|
129
143
|
|
130
|
-
if(proc
|
144
|
+
if(proc == Qnil) {
|
145
|
+
return false;
|
146
|
+
}
|
147
|
+
|
148
|
+
if(ext_flags & MSGPACK_EXT_RECURSIVE) {
|
149
|
+
msgpack_buffer_t parent_buffer = pk->buffer;
|
150
|
+
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
151
|
+
|
152
|
+
int exception_occured = 0;
|
153
|
+
msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
|
154
|
+
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
|
155
|
+
|
156
|
+
if (exception_occured) {
|
157
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
158
|
+
pk->buffer = parent_buffer;
|
159
|
+
rb_jump_tag(exception_occured); // re-raise the exception
|
160
|
+
} else {
|
161
|
+
VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
|
162
|
+
StringValue(payload);
|
163
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
164
|
+
pk->buffer = parent_buffer;
|
165
|
+
msgpack_packer_write_ext(pk, ext_type, payload);
|
166
|
+
}
|
167
|
+
} else {
|
131
168
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
169
|
StringValue(payload);
|
133
170
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
return true;
|
135
171
|
}
|
136
|
-
|
172
|
+
|
173
|
+
return true;
|
137
174
|
}
|
138
175
|
|
139
176
|
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
|
{
|
@@ -469,9 +472,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
469
472
|
|
470
473
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
471
474
|
{
|
475
|
+
int leading_zero_bits;
|
476
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
477
|
+
|
472
478
|
if(RBIGNUM_POSITIVE_P(v)) {
|
479
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
480
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
484
|
+
}
|
485
|
+
|
473
486
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
474
487
|
} else {
|
488
|
+
if(leading_zero_bits == 0) {
|
489
|
+
required_size += 1;
|
490
|
+
}
|
491
|
+
|
492
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
493
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
494
|
+
return;
|
495
|
+
}
|
496
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
497
|
+
}
|
498
|
+
|
475
499
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
476
500
|
}
|
477
501
|
}
|