msgpack-jruby 1.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.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
+