msgpack 1.4.2 → 1.4.3
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 +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
|
|