msgpack-jruby 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ /benchmark
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format doc
3
+
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use jruby-1.6.2@msgpack-jruby
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec'
7
+ gem 'viiite'
8
+ gem 'ffi-ncurses'
9
+ gem 'bson'
10
+ gem 'json'
11
+ end
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ task :clean do
7
+ rm Dir['lib/ext/**/*.class']
8
+ end
9
+
10
+ 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
+ end
13
+
14
+ BENCHMARK_RUBIES = ['1.9.2-p290', 'jruby-1.6.2', 'jruby-1.6.4']
15
+ BENCHMARK_GEMSET = 'msgpack-jruby-benchmarking'
16
+
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
22
+ end
@@ -0,0 +1,156 @@
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
data/lib/msgpack.rb ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'java'
4
+
5
+ $CLASSPATH << File.expand_path('../ext', __FILE__) << File.expand_path('../ext/msgpack-0.5.2-devel.jar', __FILE__)
6
+
7
+ MessagePack = org.msgpack.jruby.MessagePack
@@ -0,0 +1,3 @@
1
+ module MessagePack
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $:.push File.expand_path('../lib', __FILE__)
4
+
5
+ require 'msgpack/version'
6
+
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = 'msgpack-jruby'
10
+ s.version = MessagePack::VERSION
11
+ s.platform = 'java'
12
+ s.authors = ['Theo Hultberg']
13
+ s.email = ['theo@iconara.net']
14
+ s.homepage = 'http://github.com/iconara/msgpack-jruby'
15
+ s.summary = %q{MessagePack implementation for JRuby}
16
+ s.description = %q{JRuby compatible MessagePack implementation that does not use FFI}
17
+
18
+ s.rubyforge_project = 'msgpack-jruby'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ # s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ # s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = %w(lib)
24
+ end
data/spec/benchmark.rb ADDED
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ if RUBY_PLATFORM.include?('java')
4
+ # JRuby should use this library, MRI should use the standard gem
5
+ $: << File.expand_path('../../lib', __FILE__)
6
+ end
7
+
8
+ require 'viiite'
9
+ require 'msgpack'
10
+ require 'json'
11
+ require 'bson'
12
+
13
+
14
+ OBJECT_STRUCTURE = {'x' => ['y', 34, 2**30 + 3, 2.1223423423356, {'hello' => 'world', '5' => [63, 'asjdl']}]}
15
+ ENCODED_MSGPACK = "\x81\xA1x\x95\xA1y\"\xCE@\x00\x00\x03\xCB@\x00\xFA\x8E\x9F9\xFA\xC1\x82\xA5hello\xA5world\xA15\x92?\xA5asjdl"
16
+ 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
+ ENCODED_JSON = '{"x":["y",34,1073741827,2.1223423423356,{"hello":"world","5":[63,"asjdl"]}]}'
18
+ ITERATIONS = 1_00_000
19
+
20
+ Viiite.bm do |b|
21
+ b.variation_point :ruby, Viiite.which_ruby
22
+
23
+ [:json, :msgpack].each do |lib|
24
+ b.variation_point :lib, lib
25
+
26
+
27
+ b.report(:pack) do
28
+ ITERATIONS.times do
29
+ case lib
30
+ when :msgpack then MessagePack.pack(OBJECT_STRUCTURE)
31
+ when :bson then BSON::BSON_JAVA.serialize(OBJECT_STRUCTURE).to_s
32
+ when :json then OBJECT_STRUCTURE.to_json
33
+ end
34
+ end
35
+ end
36
+
37
+ b.report(:unpack) do
38
+ ITERATIONS.times do
39
+ case lib
40
+ when :msgpack then MessagePack.unpack(ENCODED_MSGPACK)
41
+ when :bson then BSON::BSON_JAVA.deserialize(ENCODED_BSON)
42
+ when :json then JSON.parse(ENCODED_JSON)
43
+ end
44
+ end
45
+ end
46
+
47
+ b.report(:pack_unpack) do
48
+ ITERATIONS.times do
49
+ case lib
50
+ 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)
52
+ when :json then JSON.parse(OBJECT_STRUCTURE.to_json)
53
+ end
54
+ end
55
+ end
56
+
57
+ b.report(:unpack_pack) do
58
+ ITERATIONS.times do
59
+ case lib
60
+ 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
62
+ when :json then OBJECT_STRUCTURE.to_json(JSON.parse(ENCODED_JSON))
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,76 @@
1
+ # encoding: ascii-8bit
2
+
3
+ require_relative 'spec_helper'
4
+
5
+
6
+ describe MessagePack do
7
+ tests = {
8
+ 'constant values' => [
9
+ ['true', true, "\xC3"],
10
+ ['false', false, "\xC2"],
11
+ ['nil', nil, "\xC0"]
12
+ ],
13
+ 'numbers' => [
14
+ ['zero', 0, "\x00"],
15
+ ['127', 127, "\x7F"],
16
+ ['128', 128, "\xCC\x80"],
17
+ ['256', 256, "\xCD\x01\x00"],
18
+ ['-1', -1, "\xFF"],
19
+ ['-33', -33, "\xD0\xDF"],
20
+ ['-129', -129, "\xD1\xFF\x7F"],
21
+ ['small integers', 42, "*"],
22
+ ['medium integers', 333, "\xCD\x01M"],
23
+ ['large integers', 2**31 - 1, "\xCE\x7F\xFF\xFF\xFF"],
24
+ ['huge integers', 2**64 - 1, "\xCF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"],
25
+ ['negative integers', -1, "\xFF"],
26
+ ['1.0', 1.0, "\xcb\x3f\xf0\x00\x00\x00\x00\x00\x00"],
27
+ ['small floats', 3.14, "\xCB@\t\x1E\xB8Q\xEB\x85\x1F"],
28
+ ['big floats', Math::PI * 1_000_000_000_000_000_000, "\xCBC\xC5\xCC\x96\xEF\xD1\x19%"],
29
+ ['negative floats', -2.1, "\xCB\xC0\x00\xCC\xCC\xCC\xCC\xCC\xCD"]
30
+ ],
31
+ 'strings' => [
32
+ ['strings', 'hello world', "\xABhello world"],
33
+ ['empty strings', '', "\xA0"]
34
+ ],
35
+ 'arrays' => [
36
+ ['empty arrays', [], "\x90"],
37
+ ['arrays with strings', ["hello", "world"], "\x92\xA5hello\xA5world"],
38
+ ['arrays with mixed values', ["hello", "world", 42], "\x93\xA5hello\xA5world*"],
39
+ ['arrays of arrays', [[[[1, 2], 3], 4]], "\x91\x92\x92\x92\x01\x02\x03\x04"],
40
+ ['empty arrays', [], "\x90"]
41
+ ],
42
+ 'hashes' => [
43
+ ['empty hashes', {}, "\x80"],
44
+ ['hashes', {'foo' => 'bar'}, "\x81\xA3foo\xA3bar"],
45
+ ['hashes with mixed keys and values', {'foo' => 'bar', 3 => 'three', 'four' => 4, 'x' => ['y'], 'a' => 'b'}, "\x85\xA3foo\xA3bar\x03\xA5three\xA4four\x04\xA1x\x91\xA1y\xA1a\xA1b"],
46
+ ['hashes of hashes', {{'x' => {'y' => 'z'}} => 's'}, "\x81\x81\xA1x\x81\xA1y\xA1z\xA1s"],
47
+ ['hashes with nils', {'foo' => nil}, "\x81\xA3foo\xC0"]
48
+ ]
49
+ }
50
+
51
+ tests.each do |ctx, its|
52
+ context("with #{ctx}") do
53
+ its.each do |desc, unpacked, packed|
54
+ it("encodes #{desc}") do
55
+ MessagePack.pack(unpacked).should == packed
56
+ end
57
+
58
+ it "decodes #{desc}" do
59
+ MessagePack.unpack(packed).should == unpacked
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'with symbols' do
66
+ it 'encodes symbols as strings' do
67
+ MessagePack.pack(:symbol).should == "\xA6symbol"
68
+ end
69
+ end
70
+
71
+ context 'with other things' do
72
+ it 'raises an error on #pack' do
73
+ expect { MessagePack.pack(self) }.to raise_error(ArgumentError, /^Cannot pack type:/)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ $: << File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'msgpack'
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
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
10
+ platform: java
11
+ authors:
12
+ - Theo Hultberg
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-09-15 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: JRuby compatible MessagePack implementation that does not use FFI
22
+ email:
23
+ - theo@iconara.net
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - .rspec
33
+ - .rvmrc
34
+ - Gemfile
35
+ - 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
39
+ - lib/msgpack.rb
40
+ - lib/msgpack/version.rb
41
+ - msgpack-jruby.gemspec
42
+ - spec/benchmark.rb
43
+ - spec/msgpack_spec.rb
44
+ - spec/spec_helper.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/iconara/msgpack-jruby
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 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"
68
+ requirements: []
69
+
70
+ rubyforge_project: msgpack-jruby
71
+ rubygems_version: 1.3.6
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: MessagePack implementation for JRuby
75
+ test_files: []
76
+