msgpack-jruby 1.1.3-java → 1.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -31,16 +31,17 @@ end
31
31
  namespace :benchmark do
32
32
  BENCHMARK_RUBIES = ['1.9.2-p0', 'jruby-1.6.5', 'jruby-head']
33
33
  BENCHMARK_GEMSET = 'msgpack-jruby-benchmarking'
34
+ BENCHMARK_FILE = 'spec/benchmarks/shootout_bm.rb'
34
35
 
35
36
  task :run do
36
37
  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
+ cmd = %(rvm #{rubies.join(',')} exec viiite run #{BENCHMARK_FILE} | tee benchmark | viiite report --hierarchy --regroup=bench,lib,ruby)
38
39
  puts cmd
39
40
  system cmd
40
41
  end
41
42
 
42
43
  task :quick do
43
- cmd = %(IMPLEMENTATIONS=msgpack viiite run spec/benchmark.rb | viiite report --hierarchy --regroup=bench)
44
+ cmd = %(IMPLEMENTATIONS=msgpack viiite run #{BENCHMARK_FILE} | viiite report --hierarchy --regroup=bench)
44
45
  puts cmd
45
46
  system cmd
46
47
  end
@@ -10,6 +10,7 @@ import org.jruby.RubyModule;
10
10
  import org.jruby.RubyClass;
11
11
  import org.jruby.RubyString;
12
12
  import org.jruby.RubyObject;
13
+ import org.jruby.RubyHash;
13
14
  import org.jruby.RubyIO;
14
15
  import org.jruby.RubyStringIO;
15
16
  import org.jruby.RubyNumeric;
@@ -54,18 +55,19 @@ public class MessagePackLibrary implements Library {
54
55
  @JRubyModule(name = "MessagePack")
55
56
  public static class MessagePackModule {
56
57
  private static MessagePack msgPack = new MessagePack();
58
+ private static RubyObjectPacker packer = new RubyObjectPacker(msgPack);
57
59
  private static RubyObjectUnpacker unpacker = new RubyObjectUnpacker(msgPack);
58
60
 
59
61
  @JRubyMethod(module = true, required = 1)
60
62
  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());
63
+ return packer.pack(obj);
64
64
  }
65
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());
66
+ @JRubyMethod(module = true, required = 1, optional = 1)
67
+ public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) throws IOException {
68
+ RubyHash options = (args.length == 2) ? (RubyHash) args[1] : null;
69
+ RubyString str = args[0].asString();
70
+ return unpacker.unpack(str, options);
69
71
  }
70
72
  }
71
73
 
@@ -89,6 +91,7 @@ public class MessagePackLibrary implements Library {
89
91
  private MessagePackUnpacker streamUnpacker;
90
92
  private IRubyObject stream;
91
93
  private IRubyObject data;
94
+ private RubyHash options;
92
95
 
93
96
  public Unpacker(Ruby runtime, RubyClass type, MessagePack msgPack) {
94
97
  super(runtime, type);
@@ -100,10 +103,17 @@ public class MessagePackLibrary implements Library {
100
103
  this.data = null;
101
104
  }
102
105
 
103
- @JRubyMethod(name = "initialize", optional = 1, visibility = PRIVATE)
106
+ @JRubyMethod(name = "initialize", optional = 2, visibility = PRIVATE)
104
107
  public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
105
- if (args.length > 0) {
108
+ if (args.length == 0) {
109
+ options = null;
110
+ } else if (args.length == 1 && args[0] instanceof RubyHash) {
111
+ options = (RubyHash) args[0];
112
+ } else if (args.length > 0) {
106
113
  setStream(ctx, args[0]);
114
+ if (args.length > 2) {
115
+ options = (RubyHash) args[1];
116
+ }
107
117
  }
108
118
  return this;
109
119
  }
@@ -125,7 +135,7 @@ public class MessagePackLibrary implements Library {
125
135
  byte[] bytes = data.asString().getBytes();
126
136
  MessagePackBufferUnpacker localBufferUnpacker = new MessagePackBufferUnpacker(msgPack, bytes.length);
127
137
  localBufferUnpacker.wrap(bytes, jOffset, jLimit == -1 ? bytes.length - jOffset : jLimit);
128
- this.data = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), localBufferUnpacker.readValue());
138
+ this.data = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), localBufferUnpacker.readValue(), options);
129
139
  return ctx.getRuntime().newFixnum(jOffset + localBufferUnpacker.getReadByteCount());
130
140
  } catch (IOException ioe) {
131
141
  // TODO: how to throw Ruby exceptions?
@@ -177,12 +187,12 @@ public class MessagePackLibrary implements Library {
177
187
  }
178
188
  if (block.isGiven()) {
179
189
  for (Value value : localUnpacker) {
180
- IRubyObject rubyObject = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), value);
190
+ IRubyObject rubyObject = rubyObjectUnpacker.valueToRubyObject(ctx.getRuntime(), value, options);
181
191
  block.yield(ctx, rubyObject);
182
192
  }
183
193
  return ctx.getRuntime().getNil();
184
194
  } else {
185
- return RubyEnumerator.RubyEnumeratorKernel.obj_to_enum(ctx, this, Block.NULL_BLOCK);
195
+ return RubyEnumerator.RubyEnumeratorKernel.obj_to_enum(ctx, this);
186
196
  }
187
197
  }
188
198
 
@@ -4,8 +4,7 @@ package org.msgpack.jruby;
4
4
  import java.io.IOException;
5
5
 
6
6
  import org.msgpack.MessagePack;
7
- import org.msgpack.packer.Packer;
8
- import org.msgpack.packer.MessagePackBufferPacker;
7
+ import org.msgpack.packer.BufferPacker;
9
8
 
10
9
  import org.jruby.RubyObject;
11
10
  import org.jruby.RubyNil;
@@ -21,91 +20,91 @@ import org.jruby.RubyHash;
21
20
  import org.jruby.runtime.builtin.IRubyObject;
22
21
 
23
22
 
24
- public class RubyObjectPacker extends MessagePackBufferPacker {
25
- private final Packer packer;
23
+ public class RubyObjectPacker {
24
+ private final MessagePack msgPack;
26
25
 
27
- public RubyObjectPacker(MessagePack msgPack, Packer packer) {
28
- super(msgPack);
29
- this.packer = packer;
26
+ public RubyObjectPacker(MessagePack msgPack) {
27
+ this.msgPack = msgPack;
30
28
  }
31
29
 
32
- public Packer write(IRubyObject o) throws IOException {
30
+ public RubyString pack(IRubyObject o) throws IOException {
31
+ return RubyString.newString(o.getRuntime(), packRaw(o));
32
+ }
33
+
34
+ public byte[] packRaw(IRubyObject o) throws IOException {
35
+ BufferPacker packer = msgPack.createBufferPacker();
36
+ write(packer, o);
37
+ return packer.toByteArray();
38
+ }
39
+
40
+ private void write(BufferPacker packer, IRubyObject o) throws IOException {
33
41
  if (o == null || o instanceof RubyNil) {
34
42
  packer.writeNil();
35
- return this;
36
43
  } else if (o instanceof RubyBoolean) {
37
44
  packer.write(((RubyBoolean) o).isTrue());
38
- return this;
39
45
  } else if (o instanceof RubyBignum) {
40
- return write((RubyBignum) o);
46
+ write(packer, (RubyBignum) o);
41
47
  } else if (o instanceof RubyInteger) {
42
- return write((RubyInteger) o);
48
+ write(packer, (RubyInteger) o);
43
49
  } else if (o instanceof RubyFixnum) {
44
- return write((RubyFixnum) o);
50
+ write(packer, (RubyFixnum) o);
45
51
  } else if (o instanceof RubyFloat) {
46
- return write((RubyFloat) o);
52
+ write(packer, (RubyFloat) o);
47
53
  } else if (o instanceof RubyString) {
48
- return write((RubyString) o);
54
+ write(packer, (RubyString) o);
49
55
  } else if (o instanceof RubySymbol) {
50
- return write((RubySymbol) o);
56
+ write(packer, (RubySymbol) o);
51
57
  } else if (o instanceof RubyArray) {
52
- return write((RubyArray) o);
58
+ write(packer, (RubyArray) o);
53
59
  } else if (o instanceof RubyHash) {
54
- return write((RubyHash) o);
60
+ write(packer, (RubyHash) o);
55
61
  } else {
56
62
  throw o.getRuntime().newArgumentError(String.format("Cannot pack type: %s", o.getClass().getName()));
57
63
  }
58
64
  }
59
65
 
60
- public final Packer write(RubyBignum bignum) throws IOException {
66
+ private void write(BufferPacker packer, RubyBignum bignum) throws IOException {
61
67
  packer.write(bignum.getBigIntegerValue());
62
- return this;
63
68
  }
64
69
 
65
- public final Packer write(RubyInteger integer) throws IOException {
70
+ private void write(BufferPacker packer, RubyInteger integer) throws IOException {
66
71
  packer.write(integer.getLongValue());
67
- return this;
68
72
  }
69
73
 
70
- public final Packer write(RubyFixnum fixnum) throws IOException {
74
+ private void write(BufferPacker packer, RubyFixnum fixnum) throws IOException {
71
75
  packer.write(fixnum.getLongValue());
72
- return this;
73
76
  }
74
77
 
75
- public final Packer write(RubyFloat flt) throws IOException {
78
+ private void write(BufferPacker packer, RubyFloat flt) throws IOException {
76
79
  packer.write(flt.getDoubleValue());
77
- return this;
78
80
  }
79
81
 
80
- public final Packer write(RubyString str) throws IOException {
82
+ private void write(BufferPacker packer, RubyString str) throws IOException {
81
83
  packer.write(str.getBytes());
82
- return this;
83
84
  }
84
85
 
85
- public final Packer write(RubySymbol sym) throws IOException {
86
- return write((RubyString) sym.to_s());
86
+ private void write(BufferPacker packer, RubySymbol sym) throws IOException {
87
+ write(packer, (RubyString) sym.to_s());
87
88
  }
88
89
 
89
- public final Packer write(RubyArray array) throws IOException {
90
+ private void write(BufferPacker packer, RubyArray array) throws IOException {
90
91
  int count = array.size();
91
92
  packer.writeArrayBegin(count);
92
93
  for (int i = 0; i < count; i++) {
93
- write((RubyObject) array.entry(i));
94
+ write(packer, (RubyObject) array.entry(i));
94
95
  }
95
96
  packer.writeArrayEnd();
96
- return this;
97
97
  }
98
98
 
99
- public final Packer write(RubyHash hash) throws IOException {
99
+ private void write(BufferPacker packer, RubyHash hash) throws IOException {
100
100
  int count = hash.size();
101
101
  packer.writeMapBegin(count);
102
102
  RubyArray keys = hash.keys();
103
103
  RubyArray values = hash.rb_values();
104
104
  for (int i = 0; i < count; i++) {
105
- write((RubyObject) keys.entry(i));
106
- write((RubyObject) values.entry(i));
105
+ write(packer, (RubyObject) keys.entry(i));
106
+ write(packer, (RubyObject) values.entry(i));
107
107
  }
108
108
  packer.writeMapEnd();
109
- return this;
110
109
  }
111
110
  }
@@ -28,6 +28,7 @@ import org.jruby.RubySymbol;
28
28
  import org.jruby.RubyArray;
29
29
  import org.jruby.RubyHash;
30
30
  import org.jruby.runtime.builtin.IRubyObject;
31
+ import org.jruby.runtime.ThreadContext;
31
32
 
32
33
 
33
34
  public class RubyObjectUnpacker {
@@ -37,17 +38,17 @@ public class RubyObjectUnpacker {
37
38
  this.msgPack = msgPack;
38
39
  }
39
40
 
40
- public IRubyObject unpack(RubyString str) throws IOException {
41
- return unpack(str.getRuntime(), str.getBytes());
41
+ public IRubyObject unpack(RubyString str, RubyHash options) throws IOException {
42
+ return unpack(str.getRuntime(), str.getBytes(), options);
42
43
  }
43
44
 
44
- public IRubyObject unpack(Ruby runtime, byte[] data) throws IOException {
45
+ public IRubyObject unpack(Ruby runtime, byte[] data, RubyHash options) throws IOException {
45
46
  MessagePackBufferUnpacker unpacker = new MessagePackBufferUnpacker(msgPack);
46
47
  unpacker.wrap(data);
47
- return valueToRubyObject(runtime, unpacker.readValue());
48
+ return valueToRubyObject(runtime, unpacker.readValue(), options);
48
49
  }
49
50
 
50
- IRubyObject valueToRubyObject(Ruby runtime, Value value) {
51
+ IRubyObject valueToRubyObject(Ruby runtime, Value value, RubyHash options) {
51
52
  switch (value.getType()) {
52
53
  case NIL:
53
54
  return runtime.getNil();
@@ -58,9 +59,9 @@ public class RubyObjectUnpacker {
58
59
  case FLOAT:
59
60
  return convert(runtime, value.asFloatValue());
60
61
  case ARRAY:
61
- return convert(runtime, value.asArrayValue());
62
+ return convert(runtime, value.asArrayValue(), options);
62
63
  case MAP:
63
- return convert(runtime, value.asMapValue());
64
+ return convert(runtime, value.asMapValue(), options);
64
65
  case RAW:
65
66
  return convert(runtime, value.asRawValue());
66
67
  default:
@@ -86,24 +87,29 @@ public class RubyObjectUnpacker {
86
87
  return RubyFloat.newFloat(runtime, value.asFloatValue().getDouble());
87
88
  }
88
89
 
89
- private IRubyObject convert(Ruby runtime, ArrayValue value) {
90
+ private IRubyObject convert(Ruby runtime, ArrayValue value, RubyHash options) {
90
91
  Value[] elements = value.asArrayValue().getElementArray();
91
92
  int elementCount = elements.length;
92
93
  IRubyObject[] rubyObjects = new IRubyObject[elementCount];
93
94
  for (int i = 0; i < elementCount; i++) {
94
- rubyObjects[i] = valueToRubyObject(runtime, elements[i]);
95
+ rubyObjects[i] = valueToRubyObject(runtime, elements[i], options);
95
96
  }
96
97
  return RubyArray.newArray(runtime, rubyObjects);
97
98
  }
98
99
 
99
- private IRubyObject convert(Ruby runtime, MapValue value) {
100
+ private IRubyObject convert(Ruby runtime, MapValue value, RubyHash options) {
100
101
  Value[] keysAndValues = value.asMapValue().getKeyValueArray();
101
102
  int kvCount = keysAndValues.length;
102
103
  RubyHash hash = RubyHash.newHash(runtime);
103
104
  for (int i = 0; i < kvCount; i += 2) {
104
105
  Value k = keysAndValues[i];
105
106
  Value v = keysAndValues[i + 1];
106
- hash.put(valueToRubyObject(runtime, k), valueToRubyObject(runtime, v));
107
+ IRubyObject kk = valueToRubyObject(runtime, k, options);
108
+ IRubyObject vv = valueToRubyObject(runtime, v, options);
109
+ if (symbolizeKeysEnabled(options)) {
110
+ kk = runtime.newSymbol(kk.asString().getByteList());
111
+ }
112
+ hash.put(kk, vv);
107
113
  }
108
114
  return hash;
109
115
  }
@@ -111,4 +117,20 @@ public class RubyObjectUnpacker {
111
117
  private IRubyObject convert(Ruby runtime, RawValue value) {
112
118
  return RubyString.newString(runtime, value.asRawValue().getByteArray());
113
119
  }
120
+
121
+ private boolean symbolizeKeysEnabled(RubyHash options) {
122
+ if (options == null) {
123
+ return false;
124
+ } else {
125
+ Ruby runtime = options.getRuntime();
126
+ ThreadContext ctx = runtime.getCurrentContext();
127
+ RubySymbol key = runtime.newSymbol("symbolize_keys");
128
+ IRubyObject value = options.fastARef(key);
129
+ if (value == null) {
130
+ return false;
131
+ } else {
132
+ return value.isTrue();
133
+ }
134
+ }
135
+ }
114
136
  }
Binary file
@@ -1,3 +1,3 @@
1
1
  module MessagePack
2
- VERSION = '1.1.3'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  if RUBY_PLATFORM.include?('java')
4
4
  # JRuby should use this library, MRI should use the standard gem
5
- $: << File.expand_path('../../lib', __FILE__)
5
+ $: << File.expand_path('../../../lib', __FILE__)
6
6
  end
7
7
 
8
8
  require 'viiite'
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ $: << File.expand_path('../../../lib', __FILE__)
4
+
5
+ require 'viiite'
6
+ require 'msgpack'
7
+
8
+
9
+ iterations = 10_000
10
+ data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
11
+
12
+ Viiite.bm do |b|
13
+ b.report(:strings) do
14
+ iterations.times do
15
+ MessagePack.unpack(data)
16
+ end
17
+ end
18
+
19
+ b.report(:symbols) do
20
+ options = {:symbolize_keys => true}
21
+ iterations.times do
22
+ MessagePack.unpack(data, options)
23
+ end
24
+ end
25
+ end
@@ -156,4 +156,38 @@ describe ::MessagePack::Unpacker do
156
156
  MessagePack.unpack(MessagePack.pack(array)).should have(10_000).items
157
157
  end
158
158
  end
159
+
160
+ context 'extensions' do
161
+ context 'symbolized keys' do
162
+ let :buffer do
163
+ MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
164
+ end
165
+
166
+ let :unpacker do
167
+ described_class.new(:symbolize_keys => true)
168
+ end
169
+
170
+ it 'can symbolize keys when using #execute' do
171
+ unpacker.execute(buffer, 0)
172
+ unpacker.data.should == {:hello => 'world', :nested => ['object', {:structure => true}]}
173
+ end
174
+
175
+ it 'can symbolize keys when using #each' do
176
+ objs = []
177
+ unpacker.feed(buffer)
178
+ unpacker.each do |obj|
179
+ objs << obj
180
+ end
181
+ objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
182
+ end
183
+
184
+ it 'can symbolize keys when using #feed_each' do
185
+ objs = []
186
+ unpacker.feed_each(buffer) do |obj|
187
+ objs << obj
188
+ end
189
+ objs.should == [{:hello => 'world', :nested => ['object', {:structure => true}]}]
190
+ end
191
+ end
192
+ end
159
193
  end
data/spec/msgpack_spec.rb CHANGED
@@ -78,4 +78,12 @@ describe MessagePack do
78
78
  expect { MessagePack.unpack('asdka;sd') }.to raise_error(MessagePack::UnpackError)
79
79
  end
80
80
  end
81
+
82
+ context 'extensions' do
83
+ it 'can unpack hashes with symbolized keys' do
84
+ packed = MessagePack.pack({'hello' => 'world', 'nested' => ['object', {'structure' => true}]})
85
+ unpacked = MessagePack.unpack(packed, :symbolize_keys => true)
86
+ unpacked.should == {:hello => 'world', :nested => ['object', {:structure => true}]}
87
+ end
88
+ end
81
89
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: msgpack-jruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.1.3
5
+ version: 1.2.0
6
6
  platform: java
7
7
  authors:
8
8
  - Theo Hultberg
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-14 00:00:00.000000000Z
12
+ date: 2012-07-29 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: JRuby compatible MessagePack implementation that does not use FFI
15
15
  email:
@@ -35,7 +35,8 @@ files:
35
35
  - lib/msgpack.rb
36
36
  - lib/msgpack/version.rb
37
37
  - msgpack-jruby.gemspec
38
- - spec/benchmark.rb
38
+ - spec/benchmarks/shootout_bm.rb
39
+ - spec/benchmarks/symbolize_keys_bm.rb
39
40
  - spec/msgpack/unpacker_spec.rb
40
41
  - spec/msgpack_spec.rb
41
42
  - spec/spec_helper.rb