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 +5 -0
- data/.rspec +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +11 -0
- data/Rakefile +22 -0
- data/ext/java/org/msgpack/jruby/MessagePack.java +156 -0
- data/lib/ext/msgpack-0.5.2-devel.jar +0 -0
- data/lib/ext/org/msgpack/jruby/MessagePack.class +0 -0
- data/lib/msgpack.rb +7 -0
- data/lib/msgpack/version.rb +3 -0
- data/msgpack-jruby.gemspec +24 -0
- data/spec/benchmark.rb +67 -0
- data/spec/msgpack_spec.rb +76 -0
- data/spec/spec_helper.rb +3 -0
- metadata +76 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create use jruby-1.6.2@msgpack-jruby
|
data/Gemfile
ADDED
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
|
Binary file
|
data/lib/msgpack.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
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
|
+
|