msgpack-jruby 1.0.0-java → 1.1.3-java

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,4 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/*
5
- /benchmark
4
+ /benchmark
data/.rvmrc CHANGED
@@ -1 +1 @@
1
- rvm --create use jruby-1.6.2@msgpack-jruby
1
+ rvm --create use jruby-1.6.7@msgpack-jruby
data/Gemfile CHANGED
@@ -1,11 +1,13 @@
1
1
  source :rubygems
2
2
 
3
- gemspec
3
+ gem 'jruby-openssl'
4
4
 
5
5
  group :test do
6
6
  gem 'rspec'
7
7
  gem 'viiite'
8
8
  gem 'ffi-ncurses'
9
9
  gem 'bson'
10
+ gem 'bson_ext', :platforms => :mri
10
11
  gem 'json'
12
+ gem 'msgpack', :platforms => :mri
11
13
  end
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
- require 'bundler'
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['lib/ext/**/*.class']
8
+ rm Dir['ext/java/**/*.class']
8
9
  end
9
10
 
10
11
  task :compile do
11
- exec %(javac -source 1.6 -target 1.6 -cp lib/ext/msgpack-0.5.2-devel.jar:$MY_RUBY_HOME/lib/jruby.jar -d lib/ext ext/java/org/msgpack/**/*.java)
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
- BENCHMARK_RUBIES = ['1.9.2-p290', 'jruby-1.6.2', 'jruby-1.6.4']
15
- BENCHMARK_GEMSET = 'msgpack-jruby-benchmarking'
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 :benchmark do
18
- rubies = BENCHMARK_RUBIES.map { |rb| "#{rb}@#{BENCHMARK_GEMSET}" }
19
- cmd = %(rvm #{rubies.join(',')} exec viiite run spec/benchmark.rb | tee benchmark | viiite report --hierarchy --regroup=bench,ruby)
20
- puts cmd
21
- system cmd
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
@@ -1,3 +1,3 @@
1
1
  module MessagePack
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.3'
3
3
  end
data/lib/msgpack.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'java'
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
- MessagePack = org.msgpack.jruby.MessagePack
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
- [:json, :msgpack].each do |lib|
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 BSON::BSON_JAVA.serialize(OBJECT_STRUCTURE).to_s
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 BSON::BSON_JAVA.deserialize(ENCODED_BSON)
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 BSON::BSON_JAVA.deserialize(BSON::BSON_JAVA.serialize(OBJECT_STRUCTURE).to_s)
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 BSON::BSON_JAVA.serialize(BSON::BSON_JAVA.deserialize(ENCODED_BSON)).to_s
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: false
5
- segments:
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/java/org/msgpack/jruby/MessagePack.java
37
- - lib/ext/msgpack-0.5.2-devel.jar
38
- - lib/ext/org/msgpack/jruby/MessagePack.class
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
- version: "0"
61
- required_rubygems_version: !ruby/object:Gem::Requirement
62
- requirements:
63
- - - ">="
64
- - !ruby/object:Gem::Version
65
- segments:
66
- - 0
67
- version: "0"
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.3.6
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