msgpack-jruby 1.1.3-java → 1.2.0-java
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.
- data/Rakefile +3 -2
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +21 -11
- data/ext/java/org/msgpack/jruby/RubyObjectPacker.java +36 -37
- data/ext/java/org/msgpack/jruby/RubyObjectUnpacker.java +33 -11
- data/lib/ext/msgpack_jruby.jar +0 -0
- data/lib/msgpack/version.rb +1 -1
- data/spec/{benchmark.rb → benchmarks/shootout_bm.rb} +1 -1
- data/spec/benchmarks/symbolize_keys_bm.rb +25 -0
- data/spec/msgpack/unpacker_spec.rb +34 -0
- data/spec/msgpack_spec.rb +8 -0
- metadata +4 -3
data/Rakefile
CHANGED
@@ -31,16 +31,17 @@ end
|
|
31
31
|
namespace :benchmark do
|
32
32
|
BENCHMARK_RUBIES = ['1.9.2-p0', 'jruby-1.6.5', 'jruby-head']
|
33
33
|
BENCHMARK_GEMSET = 'msgpack-jruby-benchmarking'
|
34
|
+
BENCHMARK_FILE = 'spec/benchmarks/shootout_bm.rb'
|
34
35
|
|
35
36
|
task :run do
|
36
37
|
rubies = BENCHMARK_RUBIES.map { |rb| "#{rb}@#{BENCHMARK_GEMSET}" }
|
37
|
-
cmd = %(rvm #{rubies.join(',')} exec viiite run
|
38
|
+
cmd = %(rvm #{rubies.join(',')} exec viiite run #{BENCHMARK_FILE} | tee benchmark | viiite report --hierarchy --regroup=bench,lib,ruby)
|
38
39
|
puts cmd
|
39
40
|
system cmd
|
40
41
|
end
|
41
42
|
|
42
43
|
task :quick do
|
43
|
-
cmd = %(IMPLEMENTATIONS=msgpack viiite run
|
44
|
+
cmd = %(IMPLEMENTATIONS=msgpack viiite run #{BENCHMARK_FILE} | viiite report --hierarchy --regroup=bench)
|
44
45
|
puts cmd
|
45
46
|
system cmd
|
46
47
|
end
|
@@ -10,6 +10,7 @@ import org.jruby.RubyModule;
|
|
10
10
|
import org.jruby.RubyClass;
|
11
11
|
import org.jruby.RubyString;
|
12
12
|
import org.jruby.RubyObject;
|
13
|
+
import org.jruby.RubyHash;
|
13
14
|
import org.jruby.RubyIO;
|
14
15
|
import org.jruby.RubyStringIO;
|
15
16
|
import org.jruby.RubyNumeric;
|
@@ -54,18 +55,19 @@ public class MessagePackLibrary implements Library {
|
|
54
55
|
@JRubyModule(name = "MessagePack")
|
55
56
|
public static class MessagePackModule {
|
56
57
|
private static MessagePack msgPack = new MessagePack();
|
58
|
+
private static RubyObjectPacker packer = new RubyObjectPacker(msgPack);
|
57
59
|
private static RubyObjectUnpacker unpacker = new RubyObjectUnpacker(msgPack);
|
58
60
|
|
59
61
|
@JRubyMethod(module = true, required = 1)
|
60
62
|
public static IRubyObject pack(ThreadContext ctx, IRubyObject recv, IRubyObject obj) throws IOException {
|
61
|
-
|
62
|
-
Packer packer = new RubyObjectPacker(msgPack, bufferedPacker).write(obj);
|
63
|
-
return RubyString.newString(ctx.getRuntime(), bufferedPacker.toByteArray());
|
63
|
+
return packer.pack(obj);
|
64
64
|
}
|
65
65
|
|
66
|
-
@JRubyMethod(module = true, required = 1)
|
67
|
-
public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject
|
68
|
-
|
66
|
+
@JRubyMethod(module = true, required = 1, optional = 1)
|
67
|
+
public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) throws IOException {
|
68
|
+
RubyHash options = (args.length == 2) ? (RubyHash) args[1] : null;
|
69
|
+
RubyString str = args[0].asString();
|
70
|
+
return unpacker.unpack(str, options);
|
69
71
|
}
|
70
72
|
}
|
71
73
|
|
@@ -89,6 +91,7 @@ public class MessagePackLibrary implements Library {
|
|
89
91
|
private MessagePackUnpacker streamUnpacker;
|
90
92
|
private IRubyObject stream;
|
91
93
|
private IRubyObject data;
|
94
|
+
private RubyHash options;
|
92
95
|
|
93
96
|
public Unpacker(Ruby runtime, RubyClass type, MessagePack msgPack) {
|
94
97
|
super(runtime, type);
|
@@ -100,10 +103,17 @@ public class MessagePackLibrary implements Library {
|
|
100
103
|
this.data = null;
|
101
104
|
}
|
102
105
|
|
103
|
-
@JRubyMethod(name = "initialize", optional =
|
106
|
+
@JRubyMethod(name = "initialize", optional = 2, visibility = PRIVATE)
|
104
107
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
105
|
-
if (args.length
|
108
|
+
if (args.length == 0) {
|
109
|
+
options = null;
|
110
|
+
} else if (args.length == 1 && args[0] instanceof RubyHash) {
|
111
|
+
options = (RubyHash) args[0];
|
112
|
+
} else if (args.length > 0) {
|
106
113
|
setStream(ctx, args[0]);
|
114
|
+
if (args.length > 2) {
|
115
|
+
options = (RubyHash) args[1];
|
116
|
+
}
|
107
117
|
}
|
108
118
|
return this;
|
109
119
|
}
|
@@ -125,7 +135,7 @@ public class MessagePackLibrary implements Library {
|
|
125
135
|
byte[] bytes = data.asString().getBytes();
|
126
136
|
MessagePackBufferUnpacker localBufferUnpacker = new MessagePackBufferUnpacker(msgPack, bytes.length);
|
127
137
|
localBufferUnpacker.wrap(bytes, jOffset, jLimit == -1 ? bytes.length - jOffset : jLimit);
|
128
|
-
this.data = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), localBufferUnpacker.readValue());
|
138
|
+
this.data = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), localBufferUnpacker.readValue(), options);
|
129
139
|
return ctx.getRuntime().newFixnum(jOffset + localBufferUnpacker.getReadByteCount());
|
130
140
|
} catch (IOException ioe) {
|
131
141
|
// TODO: how to throw Ruby exceptions?
|
@@ -177,12 +187,12 @@ public class MessagePackLibrary implements Library {
|
|
177
187
|
}
|
178
188
|
if (block.isGiven()) {
|
179
189
|
for (Value value : localUnpacker) {
|
180
|
-
IRubyObject rubyObject = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), value);
|
190
|
+
IRubyObject rubyObject = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), value, options);
|
181
191
|
block.yield(ctx, rubyObject);
|
182
192
|
}
|
183
193
|
return ctx.getRuntime().getNil();
|
184
194
|
} else {
|
185
|
-
return RubyEnumerator.RubyEnumeratorKernel.obj_to_enum(ctx, this
|
195
|
+
return RubyEnumerator.RubyEnumeratorKernel.obj_to_enum(ctx, this);
|
186
196
|
}
|
187
197
|
}
|
188
198
|
|
@@ -4,8 +4,7 @@ package org.msgpack.jruby;
|
|
4
4
|
import java.io.IOException;
|
5
5
|
|
6
6
|
import org.msgpack.MessagePack;
|
7
|
-
import org.msgpack.packer.
|
8
|
-
import org.msgpack.packer.MessagePackBufferPacker;
|
7
|
+
import org.msgpack.packer.BufferPacker;
|
9
8
|
|
10
9
|
import org.jruby.RubyObject;
|
11
10
|
import org.jruby.RubyNil;
|
@@ -21,91 +20,91 @@ import org.jruby.RubyHash;
|
|
21
20
|
import org.jruby.runtime.builtin.IRubyObject;
|
22
21
|
|
23
22
|
|
24
|
-
public class RubyObjectPacker
|
25
|
-
private final
|
23
|
+
public class RubyObjectPacker {
|
24
|
+
private final MessagePack msgPack;
|
26
25
|
|
27
|
-
public RubyObjectPacker(MessagePack msgPack
|
28
|
-
|
29
|
-
this.packer = packer;
|
26
|
+
public RubyObjectPacker(MessagePack msgPack) {
|
27
|
+
this.msgPack = msgPack;
|
30
28
|
}
|
31
29
|
|
32
|
-
public
|
30
|
+
public RubyString pack(IRubyObject o) throws IOException {
|
31
|
+
return RubyString.newString(o.getRuntime(), packRaw(o));
|
32
|
+
}
|
33
|
+
|
34
|
+
public byte[] packRaw(IRubyObject o) throws IOException {
|
35
|
+
BufferPacker packer = msgPack.createBufferPacker();
|
36
|
+
write(packer, o);
|
37
|
+
return packer.toByteArray();
|
38
|
+
}
|
39
|
+
|
40
|
+
private void write(BufferPacker packer, IRubyObject o) throws IOException {
|
33
41
|
if (o == null || o instanceof RubyNil) {
|
34
42
|
packer.writeNil();
|
35
|
-
return this;
|
36
43
|
} else if (o instanceof RubyBoolean) {
|
37
44
|
packer.write(((RubyBoolean) o).isTrue());
|
38
|
-
return this;
|
39
45
|
} else if (o instanceof RubyBignum) {
|
40
|
-
|
46
|
+
write(packer, (RubyBignum) o);
|
41
47
|
} else if (o instanceof RubyInteger) {
|
42
|
-
|
48
|
+
write(packer, (RubyInteger) o);
|
43
49
|
} else if (o instanceof RubyFixnum) {
|
44
|
-
|
50
|
+
write(packer, (RubyFixnum) o);
|
45
51
|
} else if (o instanceof RubyFloat) {
|
46
|
-
|
52
|
+
write(packer, (RubyFloat) o);
|
47
53
|
} else if (o instanceof RubyString) {
|
48
|
-
|
54
|
+
write(packer, (RubyString) o);
|
49
55
|
} else if (o instanceof RubySymbol) {
|
50
|
-
|
56
|
+
write(packer, (RubySymbol) o);
|
51
57
|
} else if (o instanceof RubyArray) {
|
52
|
-
|
58
|
+
write(packer, (RubyArray) o);
|
53
59
|
} else if (o instanceof RubyHash) {
|
54
|
-
|
60
|
+
write(packer, (RubyHash) o);
|
55
61
|
} else {
|
56
62
|
throw o.getRuntime().newArgumentError(String.format("Cannot pack type: %s", o.getClass().getName()));
|
57
63
|
}
|
58
64
|
}
|
59
65
|
|
60
|
-
|
66
|
+
private void write(BufferPacker packer, RubyBignum bignum) throws IOException {
|
61
67
|
packer.write(bignum.getBigIntegerValue());
|
62
|
-
return this;
|
63
68
|
}
|
64
69
|
|
65
|
-
|
70
|
+
private void write(BufferPacker packer, RubyInteger integer) throws IOException {
|
66
71
|
packer.write(integer.getLongValue());
|
67
|
-
return this;
|
68
72
|
}
|
69
73
|
|
70
|
-
|
74
|
+
private void write(BufferPacker packer, RubyFixnum fixnum) throws IOException {
|
71
75
|
packer.write(fixnum.getLongValue());
|
72
|
-
return this;
|
73
76
|
}
|
74
77
|
|
75
|
-
|
78
|
+
private void write(BufferPacker packer, RubyFloat flt) throws IOException {
|
76
79
|
packer.write(flt.getDoubleValue());
|
77
|
-
return this;
|
78
80
|
}
|
79
81
|
|
80
|
-
|
82
|
+
private void write(BufferPacker packer, RubyString str) throws IOException {
|
81
83
|
packer.write(str.getBytes());
|
82
|
-
return this;
|
83
84
|
}
|
84
85
|
|
85
|
-
|
86
|
-
|
86
|
+
private void write(BufferPacker packer, RubySymbol sym) throws IOException {
|
87
|
+
write(packer, (RubyString) sym.to_s());
|
87
88
|
}
|
88
89
|
|
89
|
-
|
90
|
+
private void write(BufferPacker packer, RubyArray array) throws IOException {
|
90
91
|
int count = array.size();
|
91
92
|
packer.writeArrayBegin(count);
|
92
93
|
for (int i = 0; i < count; i++) {
|
93
|
-
write((RubyObject) array.entry(i));
|
94
|
+
write(packer, (RubyObject) array.entry(i));
|
94
95
|
}
|
95
96
|
packer.writeArrayEnd();
|
96
|
-
return this;
|
97
97
|
}
|
98
98
|
|
99
|
-
|
99
|
+
private void write(BufferPacker packer, RubyHash hash) throws IOException {
|
100
100
|
int count = hash.size();
|
101
101
|
packer.writeMapBegin(count);
|
102
102
|
RubyArray keys = hash.keys();
|
103
103
|
RubyArray values = hash.rb_values();
|
104
104
|
for (int i = 0; i < count; i++) {
|
105
|
-
write((RubyObject) keys.entry(i));
|
106
|
-
write((RubyObject) values.entry(i));
|
105
|
+
write(packer, (RubyObject) keys.entry(i));
|
106
|
+
write(packer, (RubyObject) values.entry(i));
|
107
107
|
}
|
108
108
|
packer.writeMapEnd();
|
109
|
-
return this;
|
110
109
|
}
|
111
110
|
}
|
@@ -28,6 +28,7 @@ import org.jruby.RubySymbol;
|
|
28
28
|
import org.jruby.RubyArray;
|
29
29
|
import org.jruby.RubyHash;
|
30
30
|
import org.jruby.runtime.builtin.IRubyObject;
|
31
|
+
import org.jruby.runtime.ThreadContext;
|
31
32
|
|
32
33
|
|
33
34
|
public class RubyObjectUnpacker {
|
@@ -37,17 +38,17 @@ public class RubyObjectUnpacker {
|
|
37
38
|
this.msgPack = msgPack;
|
38
39
|
}
|
39
40
|
|
40
|
-
public IRubyObject unpack(RubyString str) throws IOException {
|
41
|
-
return unpack(str.getRuntime(), str.getBytes());
|
41
|
+
public IRubyObject unpack(RubyString str, RubyHash options) throws IOException {
|
42
|
+
return unpack(str.getRuntime(), str.getBytes(), options);
|
42
43
|
}
|
43
44
|
|
44
|
-
public IRubyObject unpack(Ruby runtime, byte[] data) throws IOException {
|
45
|
+
public IRubyObject unpack(Ruby runtime, byte[] data, RubyHash options) throws IOException {
|
45
46
|
MessagePackBufferUnpacker unpacker = new MessagePackBufferUnpacker(msgPack);
|
46
47
|
unpacker.wrap(data);
|
47
|
-
return valueToRubyObject(runtime, unpacker.readValue());
|
48
|
+
return valueToRubyObject(runtime, unpacker.readValue(), options);
|
48
49
|
}
|
49
50
|
|
50
|
-
IRubyObject valueToRubyObject(Ruby runtime, Value value) {
|
51
|
+
IRubyObject valueToRubyObject(Ruby runtime, Value value, RubyHash options) {
|
51
52
|
switch (value.getType()) {
|
52
53
|
case NIL:
|
53
54
|
return runtime.getNil();
|
@@ -58,9 +59,9 @@ public class RubyObjectUnpacker {
|
|
58
59
|
case FLOAT:
|
59
60
|
return convert(runtime, value.asFloatValue());
|
60
61
|
case ARRAY:
|
61
|
-
return convert(runtime, value.asArrayValue());
|
62
|
+
return convert(runtime, value.asArrayValue(), options);
|
62
63
|
case MAP:
|
63
|
-
return convert(runtime, value.asMapValue());
|
64
|
+
return convert(runtime, value.asMapValue(), options);
|
64
65
|
case RAW:
|
65
66
|
return convert(runtime, value.asRawValue());
|
66
67
|
default:
|
@@ -86,24 +87,29 @@ public class RubyObjectUnpacker {
|
|
86
87
|
return RubyFloat.newFloat(runtime, value.asFloatValue().getDouble());
|
87
88
|
}
|
88
89
|
|
89
|
-
private IRubyObject convert(Ruby runtime, ArrayValue value) {
|
90
|
+
private IRubyObject convert(Ruby runtime, ArrayValue value, RubyHash options) {
|
90
91
|
Value[] elements = value.asArrayValue().getElementArray();
|
91
92
|
int elementCount = elements.length;
|
92
93
|
IRubyObject[] rubyObjects = new IRubyObject[elementCount];
|
93
94
|
for (int i = 0; i < elementCount; i++) {
|
94
|
-
rubyObjects[i] = valueToRubyObject(runtime, elements[i]);
|
95
|
+
rubyObjects[i] = valueToRubyObject(runtime, elements[i], options);
|
95
96
|
}
|
96
97
|
return RubyArray.newArray(runtime, rubyObjects);
|
97
98
|
}
|
98
99
|
|
99
|
-
private IRubyObject convert(Ruby runtime, MapValue value) {
|
100
|
+
private IRubyObject convert(Ruby runtime, MapValue value, RubyHash options) {
|
100
101
|
Value[] keysAndValues = value.asMapValue().getKeyValueArray();
|
101
102
|
int kvCount = keysAndValues.length;
|
102
103
|
RubyHash hash = RubyHash.newHash(runtime);
|
103
104
|
for (int i = 0; i < kvCount; i += 2) {
|
104
105
|
Value k = keysAndValues[i];
|
105
106
|
Value v = keysAndValues[i + 1];
|
106
|
-
|
107
|
+
IRubyObject kk = valueToRubyObject(runtime, k, options);
|
108
|
+
IRubyObject vv = valueToRubyObject(runtime, v, options);
|
109
|
+
if (symbolizeKeysEnabled(options)) {
|
110
|
+
kk = runtime.newSymbol(kk.asString().getByteList());
|
111
|
+
}
|
112
|
+
hash.put(kk, vv);
|
107
113
|
}
|
108
114
|
return hash;
|
109
115
|
}
|
@@ -111,4 +117,20 @@ public class RubyObjectUnpacker {
|
|
111
117
|
private IRubyObject convert(Ruby runtime, RawValue value) {
|
112
118
|
return RubyString.newString(runtime, value.asRawValue().getByteArray());
|
113
119
|
}
|
120
|
+
|
121
|
+
private boolean symbolizeKeysEnabled(RubyHash options) {
|
122
|
+
if (options == null) {
|
123
|
+
return false;
|
124
|
+
} else {
|
125
|
+
Ruby runtime = options.getRuntime();
|
126
|
+
ThreadContext ctx = runtime.getCurrentContext();
|
127
|
+
RubySymbol key = runtime.newSymbol("symbolize_keys");
|
128
|
+
IRubyObject value = options.fastARef(key);
|
129
|
+
if (value == null) {
|
130
|
+
return false;
|
131
|
+
} else {
|
132
|
+
return value.isTrue();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
114
136
|
}
|
data/lib/ext/msgpack_jruby.jar
CHANGED
Binary file
|
data/lib/msgpack/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$: << File.expand_path('../../../lib', __FILE__)
|
4
|
+
|
5
|
+
require 'viiite'
|
6
|
+
require 'msgpack'
|
7
|
+
|
8
|
+
|
9
|
+
iterations = 10_000
|
10
|
+
data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
|
11
|
+
|
12
|
+
Viiite.bm do |b|
|
13
|
+
b.report(:strings) do
|
14
|
+
iterations.times do
|
15
|
+
MessagePack.unpack(data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
b.report(:symbols) do
|
20
|
+
options = {:symbolize_keys => true}
|
21
|
+
iterations.times do
|
22
|
+
MessagePack.unpack(data, options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -156,4 +156,38 @@ describe ::MessagePack::Unpacker do
|
|
156
156
|
MessagePack.unpack(MessagePack.pack(array)).should have(10_000).items
|
157
157
|
end
|
158
158
|
end
|
159
|
+
|
160
|
+
context 'extensions' do
|
161
|
+
context 'symbolized keys' do
|
162
|
+
let :buffer do
|
163
|
+
MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
|
164
|
+
end
|
165
|
+
|
166
|
+
let :unpacker do
|
167
|
+
described_class.new(:symbolize_keys => true)
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'can symbolize keys when using #execute' do
|
171
|
+
unpacker.execute(buffer, 0)
|
172
|
+
unpacker.data.should == {:hello => 'world', :nested => ['object', {:structure => true}]}
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'can symbolize keys when using #each' do
|
176
|
+
objs = []
|
177
|
+
unpacker.feed(buffer)
|
178
|
+
unpacker.each do |obj|
|
179
|
+
objs << obj
|
180
|
+
end
|
181
|
+
objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'can symbolize keys when using #feed_each' do
|
185
|
+
objs = []
|
186
|
+
unpacker.feed_each(buffer) do |obj|
|
187
|
+
objs << obj
|
188
|
+
end
|
189
|
+
objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
159
193
|
end
|
data/spec/msgpack_spec.rb
CHANGED
@@ -78,4 +78,12 @@ describe MessagePack do
|
|
78
78
|
expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
context 'extensions' do
|
83
|
+
it 'can unpack hashes with symbolized keys' do
|
84
|
+
packed = MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
|
85
|
+
unpacked = MessagePack.unpack(packed, :symbolize_keys => true)
|
86
|
+
unpacked.should == {:hello => 'world', :nested => ['object', {:structure => true}]}
|
87
|
+
end
|
88
|
+
end
|
81
89
|
end
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: msgpack-jruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.2.0
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Theo Hultberg
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-29 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: JRuby compatible MessagePack implementation that does not use FFI
|
15
15
|
email:
|
@@ -35,7 +35,8 @@ files:
|
|
35
35
|
- lib/msgpack.rb
|
36
36
|
- lib/msgpack/version.rb
|
37
37
|
- msgpack-jruby.gemspec
|
38
|
-
- spec/
|
38
|
+
- spec/benchmarks/shootout_bm.rb
|
39
|
+
- spec/benchmarks/symbolize_keys_bm.rb
|
39
40
|
- spec/msgpack/unpacker_spec.rb
|
40
41
|
- spec/msgpack_spec.rb
|
41
42
|
- spec/spec_helper.rb
|