msgpack-jruby 1.1.3-java → 1.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|