msgpack 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +56 -0
- data/ChangeLog +8 -0
- data/Rakefile +2 -2
- data/doclib/msgpack/factory.rb +1 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +17 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +6 -2
- data/ext/java/org/msgpack/jruby/Encoder.java +22 -12
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +9 -9
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
- data/ext/java/org/msgpack/jruby/Factory.java +7 -2
- data/ext/java/org/msgpack/jruby/Packer.java +11 -9
- data/ext/java/org/msgpack/jruby/Unpacker.java +30 -28
- data/ext/msgpack/buffer.c +0 -5
- data/ext/msgpack/buffer.h +5 -0
- data/ext/msgpack/extconf.rb +0 -7
- data/ext/msgpack/factory_class.c +10 -5
- data/ext/msgpack/packer.c +18 -5
- data/ext/msgpack/packer.h +0 -9
- data/ext/msgpack/packer_class.c +0 -9
- data/ext/msgpack/packer_ext_registry.c +0 -22
- data/ext/msgpack/unpacker.c +28 -22
- data/ext/msgpack/unpacker.h +2 -0
- data/ext/msgpack/unpacker_class.c +0 -5
- data/lib/msgpack/symbol.rb +14 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +1 -2
- data/spec/factory_spec.rb +17 -0
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/timestamp_spec.rb +40 -0
- data/spec/unpacker_spec.rb +10 -1
- metadata +4 -4
- data/.travis.yml +0 -39
@@ -27,6 +27,7 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
27
27
|
|
28
28
|
@JRubyClass(name="MessagePack::Unpacker")
|
29
29
|
public class Unpacker extends RubyObject {
|
30
|
+
private static final long serialVersionUID = 8451264671199362492L;
|
30
31
|
private final ExtensionRegistry registry;
|
31
32
|
|
32
33
|
private IRubyObject stream;
|
@@ -59,22 +60,23 @@ public class Unpacker extends RubyObject {
|
|
59
60
|
allowUnknownExt = false;
|
60
61
|
freeze = false;
|
61
62
|
if (args.length > 0) {
|
63
|
+
Ruby runtime = ctx.runtime;
|
62
64
|
if (args[args.length - 1] instanceof RubyHash) {
|
63
65
|
RubyHash options = (RubyHash) args[args.length - 1];
|
64
|
-
IRubyObject sk = options.fastARef(
|
66
|
+
IRubyObject sk = options.fastARef(runtime.newSymbol("symbolize_keys"));
|
65
67
|
if (sk != null) {
|
66
68
|
symbolizeKeys = sk.isTrue();
|
67
69
|
}
|
68
|
-
IRubyObject f = options.fastARef(
|
70
|
+
IRubyObject f = options.fastARef(runtime.newSymbol("freeze"));
|
69
71
|
if (f != null) {
|
70
72
|
freeze = f.isTrue();
|
71
73
|
}
|
72
|
-
IRubyObject au = options.fastARef(
|
74
|
+
IRubyObject au = options.fastARef(runtime.newSymbol("allow_unknown_ext"));
|
73
75
|
if (au != null) {
|
74
76
|
allowUnknownExt = au.isTrue();
|
75
77
|
}
|
76
78
|
}
|
77
|
-
if (args[0] !=
|
79
|
+
if (args[0] != runtime.getNil() && !(args[0] instanceof RubyHash)) {
|
78
80
|
setStream(ctx, args[0]);
|
79
81
|
}
|
80
82
|
}
|
@@ -82,24 +84,24 @@ public class Unpacker extends RubyObject {
|
|
82
84
|
}
|
83
85
|
|
84
86
|
public static Unpacker newUnpacker(ThreadContext ctx, ExtensionRegistry extRegistry, IRubyObject[] args) {
|
85
|
-
Unpacker unpacker = new Unpacker(ctx.
|
87
|
+
Unpacker unpacker = new Unpacker(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Unpacker"), extRegistry);
|
86
88
|
unpacker.initialize(ctx, args);
|
87
89
|
return unpacker;
|
88
90
|
}
|
89
91
|
|
90
92
|
@JRubyMethod(name = "symbolize_keys?")
|
91
93
|
public IRubyObject isSymbolizeKeys(ThreadContext ctx) {
|
92
|
-
return symbolizeKeys ? ctx.
|
94
|
+
return symbolizeKeys ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
93
95
|
}
|
94
96
|
|
95
97
|
@JRubyMethod(name = "freeze?")
|
96
98
|
public IRubyObject isFreeze(ThreadContext ctx) {
|
97
|
-
return freeze ? ctx.
|
99
|
+
return freeze ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
98
100
|
}
|
99
101
|
|
100
102
|
@JRubyMethod(name = "allow_unknown_ext?")
|
101
103
|
public IRubyObject isAllowUnknownExt(ThreadContext ctx) {
|
102
|
-
return allowUnknownExt ? ctx.
|
104
|
+
return allowUnknownExt ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
103
105
|
}
|
104
106
|
|
105
107
|
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
|
@@ -109,7 +111,7 @@ public class Unpacker extends RubyObject {
|
|
109
111
|
|
110
112
|
@JRubyMethod(name = "register_type", required = 1, optional = 2)
|
111
113
|
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
112
|
-
Ruby runtime = ctx.
|
114
|
+
Ruby runtime = ctx.runtime;
|
113
115
|
IRubyObject type = args[0];
|
114
116
|
|
115
117
|
RubyModule extModule;
|
@@ -155,7 +157,7 @@ public class Unpacker extends RubyObject {
|
|
155
157
|
if (limit == -1) {
|
156
158
|
limit = byteList.length() - offset;
|
157
159
|
}
|
158
|
-
Decoder decoder = new Decoder(ctx.
|
160
|
+
Decoder decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
|
159
161
|
try {
|
160
162
|
data = null;
|
161
163
|
data = decoder.next();
|
@@ -164,13 +166,13 @@ public class Unpacker extends RubyObject {
|
|
164
166
|
throw re;
|
165
167
|
}
|
166
168
|
}
|
167
|
-
return ctx.
|
169
|
+
return ctx.runtime.newFixnum(decoder.offset());
|
168
170
|
}
|
169
171
|
|
170
172
|
@JRubyMethod(name = "data")
|
171
173
|
public IRubyObject getData(ThreadContext ctx) {
|
172
174
|
if (data == null) {
|
173
|
-
return ctx.
|
175
|
+
return ctx.runtime.getNil();
|
174
176
|
} else {
|
175
177
|
return data;
|
176
178
|
}
|
@@ -178,14 +180,14 @@ public class Unpacker extends RubyObject {
|
|
178
180
|
|
179
181
|
@JRubyMethod(name = "finished?")
|
180
182
|
public IRubyObject finished_p(ThreadContext ctx) {
|
181
|
-
return data == null ? ctx.
|
183
|
+
return data == null ? ctx.runtime.getFalse() : ctx.runtime.getTrue();
|
182
184
|
}
|
183
185
|
|
184
186
|
@JRubyMethod(required = 1, name = "feed", alias = { "feed_reference" })
|
185
187
|
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
186
188
|
ByteList byteList = data.asString().getByteList();
|
187
189
|
if (decoder == null) {
|
188
|
-
decoder = new Decoder(ctx.
|
190
|
+
decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
189
191
|
} else {
|
190
192
|
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
191
193
|
}
|
@@ -202,7 +204,7 @@ public class Unpacker extends RubyObject {
|
|
202
204
|
feed(ctx, data);
|
203
205
|
if (block.isGiven()) {
|
204
206
|
each(ctx, block);
|
205
|
-
return ctx.
|
207
|
+
return ctx.runtime.getNil();
|
206
208
|
} else {
|
207
209
|
return callMethod(ctx, "to_enum");
|
208
210
|
}
|
@@ -230,7 +232,7 @@ public class Unpacker extends RubyObject {
|
|
230
232
|
|
231
233
|
@JRubyMethod
|
232
234
|
public IRubyObject fill(ThreadContext ctx) {
|
233
|
-
return ctx.
|
235
|
+
return ctx.runtime.getNil();
|
234
236
|
}
|
235
237
|
|
236
238
|
@JRubyMethod
|
@@ -238,13 +240,13 @@ public class Unpacker extends RubyObject {
|
|
238
240
|
if (decoder != null) {
|
239
241
|
decoder.reset();
|
240
242
|
}
|
241
|
-
return ctx.
|
243
|
+
return ctx.runtime.getNil();
|
242
244
|
}
|
243
245
|
|
244
246
|
@JRubyMethod(name = "read", alias = { "unpack" })
|
245
247
|
public IRubyObject read(ThreadContext ctx) {
|
246
248
|
if (decoder == null) {
|
247
|
-
throw ctx.
|
249
|
+
throw ctx.runtime.newEOFError();
|
248
250
|
}
|
249
251
|
try {
|
250
252
|
return decoder.next();
|
@@ -252,19 +254,19 @@ public class Unpacker extends RubyObject {
|
|
252
254
|
if (re.getException().getType() != underflowErrorClass) {
|
253
255
|
throw re;
|
254
256
|
} else {
|
255
|
-
throw ctx.
|
257
|
+
throw ctx.runtime.newEOFError();
|
256
258
|
}
|
257
259
|
}
|
258
260
|
}
|
259
261
|
|
260
262
|
@JRubyMethod(name = "skip")
|
261
263
|
public IRubyObject skip(ThreadContext ctx) {
|
262
|
-
throw ctx.
|
264
|
+
throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
|
263
265
|
}
|
264
266
|
|
265
267
|
@JRubyMethod(name = "skip_nil")
|
266
268
|
public IRubyObject skipNil(ThreadContext ctx) {
|
267
|
-
throw ctx.
|
269
|
+
throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
|
268
270
|
}
|
269
271
|
|
270
272
|
@JRubyMethod
|
@@ -276,11 +278,11 @@ public class Unpacker extends RubyObject {
|
|
276
278
|
if (re.getException().getType() != underflowErrorClass) {
|
277
279
|
throw re;
|
278
280
|
} else {
|
279
|
-
throw ctx.
|
281
|
+
throw ctx.runtime.newEOFError();
|
280
282
|
}
|
281
283
|
}
|
282
284
|
}
|
283
|
-
return ctx.
|
285
|
+
return ctx.runtime.getNil();
|
284
286
|
}
|
285
287
|
|
286
288
|
@JRubyMethod
|
@@ -292,17 +294,17 @@ public class Unpacker extends RubyObject {
|
|
292
294
|
if (re.getException().getType() != underflowErrorClass) {
|
293
295
|
throw re;
|
294
296
|
} else {
|
295
|
-
throw ctx.
|
297
|
+
throw ctx.runtime.newEOFError();
|
296
298
|
}
|
297
299
|
}
|
298
300
|
}
|
299
|
-
return ctx.
|
301
|
+
return ctx.runtime.getNil();
|
300
302
|
}
|
301
303
|
|
302
304
|
@JRubyMethod(name = "stream")
|
303
305
|
public IRubyObject getStream(ThreadContext ctx) {
|
304
306
|
if (stream == null) {
|
305
|
-
return ctx.
|
307
|
+
return ctx.runtime.getNil();
|
306
308
|
} else {
|
307
309
|
return stream;
|
308
310
|
}
|
@@ -318,12 +320,12 @@ public class Unpacker extends RubyObject {
|
|
318
320
|
} else if (stream.respondsTo("read")) {
|
319
321
|
str = stream.callMethod(ctx, "read").asString();
|
320
322
|
} else {
|
321
|
-
throw ctx.
|
323
|
+
throw ctx.runtime.newTypeError(stream, "IO");
|
322
324
|
}
|
323
325
|
ByteList byteList = str.getByteList();
|
324
326
|
this.stream = stream;
|
325
327
|
this.decoder = null;
|
326
|
-
this.decoder = new Decoder(ctx.
|
328
|
+
this.decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
327
329
|
return getStream(ctx);
|
328
330
|
}
|
329
331
|
}
|
data/ext/msgpack/buffer.c
CHANGED
@@ -164,12 +164,7 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
|
|
164
164
|
b->head->mapped_string != NO_MAPPED_STRING &&
|
165
165
|
length >= b->read_reference_threshold) {
|
166
166
|
VALUE s = _msgpack_buffer_refer_head_mapped_string(b, length);
|
167
|
-
#ifndef HAVE_RB_STR_REPLACE
|
168
|
-
/* TODO MRI 1.8 */
|
169
|
-
rb_funcall(string, s_replace, 1, s);
|
170
|
-
#else
|
171
167
|
rb_str_replace(string, s);
|
172
|
-
#endif
|
173
168
|
/* here doesn't have to call ENCODING_SET because
|
174
169
|
* encoding of s is always ASCII-8BIT */
|
175
170
|
_msgpack_buffer_consumed(b, length);
|
data/ext/msgpack/buffer.h
CHANGED
@@ -494,4 +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)
|
498
|
+
{
|
499
|
+
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, false));
|
500
|
+
}
|
501
|
+
|
497
502
|
#endif
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -2,14 +2,7 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
have_header("ruby/st.h")
|
4
4
|
have_header("st.h")
|
5
|
-
have_func("rb_str_replace", ["ruby.h"])
|
6
|
-
have_func("rb_intern_str", ["ruby.h"])
|
7
5
|
have_func("rb_enc_interned_str", "ruby.h")
|
8
|
-
have_func("rb_sym2str", ["ruby.h"])
|
9
|
-
have_func("rb_str_intern", ["ruby.h"])
|
10
|
-
have_func("rb_block_lambda", ["ruby.h"])
|
11
|
-
have_func("rb_hash_dup", ["ruby.h"])
|
12
|
-
have_func("rb_hash_clear", ["ruby.h"])
|
13
6
|
|
14
7
|
unless RUBY_PLATFORM.include? 'mswin'
|
15
8
|
$CFLAGS << %[ -I.. -Wall -O3 -g -std=gnu99]
|
data/ext/msgpack/factory_class.c
CHANGED
@@ -32,6 +32,8 @@ struct msgpack_factory_t {
|
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
33
33
|
msgpack_unpacker_ext_registry_t ukrg;
|
34
34
|
bool has_symbol_ext_type;
|
35
|
+
bool optimized_symbol_ext_type;
|
36
|
+
int symbol_ext_type;
|
35
37
|
};
|
36
38
|
|
37
39
|
#define FACTORY(from, name) \
|
@@ -114,6 +116,8 @@ VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
|
114
116
|
|
115
117
|
msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
|
116
118
|
msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
|
119
|
+
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
120
|
+
uk->symbol_ext_type = fc->symbol_ext_type;
|
117
121
|
|
118
122
|
return unpacker;
|
119
123
|
}
|
@@ -128,11 +132,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
|
|
128
132
|
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg.array[i]);
|
129
133
|
}
|
130
134
|
}
|
131
|
-
#ifdef HAVE_RB_HASH_DUP
|
132
135
|
return rb_ary_new3(2, rb_hash_dup(fc->pkrg.hash), uk_mapping);
|
133
|
-
#else
|
134
|
-
return rb_ary_new3(2, rb_funcall(fc->pkrg.hash, rb_intern("dup"), 0), uk_mapping);
|
135
|
-
#endif
|
136
136
|
}
|
137
137
|
|
138
138
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -141,7 +141,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
141
141
|
|
142
142
|
int ext_type;
|
143
143
|
VALUE ext_module;
|
144
|
-
VALUE options;
|
144
|
+
VALUE options = Qnil;
|
145
145
|
VALUE packer_arg, unpacker_arg;
|
146
146
|
VALUE packer_proc, unpacker_proc;
|
147
147
|
|
@@ -188,6 +188,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
188
188
|
if(unpacker_arg != Qnil) {
|
189
189
|
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
|
190
190
|
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
|
191
|
+
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
|
192
|
+
unpacker_proc = unpacker_arg;
|
191
193
|
} else {
|
192
194
|
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
|
193
195
|
}
|
@@ -197,6 +199,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
197
199
|
|
198
200
|
if (ext_module == rb_cSymbol) {
|
199
201
|
fc->has_symbol_ext_type = true;
|
202
|
+
if(RB_TEST(options) && RB_TEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
203
|
+
fc->optimized_symbol_ext_type = true;
|
204
|
+
}
|
200
205
|
}
|
201
206
|
|
202
207
|
msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, unpacker_proc, unpacker_arg);
|
data/ext/msgpack/packer.c
CHANGED
@@ -121,7 +121,7 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
121
121
|
#endif
|
122
122
|
}
|
123
123
|
|
124
|
-
|
124
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
125
125
|
{
|
126
126
|
int ext_type;
|
127
127
|
|
@@ -131,7 +131,14 @@ void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
|
131
131
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
132
|
StringValue(payload);
|
133
133
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
|
134
|
+
return true;
|
135
|
+
}
|
136
|
+
return false;
|
137
|
+
}
|
138
|
+
|
139
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
140
|
+
{
|
141
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
135
142
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
136
143
|
}
|
137
144
|
}
|
@@ -155,13 +162,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
155
162
|
msgpack_packer_write_symbol_value(pk, v);
|
156
163
|
break;
|
157
164
|
case T_STRING:
|
158
|
-
|
165
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
166
|
+
msgpack_packer_write_string_value(pk, v);
|
167
|
+
}
|
159
168
|
break;
|
160
169
|
case T_ARRAY:
|
161
|
-
|
170
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
171
|
+
msgpack_packer_write_array_value(pk, v);
|
172
|
+
}
|
162
173
|
break;
|
163
174
|
case T_HASH:
|
164
|
-
|
175
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
176
|
+
msgpack_packer_write_hash_value(pk, v);
|
177
|
+
}
|
165
178
|
break;
|
166
179
|
case T_BIGNUM:
|
167
180
|
msgpack_packer_write_bignum_value(pk, v);
|
data/ext/msgpack/packer.h
CHANGED
@@ -444,16 +444,7 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
444
444
|
|
445
445
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
446
446
|
{
|
447
|
-
#ifdef HAVE_RB_SYM2STR
|
448
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
449
447
|
msgpack_packer_write_string_value(pk, rb_sym2str(v));
|
450
|
-
#else
|
451
|
-
VALUE str = rb_id2str(SYM2ID(v));
|
452
|
-
if (!str) {
|
453
|
-
rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
|
454
|
-
}
|
455
|
-
msgpack_packer_write_string_value(pk, str);
|
456
|
-
#endif
|
457
448
|
}
|
458
449
|
|
459
450
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
data/ext/msgpack/packer_class.c
CHANGED
@@ -339,11 +339,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
339
339
|
static VALUE Packer_registered_types_internal(VALUE self)
|
340
340
|
{
|
341
341
|
PACKER(self, pk);
|
342
|
-
#ifdef HAVE_RB_HASH_DUP
|
343
342
|
return rb_hash_dup(pk->ext_registry.hash);
|
344
|
-
#else
|
345
|
-
return rb_funcall(pk->ext_registry.hash, rb_intern("dup"), 0);
|
346
|
-
#endif
|
347
343
|
}
|
348
344
|
|
349
345
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -359,12 +355,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
359
355
|
case 2:
|
360
356
|
/* register_type(0x7f, Time) {|obj| block... } */
|
361
357
|
rb_need_block();
|
362
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
363
358
|
proc = rb_block_lambda();
|
364
|
-
#else
|
365
|
-
/* MRI 1.8 */
|
366
|
-
proc = rb_block_proc();
|
367
|
-
#endif
|
368
359
|
arg = proc;
|
369
360
|
break;
|
370
361
|
case 3:
|
@@ -43,37 +43,15 @@ 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
|
-
#ifdef HAVE_RB_HASH_DUP
|
47
46
|
dst->hash = rb_hash_dup(src->hash);
|
48
47
|
dst->cache = rb_hash_dup(src->cache);
|
49
|
-
#else
|
50
|
-
dst->hash = rb_funcall(src->hash, rb_intern("dup"), 0);
|
51
|
-
dst->cache = rb_funcall(src->cache, rb_intern("dup"), 0);
|
52
|
-
#endif
|
53
48
|
}
|
54
49
|
|
55
|
-
#ifndef HAVE_RB_HASH_CLEAR
|
56
|
-
|
57
|
-
static int
|
58
|
-
__rb_hash_clear_clear_i(key, value, dummy)
|
59
|
-
VALUE key, value, dummy;
|
60
|
-
{
|
61
|
-
return ST_DELETE;
|
62
|
-
}
|
63
|
-
|
64
|
-
#endif
|
65
|
-
|
66
50
|
VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
|
67
51
|
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
68
52
|
{
|
69
53
|
VALUE e = rb_ary_new3(3, INT2FIX(ext_type), proc, arg);
|
70
54
|
/* clear lookup cache not to miss added type */
|
71
|
-
#ifdef HAVE_RB_HASH_CLEAR
|
72
55
|
rb_hash_clear(pkrg->cache);
|
73
|
-
#else
|
74
|
-
if(FIX2INT(rb_funcall(pkrg->cache, rb_intern("size"), 0)) > 0) {
|
75
|
-
rb_hash_foreach(pkrg->cache, __rb_hash_clear_clear_i, 0);
|
76
|
-
}
|
77
|
-
#endif
|
78
56
|
return rb_hash_aset(pkrg->hash, ext_module, e);
|
79
57
|
}
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -151,8 +151,19 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
|
|
151
151
|
return PRIMITIVE_OBJECT_COMPLETE;
|
152
152
|
}
|
153
153
|
|
154
|
+
static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
155
|
+
{
|
156
|
+
uk->last_object = object;
|
157
|
+
reset_head_byte(uk);
|
158
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
159
|
+
}
|
160
|
+
|
154
161
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
155
162
|
{
|
163
|
+
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
164
|
+
return object_complete_symbol(uk, rb_str_intern(str));
|
165
|
+
}
|
166
|
+
|
156
167
|
VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
|
157
168
|
if(proc != Qnil) {
|
158
169
|
VALUE obj = rb_funcall(proc, s_call, 1, str);
|
@@ -273,22 +284,27 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
273
284
|
/* try optimized read */
|
274
285
|
size_t length = uk->reading_raw_remaining;
|
275
286
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
276
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
277
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
278
|
-
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
279
|
-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
280
287
|
int ret;
|
281
|
-
if(
|
282
|
-
|
288
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
289
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length);
|
290
|
+
ret = object_complete_symbol(uk, symbol);
|
283
291
|
} else {
|
284
|
-
|
285
|
-
|
292
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
293
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
294
|
+
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
295
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
296
|
+
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
297
|
+
ret = object_complete(uk, string);
|
298
|
+
} else {
|
299
|
+
ret = object_complete_ext(uk, raw_type, string);
|
300
|
+
}
|
286
301
|
|
287
302
|
# if !HASH_ASET_DEDUPE
|
288
|
-
|
289
|
-
|
290
|
-
|
303
|
+
if(will_freeze) {
|
304
|
+
rb_obj_freeze(string);
|
305
|
+
}
|
291
306
|
# endif
|
307
|
+
}
|
292
308
|
uk->reading_raw_remaining = 0;
|
293
309
|
return ret;
|
294
310
|
}
|
@@ -705,18 +721,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
705
721
|
break;
|
706
722
|
case STACK_TYPE_MAP_VALUE:
|
707
723
|
if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
|
708
|
-
/* here uses
|
709
|
-
#ifdef HAVE_RB_STR_INTERN
|
710
|
-
/* rb_str_intern is added since MRI 2.2.0 */
|
724
|
+
/* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
|
711
725
|
rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
|
712
|
-
#else
|
713
|
-
#ifndef HAVE_RB_INTERN_STR
|
714
|
-
/* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
|
715
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
|
716
|
-
#else
|
717
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
|
718
|
-
#endif
|
719
|
-
#endif
|
720
726
|
} else {
|
721
727
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
722
728
|
}
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -369,12 +369,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
369
369
|
case 1:
|
370
370
|
/* register_type(0x7f) {|data| block... } */
|
371
371
|
rb_need_block();
|
372
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
373
372
|
proc = rb_block_lambda();
|
374
|
-
#else
|
375
|
-
/* MRI 1.8 */
|
376
|
-
proc = rb_block_proc();
|
377
|
-
#endif
|
378
373
|
arg = proc;
|
379
374
|
ext_module = Qnil;
|
380
375
|
break;
|
data/lib/msgpack/symbol.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
class Symbol
|
2
|
-
|
3
|
-
|
2
|
+
# to_msgpack_ext is supposed to return a binary string.
|
3
|
+
# The canonical way to do it for symbols would be:
|
4
|
+
# [to_s].pack('A*')
|
5
|
+
# However in this instance we can take a shortcut
|
6
|
+
if method_defined?(:name)
|
7
|
+
alias_method :to_msgpack_ext, :name
|
8
|
+
else
|
9
|
+
alias_method :to_msgpack_ext, :to_s
|
4
10
|
end
|
5
11
|
|
6
12
|
def self.from_msgpack_ext(data)
|
7
|
-
|
13
|
+
# from_msgpack_ext is supposed to parse a binary string.
|
14
|
+
# The canonical way to do it for symbols would be:
|
15
|
+
# data.unpack1('A*').to_sym
|
16
|
+
# However in this instance we can take a shortcut
|
17
|
+
data.to_sym
|
8
18
|
end
|
9
|
-
end
|
19
|
+
end
|
data/lib/msgpack/time.rb
CHANGED
data/lib/msgpack/version.rb
CHANGED
data/lib/msgpack.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require "msgpack/version"
|
2
2
|
|
3
3
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" # This is same with `/java/ =~ RUBY_VERSION`
|
4
|
-
require "java"
|
5
4
|
require "msgpack/msgpack.jar"
|
6
|
-
org.msgpack.jruby.MessagePackLibrary
|
5
|
+
JRuby::Util.load_ext("org.msgpack.jruby.MessagePackLibrary")
|
7
6
|
else
|
8
7
|
require "msgpack/msgpack"
|
9
8
|
end
|
data/spec/factory_spec.rb
CHANGED
@@ -280,6 +280,23 @@ describe MessagePack::Factory do
|
|
280
280
|
unpacker.feed(packed_symbol).unpack
|
281
281
|
end
|
282
282
|
|
283
|
+
context 'using the optimized symbol unpacker' do
|
284
|
+
before do
|
285
|
+
skip if IS_JRUBY # JRuby implementation doesn't support the optimized symbols unpacker for now
|
286
|
+
subject.register_type(
|
287
|
+
0x00,
|
288
|
+
::Symbol,
|
289
|
+
packer: :to_msgpack_ext,
|
290
|
+
unpacker: :from_msgpack_ext,
|
291
|
+
optimized_symbols_parsing: true,
|
292
|
+
)
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'lets symbols survive a roundtrip' do
|
296
|
+
expect(symbol_after_roundtrip).to be :symbol
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
283
300
|
context 'if no ext type is registered for symbols' do
|
284
301
|
it 'converts symbols to string' do
|
285
302
|
expect(symbol_after_roundtrip).to eq 'symbol'
|
data/spec/msgpack_spec.rb
CHANGED
@@ -115,7 +115,7 @@ describe MessagePack do
|
|
115
115
|
expect { MessagePack.pack(self) }.to raise_error(NoMethodError, /^undefined method `to_msgpack'/)
|
116
116
|
end
|
117
117
|
|
118
|
-
it '
|
118
|
+
it 'raises an error on #unpack with garbage' do
|
119
119
|
skip "but nothing was raised. why?"
|
120
120
|
expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
|
121
121
|
end
|
data/spec/packer_spec.rb
CHANGED
@@ -488,6 +488,24 @@ describe MessagePack::Packer do
|
|
488
488
|
it { is_expected.to eq "\xC7\x0F\x01value_msgpacked" }
|
489
489
|
end
|
490
490
|
|
491
|
+
shared_examples_for 'extension subclasses core type' do |klass|
|
492
|
+
before { stub_const('Value', Class.new(klass)) }
|
493
|
+
let(:object) { Value.new }
|
494
|
+
subject { packer.pack(object).to_s }
|
495
|
+
|
496
|
+
it "defaults to #{klass.name} packer if no extension is present" do
|
497
|
+
expect(subject).to eq(MessagePack.dump(klass.new))
|
498
|
+
end
|
499
|
+
|
500
|
+
it "uses core type extension for #{klass.name}" do
|
501
|
+
packer.register_type(0x01, Value, ->(_) { 'value_msgpacked' })
|
502
|
+
expect(subject).to eq("\xC7\x0F\x01value_msgpacked")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
it_behaves_like 'extension subclasses core type', Hash
|
506
|
+
it_behaves_like 'extension subclasses core type', Array
|
507
|
+
it_behaves_like 'extension subclasses core type', String
|
508
|
+
|
491
509
|
context 'when registering a type for symbols' do
|
492
510
|
before { packer.register_type(0x00, ::Symbol, :to_msgpack_ext) }
|
493
511
|
|