msgpack-jruby 1.0.0-java → 1.1.3-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/.gitignore +1 -2
- data/.rvmrc +1 -1
- data/Gemfile +3 -1
- data/Gemfile.lock +52 -0
- data/Rakefile +45 -11
- data/ext/.gitignore +1 -0
- data/ext/java/MsgpackJrubyService.java +15 -0
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +229 -0
- data/ext/java/org/msgpack/jruby/RubyObjectPacker.java +111 -0
- data/ext/java/org/msgpack/jruby/RubyObjectUnpacker.java +114 -0
- data/lib/ext/javassist-3.15.0-GA.jar +0 -0
- data/lib/ext/msgpack-0.6.6.jar +0 -0
- data/lib/ext/msgpack_jruby.jar +0 -0
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +5 -4
- data/spec/benchmark.rb +11 -5
- data/spec/msgpack/unpacker_spec.rb +159 -0
- data/spec/msgpack_spec.rb +6 -1
- metadata +38 -44
- data/ext/java/org/msgpack/jruby/MessagePack.java +0 -156
- data/lib/ext/msgpack-0.5.2-devel.jar +0 -0
- data/lib/ext/org/msgpack/jruby/MessagePack.class +0 -0
data/.gitignore
CHANGED
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm --create use jruby-1.6.
|
1
|
+
rvm --create use jruby-1.6.7@msgpack-jruby
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
alf (0.10.1)
|
5
|
+
highline (~> 1.6.2)
|
6
|
+
myrrha (~> 1.2.1)
|
7
|
+
quickl (~> 0.4.1)
|
8
|
+
bouncy-castle-java (1.5.0146.1)
|
9
|
+
bson (1.5.2)
|
10
|
+
bson (1.5.2-java)
|
11
|
+
bson_ext (1.5.2)
|
12
|
+
bson (= 1.5.2)
|
13
|
+
diff-lcs (1.1.3)
|
14
|
+
ffi (1.0.9)
|
15
|
+
ffi (1.0.9-java)
|
16
|
+
ffi-ncurses (0.3.3)
|
17
|
+
ffi (>= 0.6.3)
|
18
|
+
gnuplot (2.3.6)
|
19
|
+
highline (1.6.2)
|
20
|
+
jruby-openssl (0.7.4)
|
21
|
+
bouncy-castle-java
|
22
|
+
json (1.5.0)
|
23
|
+
json (1.5.0-java)
|
24
|
+
msgpack (0.4.6)
|
25
|
+
myrrha (1.2.1)
|
26
|
+
quickl (0.4.1)
|
27
|
+
rspec (2.6.0)
|
28
|
+
rspec-core (~> 2.6.0)
|
29
|
+
rspec-expectations (~> 2.6.0)
|
30
|
+
rspec-mocks (~> 2.6.0)
|
31
|
+
rspec-core (2.6.4)
|
32
|
+
rspec-expectations (2.6.0)
|
33
|
+
diff-lcs (~> 1.1.2)
|
34
|
+
rspec-mocks (2.6.0)
|
35
|
+
viiite (0.1.0)
|
36
|
+
alf (~> 0.10.0)
|
37
|
+
gnuplot (~> 2.3.6)
|
38
|
+
quickl (~> 0.4.0)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
java
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
bson
|
46
|
+
bson_ext
|
47
|
+
ffi-ncurses
|
48
|
+
jruby-openssl
|
49
|
+
json
|
50
|
+
msgpack
|
51
|
+
rspec
|
52
|
+
viiite
|
data/Rakefile
CHANGED
@@ -1,22 +1,56 @@
|
|
1
|
-
|
1
|
+
$: << 'lib'
|
2
2
|
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'msgpack/version'
|
3
5
|
|
4
|
-
Bundler::GemHelper.install_tasks
|
5
6
|
|
6
7
|
task :clean do
|
7
|
-
rm Dir['
|
8
|
+
rm Dir['ext/java/**/*.class']
|
8
9
|
end
|
9
10
|
|
10
11
|
task :compile do
|
11
|
-
|
12
|
+
classpath = (Dir["lib/ext/*.jar"] + ["#{ENV['MY_RUBY_HOME']}/lib/jruby.jar"]).join(':')
|
13
|
+
system %(javac -Xlint:-options -source 1.6 -target 1.6 -cp #{classpath} ext/java/*.java ext/java/org/msgpack/jruby/*.java)
|
14
|
+
exit($?.exitstatus) unless $?.success?
|
12
15
|
end
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
task :package => :compile do
|
18
|
+
class_files = Dir['ext/java/**/*.class'].map { |path| path = path.sub('ext/java/', ''); "-C ext/java '#{path}'" }
|
19
|
+
system %(jar cf lib/ext/msgpack_jruby.jar #{class_files.join(' ')})
|
20
|
+
exit($?.exitstatus) unless $?.success?
|
21
|
+
end
|
16
22
|
|
17
|
-
task :
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
task :release do
|
24
|
+
version_string = "v#{MessagePack::VERSION}"
|
25
|
+
unless %x(git tag -l).include?(version_string)
|
26
|
+
system %(git tag -a #{version_string} -m #{version_string})
|
27
|
+
end
|
28
|
+
system %(gem build msgpack-jruby.gemspec && gem push msgpack-jruby-*.gem && mv msgpack-jruby-*.gem pkg)
|
22
29
|
end
|
30
|
+
|
31
|
+
namespace :benchmark do
|
32
|
+
BENCHMARK_RUBIES = ['1.9.2-p0', 'jruby-1.6.5', 'jruby-head']
|
33
|
+
BENCHMARK_GEMSET = 'msgpack-jruby-benchmarking'
|
34
|
+
|
35
|
+
task :run do
|
36
|
+
rubies = BENCHMARK_RUBIES.map { |rb| "#{rb}@#{BENCHMARK_GEMSET}" }
|
37
|
+
cmd = %(rvm #{rubies.join(',')} exec viiite run spec/benchmark.rb | tee benchmark | viiite report --hierarchy --regroup=bench,lib,ruby)
|
38
|
+
puts cmd
|
39
|
+
system cmd
|
40
|
+
end
|
41
|
+
|
42
|
+
task :quick do
|
43
|
+
cmd = %(IMPLEMENTATIONS=msgpack viiite run spec/benchmark.rb | viiite report --hierarchy --regroup=bench)
|
44
|
+
puts cmd
|
45
|
+
system cmd
|
46
|
+
end
|
47
|
+
|
48
|
+
task :setup do
|
49
|
+
rubies = BENCHMARK_RUBIES.map { |rb| "#{rb}@#{BENCHMARK_GEMSET}" }
|
50
|
+
rubies.each do |ruby_version|
|
51
|
+
cmd = %(rvm-shell #{ruby_version} -c 'bundle check || bundle install')
|
52
|
+
puts cmd
|
53
|
+
system cmd
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/ext/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.class
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import java.io.IOException;
|
2
|
+
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.runtime.load.BasicLibraryService;
|
5
|
+
|
6
|
+
import org.msgpack.jruby.MessagePackLibrary;
|
7
|
+
|
8
|
+
|
9
|
+
public class MsgpackJrubyService implements BasicLibraryService {
|
10
|
+
public boolean basicLoad(final Ruby runtime) throws IOException {
|
11
|
+
new MessagePackLibrary().load(runtime, false);
|
12
|
+
return true;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
@@ -0,0 +1,229 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
import java.io.InputStream;
|
5
|
+
import java.io.ByteArrayInputStream;
|
6
|
+
import java.io.IOException;
|
7
|
+
|
8
|
+
import org.jruby.Ruby;
|
9
|
+
import org.jruby.RubyModule;
|
10
|
+
import org.jruby.RubyClass;
|
11
|
+
import org.jruby.RubyString;
|
12
|
+
import org.jruby.RubyObject;
|
13
|
+
import org.jruby.RubyIO;
|
14
|
+
import org.jruby.RubyStringIO;
|
15
|
+
import org.jruby.RubyNumeric;
|
16
|
+
import org.jruby.RubyEnumerator;
|
17
|
+
import org.jruby.runtime.load.Library;
|
18
|
+
import org.jruby.runtime.callback.Callback;
|
19
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
20
|
+
import org.jruby.runtime.Arity;
|
21
|
+
import org.jruby.runtime.Block;
|
22
|
+
import org.jruby.runtime.ObjectAllocator;
|
23
|
+
import org.jruby.runtime.ThreadContext;
|
24
|
+
import org.jruby.anno.JRubyClass;
|
25
|
+
import org.jruby.anno.JRubyModule;
|
26
|
+
import org.jruby.anno.JRubyMethod;
|
27
|
+
import org.jruby.util.IOInputStream;
|
28
|
+
|
29
|
+
import static org.jruby.runtime.Visibility.*;
|
30
|
+
|
31
|
+
import org.msgpack.MessagePack;
|
32
|
+
import org.msgpack.packer.BufferPacker;
|
33
|
+
import org.msgpack.packer.Packer;
|
34
|
+
import org.msgpack.unpacker.MessagePackBufferUnpacker;
|
35
|
+
import org.msgpack.unpacker.MessagePackUnpacker;
|
36
|
+
import org.msgpack.unpacker.UnpackerIterator;
|
37
|
+
import org.msgpack.type.Value;
|
38
|
+
import org.msgpack.io.Input;
|
39
|
+
import org.msgpack.io.LinkedBufferInput;
|
40
|
+
import org.msgpack.io.StreamInput;
|
41
|
+
|
42
|
+
|
43
|
+
public class MessagePackLibrary implements Library {
|
44
|
+
public void load(Ruby runtime, boolean wrap) throws IOException {
|
45
|
+
MessagePack msgPack = new MessagePack();
|
46
|
+
RubyModule msgpackModule = runtime.defineModule("MessagePack");
|
47
|
+
msgpackModule.defineAnnotatedMethods(MessagePackModule.class);
|
48
|
+
RubyClass standardErrorClass = runtime.getStandardError();
|
49
|
+
RubyClass unpackErrorClass = msgpackModule.defineClassUnder("UnpackError", standardErrorClass, standardErrorClass.getAllocator());
|
50
|
+
RubyClass unpackerClass = msgpackModule.defineClassUnder("Unpacker", runtime.getObject(), new UnpackerAllocator(msgPack));
|
51
|
+
unpackerClass.defineAnnotatedMethods(Unpacker.class);
|
52
|
+
}
|
53
|
+
|
54
|
+
@JRubyModule(name = "MessagePack")
|
55
|
+
public static class MessagePackModule {
|
56
|
+
private static MessagePack msgPack = new MessagePack();
|
57
|
+
private static RubyObjectUnpacker unpacker = new RubyObjectUnpacker(msgPack);
|
58
|
+
|
59
|
+
@JRubyMethod(module = true, required = 1)
|
60
|
+
public static IRubyObject pack(ThreadContext ctx, IRubyObject recv, IRubyObject obj) throws IOException {
|
61
|
+
BufferPacker bufferedPacker = msgPack.createBufferPacker();
|
62
|
+
Packer packer = new RubyObjectPacker(msgPack, bufferedPacker).write(obj);
|
63
|
+
return RubyString.newString(ctx.getRuntime(), bufferedPacker.toByteArray());
|
64
|
+
}
|
65
|
+
|
66
|
+
@JRubyMethod(module = true, required = 1)
|
67
|
+
public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject obj) throws IOException {
|
68
|
+
return unpacker.unpack(obj.asString());
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
private static class UnpackerAllocator implements ObjectAllocator {
|
73
|
+
private MessagePack msgPack;
|
74
|
+
|
75
|
+
public UnpackerAllocator(MessagePack msgPack) {
|
76
|
+
this.msgPack = msgPack;
|
77
|
+
}
|
78
|
+
|
79
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
80
|
+
return new Unpacker(runtime, klass, msgPack);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
@JRubyClass(name="MessagePack::Unpacker")
|
85
|
+
public static class Unpacker extends RubyObject {
|
86
|
+
private MessagePack msgPack;
|
87
|
+
private RubyObjectUnpacker rubyObjectUnpacker;
|
88
|
+
private MessagePackBufferUnpacker bufferUnpacker;
|
89
|
+
private MessagePackUnpacker streamUnpacker;
|
90
|
+
private IRubyObject stream;
|
91
|
+
private IRubyObject data;
|
92
|
+
|
93
|
+
public Unpacker(Ruby runtime, RubyClass type, MessagePack msgPack) {
|
94
|
+
super(runtime, type);
|
95
|
+
this.msgPack = msgPack;
|
96
|
+
this.rubyObjectUnpacker = new RubyObjectUnpacker(msgPack);
|
97
|
+
this.bufferUnpacker = null;
|
98
|
+
this.streamUnpacker = null;
|
99
|
+
this.stream = null;
|
100
|
+
this.data = null;
|
101
|
+
}
|
102
|
+
|
103
|
+
@JRubyMethod(name = "initialize", optional = 1, visibility = PRIVATE)
|
104
|
+
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
105
|
+
if (args.length > 0) {
|
106
|
+
setStream(ctx, args[0]);
|
107
|
+
}
|
108
|
+
return this;
|
109
|
+
}
|
110
|
+
|
111
|
+
@JRubyMethod(required = 2)
|
112
|
+
public IRubyObject execute(ThreadContext ctx, IRubyObject data, IRubyObject offset) {
|
113
|
+
return executeLimit(ctx, data, offset, null);
|
114
|
+
}
|
115
|
+
|
116
|
+
@JRubyMethod(name = "execute_limit", required = 3)
|
117
|
+
public IRubyObject executeLimit(ThreadContext ctx, IRubyObject data, IRubyObject offset, IRubyObject limit) {
|
118
|
+
this.data = null;
|
119
|
+
try {
|
120
|
+
int jOffset = RubyNumeric.fix2int(offset);
|
121
|
+
int jLimit = -1;
|
122
|
+
if (limit != null) {
|
123
|
+
jLimit = RubyNumeric.fix2int(limit);
|
124
|
+
}
|
125
|
+
byte[] bytes = data.asString().getBytes();
|
126
|
+
MessagePackBufferUnpacker localBufferUnpacker = new MessagePackBufferUnpacker(msgPack, bytes.length);
|
127
|
+
localBufferUnpacker.wrap(bytes, jOffset, jLimit == -1 ? bytes.length - jOffset : jLimit);
|
128
|
+
this.data = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), localBufferUnpacker.readValue());
|
129
|
+
return ctx.getRuntime().newFixnum(jOffset + localBufferUnpacker.getReadByteCount());
|
130
|
+
} catch (IOException ioe) {
|
131
|
+
// TODO: how to throw Ruby exceptions?
|
132
|
+
return ctx.getRuntime().getNil();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
@JRubyMethod(name = "data")
|
137
|
+
public IRubyObject getData(ThreadContext ctx) {
|
138
|
+
if (data == null) {
|
139
|
+
return ctx.getRuntime().getNil();
|
140
|
+
} else {
|
141
|
+
return data;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
@JRubyMethod(name = "finished?")
|
146
|
+
public IRubyObject finished_q(ThreadContext ctx) {
|
147
|
+
return data == null ? ctx.getRuntime().getFalse() : ctx.getRuntime().getTrue();
|
148
|
+
}
|
149
|
+
|
150
|
+
@JRubyMethod(required = 1)
|
151
|
+
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
152
|
+
streamUnpacker = null;
|
153
|
+
byte[] bytes = data.asString().getBytes();
|
154
|
+
if (bufferUnpacker == null) {
|
155
|
+
bufferUnpacker = new MessagePackBufferUnpacker(msgPack);
|
156
|
+
}
|
157
|
+
bufferUnpacker.feed(bytes);
|
158
|
+
return ctx.getRuntime().getNil();
|
159
|
+
}
|
160
|
+
|
161
|
+
@JRubyMethod(name = "feed_each", required = 1)
|
162
|
+
public IRubyObject feedEach(ThreadContext ctx, IRubyObject data, Block block) {
|
163
|
+
feed(ctx, data);
|
164
|
+
each(ctx, block);
|
165
|
+
return ctx.getRuntime().getNil();
|
166
|
+
}
|
167
|
+
|
168
|
+
@JRubyMethod
|
169
|
+
public IRubyObject each(ThreadContext ctx, Block block) {
|
170
|
+
MessagePackUnpacker localUnpacker = null;
|
171
|
+
if (bufferUnpacker == null && streamUnpacker != null) {
|
172
|
+
localUnpacker = streamUnpacker;
|
173
|
+
} else if (bufferUnpacker != null) {
|
174
|
+
localUnpacker = bufferUnpacker;
|
175
|
+
} else {
|
176
|
+
return ctx.getRuntime().getNil();
|
177
|
+
}
|
178
|
+
if (block.isGiven()) {
|
179
|
+
for (Value value : localUnpacker) {
|
180
|
+
IRubyObject rubyObject = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), value);
|
181
|
+
block.yield(ctx, rubyObject);
|
182
|
+
}
|
183
|
+
return ctx.getRuntime().getNil();
|
184
|
+
} else {
|
185
|
+
return RubyEnumerator.RubyEnumeratorKernel.obj_to_enum(ctx, this, Block.NULL_BLOCK);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
@JRubyMethod
|
190
|
+
public IRubyObject fill(ThreadContext ctx) {
|
191
|
+
return ctx.getRuntime().getNil();
|
192
|
+
}
|
193
|
+
|
194
|
+
@JRubyMethod
|
195
|
+
public IRubyObject reset(ThreadContext ctx) {
|
196
|
+
if (bufferUnpacker != null) {
|
197
|
+
bufferUnpacker.reset();
|
198
|
+
}
|
199
|
+
if (streamUnpacker != null) {
|
200
|
+
streamUnpacker.reset();
|
201
|
+
}
|
202
|
+
return ctx.getRuntime().getNil();
|
203
|
+
}
|
204
|
+
|
205
|
+
@JRubyMethod(name = "stream")
|
206
|
+
public IRubyObject getStream(ThreadContext ctx) {
|
207
|
+
if (stream == null) {
|
208
|
+
return ctx.getRuntime().getNil();
|
209
|
+
} else {
|
210
|
+
return stream;
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
@JRubyMethod(name = "stream=", required = 1)
|
215
|
+
public IRubyObject setStream(ThreadContext ctx, IRubyObject stream) {
|
216
|
+
bufferUnpacker = null;
|
217
|
+
this.stream = stream;
|
218
|
+
if (stream instanceof RubyStringIO) {
|
219
|
+
// TODO: RubyStringIO returns negative numbers when read through IOInputStream#read
|
220
|
+
IRubyObject str = ((RubyStringIO) stream).string();
|
221
|
+
byte[] bytes = ((RubyString) str).getBytes();
|
222
|
+
streamUnpacker = new MessagePackUnpacker(msgPack, new ByteArrayInputStream(bytes));
|
223
|
+
} else {
|
224
|
+
streamUnpacker = new MessagePackUnpacker(msgPack, new IOInputStream(stream));
|
225
|
+
}
|
226
|
+
return getStream(ctx);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
import java.io.IOException;
|
5
|
+
|
6
|
+
import org.msgpack.MessagePack;
|
7
|
+
import org.msgpack.packer.Packer;
|
8
|
+
import org.msgpack.packer.MessagePackBufferPacker;
|
9
|
+
|
10
|
+
import org.jruby.RubyObject;
|
11
|
+
import org.jruby.RubyNil;
|
12
|
+
import org.jruby.RubyBoolean;
|
13
|
+
import org.jruby.RubyBignum;
|
14
|
+
import org.jruby.RubyInteger;
|
15
|
+
import org.jruby.RubyFixnum;
|
16
|
+
import org.jruby.RubyFloat;
|
17
|
+
import org.jruby.RubyString;
|
18
|
+
import org.jruby.RubySymbol;
|
19
|
+
import org.jruby.RubyArray;
|
20
|
+
import org.jruby.RubyHash;
|
21
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
22
|
+
|
23
|
+
|
24
|
+
public class RubyObjectPacker extends MessagePackBufferPacker {
|
25
|
+
private final Packer packer;
|
26
|
+
|
27
|
+
public RubyObjectPacker(MessagePack msgPack, Packer packer) {
|
28
|
+
super(msgPack);
|
29
|
+
this.packer = packer;
|
30
|
+
}
|
31
|
+
|
32
|
+
public Packer write(IRubyObject o) throws IOException {
|
33
|
+
if (o == null || o instanceof RubyNil) {
|
34
|
+
packer.writeNil();
|
35
|
+
return this;
|
36
|
+
} else if (o instanceof RubyBoolean) {
|
37
|
+
packer.write(((RubyBoolean) o).isTrue());
|
38
|
+
return this;
|
39
|
+
} else if (o instanceof RubyBignum) {
|
40
|
+
return write((RubyBignum) o);
|
41
|
+
} else if (o instanceof RubyInteger) {
|
42
|
+
return write((RubyInteger) o);
|
43
|
+
} else if (o instanceof RubyFixnum) {
|
44
|
+
return write((RubyFixnum) o);
|
45
|
+
} else if (o instanceof RubyFloat) {
|
46
|
+
return write((RubyFloat) o);
|
47
|
+
} else if (o instanceof RubyString) {
|
48
|
+
return write((RubyString) o);
|
49
|
+
} else if (o instanceof RubySymbol) {
|
50
|
+
return write((RubySymbol) o);
|
51
|
+
} else if (o instanceof RubyArray) {
|
52
|
+
return write((RubyArray) o);
|
53
|
+
} else if (o instanceof RubyHash) {
|
54
|
+
return write((RubyHash) o);
|
55
|
+
} else {
|
56
|
+
throw o.getRuntime().newArgumentError(String.format("Cannot pack type: %s", o.getClass().getName()));
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
public final Packer write(RubyBignum bignum) throws IOException {
|
61
|
+
packer.write(bignum.getBigIntegerValue());
|
62
|
+
return this;
|
63
|
+
}
|
64
|
+
|
65
|
+
public final Packer write(RubyInteger integer) throws IOException {
|
66
|
+
packer.write(integer.getLongValue());
|
67
|
+
return this;
|
68
|
+
}
|
69
|
+
|
70
|
+
public final Packer write(RubyFixnum fixnum) throws IOException {
|
71
|
+
packer.write(fixnum.getLongValue());
|
72
|
+
return this;
|
73
|
+
}
|
74
|
+
|
75
|
+
public final Packer write(RubyFloat flt) throws IOException {
|
76
|
+
packer.write(flt.getDoubleValue());
|
77
|
+
return this;
|
78
|
+
}
|
79
|
+
|
80
|
+
public final Packer write(RubyString str) throws IOException {
|
81
|
+
packer.write(str.getBytes());
|
82
|
+
return this;
|
83
|
+
}
|
84
|
+
|
85
|
+
public final Packer write(RubySymbol sym) throws IOException {
|
86
|
+
return write((RubyString) sym.to_s());
|
87
|
+
}
|
88
|
+
|
89
|
+
public final Packer write(RubyArray array) throws IOException {
|
90
|
+
int count = array.size();
|
91
|
+
packer.writeArrayBegin(count);
|
92
|
+
for (int i = 0; i < count; i++) {
|
93
|
+
write((RubyObject) array.entry(i));
|
94
|
+
}
|
95
|
+
packer.writeArrayEnd();
|
96
|
+
return this;
|
97
|
+
}
|
98
|
+
|
99
|
+
public final Packer write(RubyHash hash) throws IOException {
|
100
|
+
int count = hash.size();
|
101
|
+
packer.writeMapBegin(count);
|
102
|
+
RubyArray keys = hash.keys();
|
103
|
+
RubyArray values = hash.rb_values();
|
104
|
+
for (int i = 0; i < count; i++) {
|
105
|
+
write((RubyObject) keys.entry(i));
|
106
|
+
write((RubyObject) values.entry(i));
|
107
|
+
}
|
108
|
+
packer.writeMapEnd();
|
109
|
+
return this;
|
110
|
+
}
|
111
|
+
}
|
@@ -0,0 +1,114 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
import java.io.IOException;
|
5
|
+
|
6
|
+
import org.msgpack.MessagePack;
|
7
|
+
import org.msgpack.MessageTypeException;
|
8
|
+
import org.msgpack.unpacker.MessagePackBufferUnpacker;
|
9
|
+
import org.msgpack.type.Value;
|
10
|
+
import org.msgpack.type.ValueType;
|
11
|
+
import org.msgpack.type.BooleanValue;
|
12
|
+
import org.msgpack.type.IntegerValue;
|
13
|
+
import org.msgpack.type.FloatValue;
|
14
|
+
import org.msgpack.type.ArrayValue;
|
15
|
+
import org.msgpack.type.MapValue;
|
16
|
+
import org.msgpack.type.RawValue;
|
17
|
+
|
18
|
+
import org.jruby.Ruby;
|
19
|
+
import org.jruby.RubyObject;
|
20
|
+
import org.jruby.RubyNil;
|
21
|
+
import org.jruby.RubyBoolean;
|
22
|
+
import org.jruby.RubyBignum;
|
23
|
+
import org.jruby.RubyInteger;
|
24
|
+
import org.jruby.RubyFixnum;
|
25
|
+
import org.jruby.RubyFloat;
|
26
|
+
import org.jruby.RubyString;
|
27
|
+
import org.jruby.RubySymbol;
|
28
|
+
import org.jruby.RubyArray;
|
29
|
+
import org.jruby.RubyHash;
|
30
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
31
|
+
|
32
|
+
|
33
|
+
public class RubyObjectUnpacker {
|
34
|
+
private final MessagePack msgPack;
|
35
|
+
|
36
|
+
public RubyObjectUnpacker(MessagePack msgPack) {
|
37
|
+
this.msgPack = msgPack;
|
38
|
+
}
|
39
|
+
|
40
|
+
public IRubyObject unpack(RubyString str) throws IOException {
|
41
|
+
return unpack(str.getRuntime(), str.getBytes());
|
42
|
+
}
|
43
|
+
|
44
|
+
public IRubyObject unpack(Ruby runtime, byte[] data) throws IOException {
|
45
|
+
MessagePackBufferUnpacker unpacker = new MessagePackBufferUnpacker(msgPack);
|
46
|
+
unpacker.wrap(data);
|
47
|
+
return valueToRubyObject(runtime, unpacker.readValue());
|
48
|
+
}
|
49
|
+
|
50
|
+
IRubyObject valueToRubyObject(Ruby runtime, Value value) {
|
51
|
+
switch (value.getType()) {
|
52
|
+
case NIL:
|
53
|
+
return runtime.getNil();
|
54
|
+
case BOOLEAN:
|
55
|
+
return convert(runtime, value.asBooleanValue());
|
56
|
+
case INTEGER:
|
57
|
+
return convert(runtime, value.asIntegerValue());
|
58
|
+
case FLOAT:
|
59
|
+
return convert(runtime, value.asFloatValue());
|
60
|
+
case ARRAY:
|
61
|
+
return convert(runtime, value.asArrayValue());
|
62
|
+
case MAP:
|
63
|
+
return convert(runtime, value.asMapValue());
|
64
|
+
case RAW:
|
65
|
+
return convert(runtime, value.asRawValue());
|
66
|
+
default:
|
67
|
+
throw runtime.newArgumentError(String.format("Unexpected value: %s", value.toString()));
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
private IRubyObject convert(Ruby runtime, BooleanValue value) {
|
72
|
+
return RubyBoolean.newBoolean(runtime, value.asBooleanValue().getBoolean());
|
73
|
+
}
|
74
|
+
|
75
|
+
private IRubyObject convert(Ruby runtime, IntegerValue value) {
|
76
|
+
// TODO: is there any way of checking for bignums up front?
|
77
|
+
IntegerValue iv = value.asIntegerValue();
|
78
|
+
try {
|
79
|
+
return RubyFixnum.newFixnum(runtime, iv.getLong());
|
80
|
+
} catch (MessageTypeException mte) {
|
81
|
+
return RubyBignum.newBignum(runtime, iv.getBigInteger());
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
private IRubyObject convert(Ruby runtime, FloatValue value) {
|
86
|
+
return RubyFloat.newFloat(runtime, value.asFloatValue().getDouble());
|
87
|
+
}
|
88
|
+
|
89
|
+
private IRubyObject convert(Ruby runtime, ArrayValue value) {
|
90
|
+
Value[] elements = value.asArrayValue().getElementArray();
|
91
|
+
int elementCount = elements.length;
|
92
|
+
IRubyObject[] rubyObjects = new IRubyObject[elementCount];
|
93
|
+
for (int i = 0; i < elementCount; i++) {
|
94
|
+
rubyObjects[i] = valueToRubyObject(runtime, elements[i]);
|
95
|
+
}
|
96
|
+
return RubyArray.newArray(runtime, rubyObjects);
|
97
|
+
}
|
98
|
+
|
99
|
+
private IRubyObject convert(Ruby runtime, MapValue value) {
|
100
|
+
Value[] keysAndValues = value.asMapValue().getKeyValueArray();
|
101
|
+
int kvCount = keysAndValues.length;
|
102
|
+
RubyHash hash = RubyHash.newHash(runtime);
|
103
|
+
for (int i = 0; i < kvCount; i += 2) {
|
104
|
+
Value k = keysAndValues[i];
|
105
|
+
Value v = keysAndValues[i + 1];
|
106
|
+
hash.put(valueToRubyObject(runtime, k), valueToRubyObject(runtime, v));
|
107
|
+
}
|
108
|
+
return hash;
|
109
|
+
}
|
110
|
+
|
111
|
+
private IRubyObject convert(Ruby runtime, RawValue value) {
|
112
|
+
return RubyString.newString(runtime, value.asRawValue().getByteArray());
|
113
|
+
}
|
114
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
data/lib/msgpack/version.rb
CHANGED
data/lib/msgpack.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
$CLASSPATH << File.expand_path('../ext', __FILE__) << File.expand_path('../ext/msgpack-0.5.2-devel.jar', __FILE__)
|
3
|
+
$: << File.expand_path('../ext', __FILE__)
|
6
4
|
|
7
|
-
|
5
|
+
require 'java'
|
6
|
+
require 'javassist-3.15.0-GA'
|
7
|
+
require 'msgpack-0.6.6'
|
8
|
+
require 'msgpack_jruby'
|
data/spec/benchmark.rb
CHANGED
@@ -10,17 +10,23 @@ require 'msgpack'
|
|
10
10
|
require 'json'
|
11
11
|
require 'bson'
|
12
12
|
|
13
|
+
if RUBY_PLATFORM.include?('java')
|
14
|
+
BSON_IMPL = BSON::BSON_JAVA
|
15
|
+
else
|
16
|
+
BSON_IMPL = BSON::BSON_C
|
17
|
+
end
|
13
18
|
|
14
19
|
OBJECT_STRUCTURE = {'x' => ['y', 34, 2**30 + 3, 2.1223423423356, {'hello' => 'world', '5' => [63, 'asjdl']}]}
|
15
20
|
ENCODED_MSGPACK = "\x81\xA1x\x95\xA1y\"\xCE@\x00\x00\x03\xCB@\x00\xFA\x8E\x9F9\xFA\xC1\x82\xA5hello\xA5world\xA15\x92?\xA5asjdl"
|
16
21
|
ENCODED_BSON = "d\x00\x00\x00\x04x\x00\\\x00\x00\x00\x020\x00\x02\x00\x00\x00y\x00\x101\x00\"\x00\x00\x00\x102\x00\x03\x00\x00@\x013\x00\xC1\xFA9\x9F\x8E\xFA\x00@\x034\x002\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x045\x00\x19\x00\x00\x00\x100\x00?\x00\x00\x00\x021\x00\x06\x00\x00\x00asjdl\x00\x00\x00\x00\x00"
|
17
22
|
ENCODED_JSON = '{"x":["y",34,1073741827,2.1223423423356,{"hello":"world","5":[63,"asjdl"]}]}'
|
18
23
|
ITERATIONS = 1_00_000
|
24
|
+
IMPLEMENTATIONS = ENV.fetch('IMPLEMENTATIONS', 'json,bson,msgpack').split(',').map(&:to_sym)
|
19
25
|
|
20
26
|
Viiite.bm do |b|
|
21
27
|
b.variation_point :ruby, Viiite.which_ruby
|
22
28
|
|
23
|
-
|
29
|
+
IMPLEMENTATIONS.each do |lib|
|
24
30
|
b.variation_point :lib, lib
|
25
31
|
|
26
32
|
|
@@ -28,7 +34,7 @@ Viiite.bm do |b|
|
|
28
34
|
ITERATIONS.times do
|
29
35
|
case lib
|
30
36
|
when :msgpack then MessagePack.pack(OBJECT_STRUCTURE)
|
31
|
-
when :bson then
|
37
|
+
when :bson then BSON_IMPL.serialize(OBJECT_STRUCTURE).to_s
|
32
38
|
when :json then OBJECT_STRUCTURE.to_json
|
33
39
|
end
|
34
40
|
end
|
@@ -38,7 +44,7 @@ Viiite.bm do |b|
|
|
38
44
|
ITERATIONS.times do
|
39
45
|
case lib
|
40
46
|
when :msgpack then MessagePack.unpack(ENCODED_MSGPACK)
|
41
|
-
when :bson then
|
47
|
+
when :bson then BSON_IMPL.deserialize(ENCODED_BSON)
|
42
48
|
when :json then JSON.parse(ENCODED_JSON)
|
43
49
|
end
|
44
50
|
end
|
@@ -48,7 +54,7 @@ Viiite.bm do |b|
|
|
48
54
|
ITERATIONS.times do
|
49
55
|
case lib
|
50
56
|
when :msgpack then MessagePack.unpack(MessagePack.pack(OBJECT_STRUCTURE))
|
51
|
-
when :bson then
|
57
|
+
when :bson then BSON_IMPL.deserialize(BSON_IMPL.serialize(OBJECT_STRUCTURE).to_s)
|
52
58
|
when :json then JSON.parse(OBJECT_STRUCTURE.to_json)
|
53
59
|
end
|
54
60
|
end
|
@@ -58,7 +64,7 @@ Viiite.bm do |b|
|
|
58
64
|
ITERATIONS.times do
|
59
65
|
case lib
|
60
66
|
when :msgpack then MessagePack.pack(MessagePack.unpack(ENCODED_MSGPACK))
|
61
|
-
when :bson then
|
67
|
+
when :bson then BSON_IMPL.serialize(BSON_IMPL.deserialize(ENCODED_BSON)).to_s
|
62
68
|
when :json then OBJECT_STRUCTURE.to_json(JSON.parse(ENCODED_JSON))
|
63
69
|
end
|
64
70
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
require_relative '../spec_helper'
|
4
|
+
require 'stringio'
|
5
|
+
require 'tempfile'
|
6
|
+
|
7
|
+
|
8
|
+
describe ::MessagePack::Unpacker do
|
9
|
+
subject do
|
10
|
+
described_class.new
|
11
|
+
end
|
12
|
+
|
13
|
+
let :buffer1 do
|
14
|
+
MessagePack.pack(:foo => 'bar')
|
15
|
+
end
|
16
|
+
|
17
|
+
let :buffer2 do
|
18
|
+
MessagePack.pack(:hello => {:world => [1, 2, 3]})
|
19
|
+
end
|
20
|
+
|
21
|
+
let :buffer3 do
|
22
|
+
MessagePack.pack(:x => 'y')
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#execute/#execute_limit/#finished?' do
|
26
|
+
let :buffer do
|
27
|
+
buffer1 + buffer2 + buffer3
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'extracts an object from the buffer' do
|
31
|
+
subject.execute(buffer, 0)
|
32
|
+
subject.data.should == {'foo' => 'bar'}
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'extracts an object from the buffer, starting at an offset' do
|
36
|
+
subject.execute(buffer, buffer1.length)
|
37
|
+
subject.data.should == {'hello' => {'world' => [1, 2, 3]}}
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'extracts an object from the buffer, starting at an offset reading bytes up to a limit' do
|
41
|
+
subject.execute_limit(buffer, buffer1.length, buffer2.length)
|
42
|
+
subject.data.should == {'hello' => {'world' => [1, 2, 3]}}
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'extracts nothing if the limit cuts an object in half' do
|
46
|
+
subject.execute_limit(buffer, buffer1.length, 3)
|
47
|
+
subject.data.should be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns the offset where the object ended' do
|
51
|
+
subject.execute(buffer, 0).should == buffer1.length
|
52
|
+
subject.execute(buffer, buffer1.length).should == buffer1.length + buffer2.length
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'is finished if #data returns an object' do
|
56
|
+
subject.execute_limit(buffer, buffer1.length, buffer2.length)
|
57
|
+
subject.should be_finished
|
58
|
+
|
59
|
+
subject.execute_limit(buffer, buffer1.length, 3)
|
60
|
+
subject.should_not be_finished
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#each' do
|
65
|
+
context 'with a buffer' do
|
66
|
+
it 'yields each object in the buffer' do
|
67
|
+
objects = []
|
68
|
+
subject.feed(buffer1)
|
69
|
+
subject.feed(buffer2)
|
70
|
+
subject.feed(buffer3)
|
71
|
+
subject.each do |obj|
|
72
|
+
objects << obj
|
73
|
+
end
|
74
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'returns an enumerator when no block is given' do
|
78
|
+
subject.feed(buffer1)
|
79
|
+
subject.feed(buffer2)
|
80
|
+
subject.feed(buffer3)
|
81
|
+
enum = subject.each
|
82
|
+
enum.map { |obj| obj.keys.first }.should == %w[foo hello x]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'with a StringIO stream' do
|
87
|
+
it 'yields each object in the stream' do
|
88
|
+
objects = []
|
89
|
+
subject.stream = StringIO.new(buffer1 + buffer2 + buffer3)
|
90
|
+
subject.each do |obj|
|
91
|
+
objects << obj
|
92
|
+
end
|
93
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'with a File stream' do
|
98
|
+
it 'yields each object in the stream' do
|
99
|
+
objects = []
|
100
|
+
file = Tempfile.new('msgpack')
|
101
|
+
file.write(buffer1)
|
102
|
+
file.write(buffer2)
|
103
|
+
file.write(buffer3)
|
104
|
+
file.open
|
105
|
+
subject.stream = file
|
106
|
+
subject.each do |obj|
|
107
|
+
objects << obj
|
108
|
+
end
|
109
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with a stream passed to the constructor' do
|
114
|
+
it 'yields each object in the stream' do
|
115
|
+
objects = []
|
116
|
+
unpacker = described_class.new(StringIO.new(buffer1 + buffer2 + buffer3))
|
117
|
+
unpacker.each do |obj|
|
118
|
+
objects << obj
|
119
|
+
end
|
120
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#feed_each' do
|
126
|
+
it 'feeds the buffer then runs #each' do
|
127
|
+
objects = []
|
128
|
+
subject.feed_each(buffer1 + buffer2 + buffer3) do |obj|
|
129
|
+
objects << obj
|
130
|
+
end
|
131
|
+
objects.should == [{'foo' => 'bar'}, {'hello' => {'world' => [1, 2, 3]}}, {'x' => 'y'}]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '#fill' do
|
136
|
+
it 'is a no-op' do
|
137
|
+
subject.stream = StringIO.new(buffer1 + buffer2 + buffer3)
|
138
|
+
subject.fill
|
139
|
+
subject.each { |obj| }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#reset' do
|
144
|
+
context 'with a buffer' do
|
145
|
+
it 'is unclear what it is supposed to do'
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with a stream' do
|
149
|
+
it 'is unclear what it is supposed to do'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'regressions' do
|
154
|
+
it 'handles massive arrays (issue #2)' do
|
155
|
+
array = ['foo'] * 10_000
|
156
|
+
MessagePack.unpack(MessagePack.pack(array)).should have(10_000).items
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/spec/msgpack_spec.rb
CHANGED
@@ -69,8 +69,13 @@ describe MessagePack do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
context 'with other things' do
|
72
|
-
it 'raises an error on #pack' do
|
72
|
+
it 'raises an error on #pack with an unsupported type' do
|
73
73
|
expect { MessagePack.pack(self) }.to raise_error(ArgumentError, /^Cannot pack type:/)
|
74
74
|
end
|
75
|
+
|
76
|
+
it 'rasies an error on #unpack with garbage' do
|
77
|
+
pending
|
78
|
+
expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
|
79
|
+
end
|
75
80
|
end
|
76
81
|
end
|
metadata
CHANGED
@@ -1,76 +1,70 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: msgpack-jruby
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 1
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
version: 1.0.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.1.3
|
10
6
|
platform: java
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Theo Hultberg
|
13
|
-
autorequire:
|
9
|
+
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
date: 2011-09-15 00:00:00 +02:00
|
18
|
-
default_executable:
|
12
|
+
date: 2012-06-14 00:00:00.000000000Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
14
|
description: JRuby compatible MessagePack implementation that does not use FFI
|
22
|
-
email:
|
15
|
+
email:
|
23
16
|
- theo@iconara.net
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
19
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
20
|
+
files:
|
31
21
|
- .gitignore
|
32
22
|
- .rspec
|
33
23
|
- .rvmrc
|
34
24
|
- Gemfile
|
25
|
+
- Gemfile.lock
|
35
26
|
- Rakefile
|
36
|
-
- ext
|
37
|
-
-
|
38
|
-
-
|
27
|
+
- ext/.gitignore
|
28
|
+
- ext/java/MsgpackJrubyService.java
|
29
|
+
- ext/java/org/msgpack/jruby/MessagePackLibrary.java
|
30
|
+
- ext/java/org/msgpack/jruby/RubyObjectPacker.java
|
31
|
+
- ext/java/org/msgpack/jruby/RubyObjectUnpacker.java
|
32
|
+
- lib/ext/javassist-3.15.0-GA.jar
|
33
|
+
- lib/ext/msgpack-0.6.6.jar
|
34
|
+
- lib/ext/msgpack_jruby.jar
|
39
35
|
- lib/msgpack.rb
|
40
36
|
- lib/msgpack/version.rb
|
41
37
|
- msgpack-jruby.gemspec
|
42
38
|
- spec/benchmark.rb
|
39
|
+
- spec/msgpack/unpacker_spec.rb
|
43
40
|
- spec/msgpack_spec.rb
|
44
41
|
- spec/spec_helper.rb
|
45
|
-
has_rdoc: true
|
46
42
|
homepage: http://github.com/iconara/msgpack-jruby
|
47
43
|
licenses: []
|
48
|
-
|
49
|
-
post_install_message:
|
44
|
+
post_install_message:
|
50
45
|
rdoc_options: []
|
51
|
-
|
52
|
-
require_paths:
|
46
|
+
require_paths:
|
53
47
|
- lib
|
54
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
-
requirements:
|
56
|
-
- -
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
segments:
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
59
53
|
- 0
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
version:
|
54
|
+
hash: 2
|
55
|
+
version: '0'
|
56
|
+
none: false
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
none: false
|
68
63
|
requirements: []
|
69
|
-
|
70
64
|
rubyforge_project: msgpack-jruby
|
71
|
-
rubygems_version: 1.
|
72
|
-
signing_key:
|
65
|
+
rubygems_version: 1.8.15
|
66
|
+
signing_key:
|
73
67
|
specification_version: 3
|
74
68
|
summary: MessagePack implementation for JRuby
|
75
69
|
test_files: []
|
76
|
-
|
70
|
+
...
|
@@ -1,156 +0,0 @@
|
|
1
|
-
package org.msgpack.jruby;
|
2
|
-
|
3
|
-
|
4
|
-
import java.io.IOException;
|
5
|
-
import java.io.ByteArrayOutputStream;
|
6
|
-
import java.math.BigInteger;
|
7
|
-
import java.util.Map;
|
8
|
-
import java.util.HashMap;
|
9
|
-
import java.lang.reflect.Field;
|
10
|
-
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
-
import org.jruby.Ruby;
|
12
|
-
import org.jruby.RubyObject;
|
13
|
-
import org.jruby.RubyString;
|
14
|
-
import org.jruby.RubySymbol;
|
15
|
-
import org.jruby.RubyArray;
|
16
|
-
import org.jruby.RubyHash;
|
17
|
-
import org.jruby.RubyBoolean;
|
18
|
-
import org.jruby.RubyInteger;
|
19
|
-
import org.jruby.RubyFixnum;
|
20
|
-
import org.jruby.RubyFloat;
|
21
|
-
import org.jruby.RubyBignum;
|
22
|
-
import org.jruby.RubyNil;
|
23
|
-
import org.msgpack.Packer;
|
24
|
-
import org.msgpack.Unpacker;
|
25
|
-
import org.msgpack.MessagePackObject;
|
26
|
-
import org.msgpack.MessageTypeException;
|
27
|
-
import org.msgpack.object.MapType;
|
28
|
-
|
29
|
-
|
30
|
-
public class MessagePack {
|
31
|
-
private static final MessagePack instance = new MessagePack();
|
32
|
-
|
33
|
-
public static RubyString pack(RubyObject o) throws IOException {
|
34
|
-
return instance.packObject(o);
|
35
|
-
}
|
36
|
-
|
37
|
-
public static RubyObject unpack(RubyString s) throws IOException {
|
38
|
-
return instance.unpackString(s);
|
39
|
-
}
|
40
|
-
|
41
|
-
public RubyString packObject(IRubyObject o) throws IOException {
|
42
|
-
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
43
|
-
_pack(o, new Packer(stream));
|
44
|
-
Ruby runtime = o == null ? Ruby.getGlobalRuntime() : o.getRuntime();
|
45
|
-
return RubyString.newString(runtime, stream.toByteArray());
|
46
|
-
}
|
47
|
-
|
48
|
-
private void _pack(IRubyObject o, Packer packer) throws IOException {
|
49
|
-
if (o == null || o instanceof RubyNil) {
|
50
|
-
packer.packNil();
|
51
|
-
} else if (o instanceof RubyBoolean) {
|
52
|
-
packer.packBoolean((Boolean) ((RubyBoolean) o).toJava(Boolean.class));
|
53
|
-
} else if (o instanceof RubyBignum) {
|
54
|
-
packer.packBigInteger(((RubyBignum) o).getBigIntegerValue());
|
55
|
-
} else if (o instanceof RubyInteger) {
|
56
|
-
packer.packLong(((RubyInteger) o).getLongValue());
|
57
|
-
} else if (o instanceof RubyFixnum) {
|
58
|
-
packer.packLong(((RubyFixnum) o).getLongValue());
|
59
|
-
} else if (o instanceof RubyFloat) {
|
60
|
-
packer.packDouble(((RubyFloat) o).getDoubleValue());
|
61
|
-
} else if (o instanceof RubyString) {
|
62
|
-
byte[] bytes = ((RubyString) o).getBytes();
|
63
|
-
packer.packRaw(bytes.length);
|
64
|
-
packer.packRawBody(bytes);
|
65
|
-
} else if (o instanceof RubySymbol) {
|
66
|
-
_pack((IRubyObject) ((RubySymbol) o).to_s(), packer);
|
67
|
-
} else if (o instanceof RubyArray) {
|
68
|
-
RubyArray array = (RubyArray) o;
|
69
|
-
int count = array.size();
|
70
|
-
packer.packArray(count);
|
71
|
-
for (int i = 0; i < count; i++) {
|
72
|
-
_pack(array.entry(i), packer);
|
73
|
-
}
|
74
|
-
} else if (o instanceof RubyHash) {
|
75
|
-
RubyHash hash = (RubyHash) o;
|
76
|
-
int count = hash.size();
|
77
|
-
packer.packMap(count);
|
78
|
-
RubyArray keys = hash.keys();
|
79
|
-
RubyArray values = hash.rb_values();
|
80
|
-
for (int i = 0; i < count; i++) {
|
81
|
-
_pack(keys.entry(i), packer);
|
82
|
-
_pack(values.entry(i), packer);
|
83
|
-
}
|
84
|
-
} else {
|
85
|
-
throw Ruby.getGlobalRuntime().newArgumentError(String.format("Cannot pack type: %s", o.getClass().getName()));
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
public RubyObject unpackString(RubyString blob) throws IOException {
|
90
|
-
RubyObject obj = null;
|
91
|
-
Unpacker unpacker = new Unpacker();
|
92
|
-
unpacker.wrap(blob.getBytes());
|
93
|
-
return _unpack(unpacker.iterator().next(), blob.getRuntime());
|
94
|
-
}
|
95
|
-
|
96
|
-
private static Field cachedMapField = null;
|
97
|
-
|
98
|
-
private RubyObject _unpack(MessagePackObject mpo, Ruby runtime) throws IOException {
|
99
|
-
if (mpo.isNil()) {
|
100
|
-
return null;
|
101
|
-
} else if (mpo.isBooleanType()) {
|
102
|
-
return RubyBoolean.newBoolean(runtime, mpo.asBoolean());
|
103
|
-
} else if (mpo.isIntegerType()) {
|
104
|
-
try {
|
105
|
-
return RubyFixnum.newFixnum(runtime, mpo.asLong());
|
106
|
-
} catch (MessageTypeException mte) {
|
107
|
-
return RubyBignum.newBignum(runtime, mpo.asBigInteger());
|
108
|
-
}
|
109
|
-
} else if (mpo.isFloatType()) {
|
110
|
-
return RubyFloat.newFloat(runtime, mpo.asDouble());
|
111
|
-
} else if (mpo.isArrayType()) {
|
112
|
-
MessagePackObject[] mpoElements = mpo.asArray();
|
113
|
-
RubyObject[] elements = new RubyObject[mpoElements.length];
|
114
|
-
int count = mpoElements.length;
|
115
|
-
for (int i = 0; i < count; i++ ) {
|
116
|
-
elements[i] = _unpack(mpoElements[i], runtime);
|
117
|
-
}
|
118
|
-
return RubyArray.newArray(runtime, elements);
|
119
|
-
} else if (mpo.isMapType()) {
|
120
|
-
// This is hackish, but the only way to make sure that hashes
|
121
|
-
// keep their order. MessagePack's unpacking subsystem does not
|
122
|
-
// expose the key/value pair array, only a Map constructed from
|
123
|
-
// that array. This code first attempts to get that array from a
|
124
|
-
// private field, and if that fails it falls back on using the
|
125
|
-
// unordered Map.
|
126
|
-
RubyHash hash = null;
|
127
|
-
try {
|
128
|
-
if (cachedMapField == null) {
|
129
|
-
cachedMapField = mpo.getClass().getDeclaredField("map");
|
130
|
-
cachedMapField.setAccessible(true);
|
131
|
-
}
|
132
|
-
MessagePackObject[] keyValuePairs = (MessagePackObject[]) cachedMapField.get(mpo);
|
133
|
-
int count = keyValuePairs.length;
|
134
|
-
hash = RubyHash.newHash(runtime);
|
135
|
-
for (int i = 0; i < count; i += 2) {
|
136
|
-
hash.put(_unpack(keyValuePairs[i], runtime), _unpack(keyValuePairs[i + 1], runtime));
|
137
|
-
}
|
138
|
-
} catch (IllegalAccessException iae) {
|
139
|
-
} catch (NoSuchFieldException nfe) {
|
140
|
-
}
|
141
|
-
if (hash == null) {
|
142
|
-
Map<MessagePackObject, MessagePackObject> mpoMap = mpo.asMap();
|
143
|
-
hash = RubyHash.newHash(runtime);
|
144
|
-
for (Map.Entry<MessagePackObject, MessagePackObject> entry : mpoMap.entrySet()) {
|
145
|
-
hash.put(_unpack(entry.getKey(), runtime), _unpack(entry.getValue(), runtime));
|
146
|
-
}
|
147
|
-
}
|
148
|
-
return hash;
|
149
|
-
|
150
|
-
} else if (mpo.isRawType()) {
|
151
|
-
return RubyString.newString(runtime, mpo.asByteArray());
|
152
|
-
} else {
|
153
|
-
throw runtime.newArgumentError(String.format("Cannot upack type: %s", mpo.getClass().getName()));
|
154
|
-
}
|
155
|
-
}
|
156
|
-
}
|
Binary file
|
Binary file
|