msgpack 0.5.9-x86-mingw32 → 0.5.10-x86-mingw32

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.
@@ -0,0 +1,309 @@
1
+ package org.msgpack.jruby;
2
+
3
+
4
+ import java.math.BigInteger;
5
+ import java.nio.ByteBuffer;
6
+
7
+ import org.jruby.Ruby;
8
+ import org.jruby.RubyObject;
9
+ import org.jruby.RubyNil;
10
+ import org.jruby.RubyBoolean;
11
+ import org.jruby.RubyBignum;
12
+ import org.jruby.RubyInteger;
13
+ import org.jruby.RubyFixnum;
14
+ import org.jruby.RubyFloat;
15
+ import org.jruby.RubyString;
16
+ import org.jruby.RubySymbol;
17
+ import org.jruby.RubyArray;
18
+ import org.jruby.RubyHash;
19
+ import org.jruby.RubyEncoding;
20
+ import org.jruby.runtime.builtin.IRubyObject;
21
+ import org.jruby.util.ByteList;
22
+
23
+ import org.jcodings.Encoding;
24
+ import org.jcodings.specific.UTF8Encoding;
25
+
26
+ import static org.msgpack.jruby.Types.*;
27
+
28
+
29
+ public class Encoder {
30
+
31
+ private static final int CACHE_LINE_SIZE = 64;
32
+ private static final int ARRAY_HEADER_SIZE = 24;
33
+
34
+ private final Ruby runtime;
35
+ private final Encoding binaryEncoding;
36
+ private final Encoding utf8Encoding;
37
+
38
+ private ByteBuffer buffer;
39
+
40
+ public Encoder(Ruby runtime) {
41
+ this.runtime = runtime;
42
+ this.buffer = ByteBuffer.allocate(CACHE_LINE_SIZE - ARRAY_HEADER_SIZE);
43
+ this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
44
+ this.utf8Encoding = UTF8Encoding.INSTANCE;
45
+ }
46
+
47
+ private void ensureRemainingCapacity(int c) {
48
+ if (buffer.remaining() < c) {
49
+ int newLength = Math.max(buffer.capacity() + (buffer.capacity() >> 1), buffer.capacity() + c);
50
+ newLength += CACHE_LINE_SIZE - ((ARRAY_HEADER_SIZE + newLength) % CACHE_LINE_SIZE);
51
+ buffer = ByteBuffer.allocate(newLength).put(buffer.array(), 0, buffer.position());
52
+ }
53
+ }
54
+
55
+ private IRubyObject readRubyString() {
56
+ IRubyObject str = runtime.newString(new ByteList(buffer.array(), 0, buffer.position(), binaryEncoding, false));
57
+ buffer.clear();
58
+ return str;
59
+ }
60
+
61
+ public IRubyObject encode(IRubyObject object) {
62
+ appendObject(object);
63
+ return readRubyString();
64
+ }
65
+
66
+ public IRubyObject encode(IRubyObject object, IRubyObject destination) {
67
+ appendObject(object, destination);
68
+ return readRubyString();
69
+ }
70
+
71
+ public IRubyObject encodeArrayHeader(int size) {
72
+ appendArrayHeader(size);
73
+ return readRubyString();
74
+ }
75
+
76
+ public IRubyObject encodeMapHeader(int size) {
77
+ appendHashHeader(size);
78
+ return readRubyString();
79
+ }
80
+
81
+ private void appendObject(IRubyObject object) {
82
+ appendObject(object, null);
83
+ }
84
+
85
+ private void appendObject(IRubyObject object, IRubyObject destination) {
86
+ if (object == null || object instanceof RubyNil) {
87
+ ensureRemainingCapacity(1);
88
+ buffer.put(NIL);
89
+ } else if (object instanceof RubyBoolean) {
90
+ ensureRemainingCapacity(1);
91
+ buffer.put(((RubyBoolean) object).isTrue() ? TRUE : FALSE);
92
+ } else if (object instanceof RubyBignum) {
93
+ appendBignum((RubyBignum) object);
94
+ } else if (object instanceof RubyInteger) {
95
+ appendInteger((RubyInteger) object);
96
+ } else if (object instanceof RubyFloat) {
97
+ appendFloat((RubyFloat) object);
98
+ } else if (object instanceof RubyString) {
99
+ appendString((RubyString) object);
100
+ } else if (object instanceof RubySymbol) {
101
+ appendString(((RubySymbol) object).asString());
102
+ } else if (object instanceof RubyArray) {
103
+ appendArray((RubyArray) object);
104
+ } else if (object instanceof RubyHash) {
105
+ appendHash((RubyHash) object);
106
+ } else if (object.respondsTo("to_msgpack")) {
107
+ appendCustom(object, destination);
108
+ } else {
109
+ throw runtime.newArgumentError(String.format("Cannot pack type: %s", object.getClass().getName()));
110
+ }
111
+ }
112
+
113
+ private void appendBignum(RubyBignum object) {
114
+ BigInteger value = ((RubyBignum) object).getBigIntegerValue();
115
+ if (value.bitLength() > 64 || (value.bitLength() > 63 && value.signum() < 0)) {
116
+ throw runtime.newArgumentError(String.format("Cannot pack big integer: %s", value));
117
+ }
118
+ ensureRemainingCapacity(9);
119
+ buffer.put(value.signum() < 0 ? INT64 : UINT64);
120
+ byte[] b = value.toByteArray();
121
+ buffer.put(b, b.length - 8, 8);
122
+ }
123
+
124
+ private void appendInteger(RubyInteger object) {
125
+ long value = ((RubyInteger) object).getLongValue();
126
+ if (value < 0) {
127
+ if (value < Short.MIN_VALUE) {
128
+ if (value < Integer.MIN_VALUE) {
129
+ ensureRemainingCapacity(9);
130
+ buffer.put(INT64);
131
+ buffer.putLong(value);
132
+ } else {
133
+ ensureRemainingCapacity(5);
134
+ buffer.put(INT32);
135
+ buffer.putInt((int) value);
136
+ }
137
+ } else if (value >= -0x20L) {
138
+ ensureRemainingCapacity(1);
139
+ byte b = (byte) (value | 0xe0);
140
+ buffer.put(b);
141
+ } else if (value < Byte.MIN_VALUE) {
142
+ ensureRemainingCapacity(3);
143
+ buffer.put(INT16);
144
+ buffer.putShort((short) value);
145
+ } else {
146
+ ensureRemainingCapacity(2);
147
+ buffer.put(INT8);
148
+ buffer.put((byte) value);
149
+ }
150
+ } else {
151
+ if (value < 0x10000L) {
152
+ if (value < 128L) {
153
+ ensureRemainingCapacity(1);
154
+ buffer.put((byte) value);
155
+ } else if (value < 0x100L) {
156
+ ensureRemainingCapacity(2);
157
+ buffer.put(UINT8);
158
+ buffer.put((byte) value);
159
+ } else {
160
+ ensureRemainingCapacity(3);
161
+ buffer.put(UINT16);
162
+ buffer.putShort((short) value);
163
+ }
164
+ } else if (value < 0x100000000L) {
165
+ ensureRemainingCapacity(5);
166
+ buffer.put(UINT32);
167
+ buffer.putInt((int) value);
168
+ } else {
169
+ ensureRemainingCapacity(9);
170
+ buffer.put(INT64);
171
+ buffer.putLong(value);
172
+ }
173
+ }
174
+ }
175
+
176
+ private void appendFloat(RubyFloat object) {
177
+ double value = object.getDoubleValue();
178
+ float f = (float) value;
179
+ //TODO: msgpack-ruby original does encode this value as Double, not float
180
+ // if (Double.compare(f, value) == 0) {
181
+ // ensureRemainingCapacity(5);
182
+ // buffer.put(FLOAT32);
183
+ // buffer.putFloat(f);
184
+ // } else {
185
+ ensureRemainingCapacity(9);
186
+ buffer.put(FLOAT64);
187
+ buffer.putDouble(value);
188
+ // }
189
+ }
190
+
191
+ private void appendString(RubyString object) {
192
+ Encoding encoding = object.getEncoding();
193
+ boolean binary = encoding == binaryEncoding;
194
+ if (encoding != utf8Encoding && encoding != binaryEncoding) {
195
+ object = (RubyString) ((RubyString) object).encode(runtime.getCurrentContext(), RubyEncoding.newEncoding(runtime, utf8Encoding));
196
+ }
197
+ ByteList bytes = object.getByteList();
198
+ int length = bytes.length();
199
+ if (length < 32 && !binary) {
200
+ ensureRemainingCapacity(1 + length);
201
+ buffer.put((byte) (length | FIXSTR));
202
+ //TODO: msgpack-ruby original does encode this value as RAW16 (currently should be BIN8/STR8)
203
+ // } else if (length <= 0xff) {
204
+ // ensureRemainingCapacity(2 + length);
205
+ // buffer.put(binary ? BIN8 : STR8);
206
+ // buffer.put((byte) length);
207
+ } else if (length <= 0xffff) {
208
+ ensureRemainingCapacity(3 + length);
209
+ buffer.put(binary ? BIN16 : STR16);
210
+ buffer.putShort((short) length);
211
+ } else {
212
+ ensureRemainingCapacity(5 + length);
213
+ buffer.put(binary ? BIN32 : STR32);
214
+ buffer.putInt((int) length);
215
+ }
216
+ buffer.put(bytes.unsafeBytes(), bytes.begin(), length);
217
+ }
218
+
219
+ private void appendArray(RubyArray object) {
220
+ appendArrayHeader(object);
221
+ appendArrayElements(object);
222
+ }
223
+
224
+ private void appendArrayHeader(RubyArray object) {
225
+ appendArrayHeader(object.size());
226
+ }
227
+
228
+ private void appendArrayHeader(int size) {
229
+ if (size < 16) {
230
+ ensureRemainingCapacity(1);
231
+ buffer.put((byte) (size | 0x90));
232
+ } else if (size < 0x10000) {
233
+ ensureRemainingCapacity(3);
234
+ buffer.put(ARY16);
235
+ buffer.putShort((short) size);
236
+ } else {
237
+ ensureRemainingCapacity(5);
238
+ buffer.put(ARY32);
239
+ buffer.putInt(size);
240
+ }
241
+ }
242
+
243
+ private void appendArrayElements(RubyArray object) {
244
+ int size = object.size();
245
+ for (int i = 0; i < size; i++) {
246
+ appendObject(object.eltOk(i));
247
+ }
248
+ }
249
+
250
+ private void appendHash(RubyHash object) {
251
+ appendHashHeader(object);
252
+ appendHashElements(object);
253
+ }
254
+
255
+ private void appendHashHeader(RubyHash object) {
256
+ appendHashHeader(object.size());
257
+ }
258
+
259
+ private void appendHashHeader(int size) {
260
+ if (size < 16) {
261
+ ensureRemainingCapacity(1);
262
+ buffer.put((byte) (size | 0x80));
263
+ } else if (size < 0x10000) {
264
+ ensureRemainingCapacity(3);
265
+ buffer.put(MAP16);
266
+ buffer.putShort((short) size);
267
+ } else {
268
+ ensureRemainingCapacity(5);
269
+ buffer.put(MAP32);
270
+ buffer.putInt(size);
271
+ }
272
+ }
273
+
274
+ private void appendHashElements(RubyHash object) {
275
+ int size = object.size();
276
+ HashVisitor visitor = new HashVisitor(size);
277
+ object.visitAll(visitor);
278
+ if (visitor.remain != 0) {
279
+ object.getRuntime().newConcurrencyError("Hash size changed while packing");
280
+ }
281
+ }
282
+
283
+ private class HashVisitor extends RubyHash.Visitor {
284
+ public int remain;
285
+
286
+ public HashVisitor(int size) {
287
+ remain = size;
288
+ }
289
+
290
+ public void visit(IRubyObject key, IRubyObject value) {
291
+ if (remain-- > 0) {
292
+ appendObject(key);
293
+ appendObject(value);
294
+ }
295
+ }
296
+ }
297
+
298
+ private void appendCustom(IRubyObject object, IRubyObject destination) {
299
+ if (destination == null) {
300
+ IRubyObject result = object.callMethod(runtime.getCurrentContext(), "to_msgpack");
301
+ ByteList bytes = result.asString().getByteList();
302
+ int length = bytes.length();
303
+ ensureRemainingCapacity(length);
304
+ buffer.put(bytes.unsafeBytes(), bytes.begin(), length);
305
+ } else {
306
+ object.callMethod(runtime.getCurrentContext(), "to_msgpack", destination);
307
+ }
308
+ }
309
+ }
@@ -0,0 +1,136 @@
1
+ package org.msgpack.jruby;
2
+
3
+
4
+ import java.util.Arrays;
5
+ import java.nio.ByteBuffer;
6
+
7
+ import org.jruby.Ruby;
8
+ import org.jruby.RubyClass;
9
+ import org.jruby.RubyObject;
10
+ import org.jruby.RubyFixnum;
11
+ import org.jruby.RubyString;
12
+ import org.jruby.runtime.builtin.IRubyObject;
13
+ import org.jruby.runtime.ObjectAllocator;
14
+ import org.jruby.runtime.ThreadContext;
15
+ import org.jruby.anno.JRubyClass;
16
+ import org.jruby.anno.JRubyMethod;
17
+ import org.jruby.util.ByteList;
18
+
19
+ import static org.jruby.runtime.Visibility.PRIVATE;
20
+
21
+ import org.jcodings.Encoding;
22
+
23
+ import static org.msgpack.jruby.Types.*;
24
+
25
+
26
+ @JRubyClass(name="MessagePack::ExtensionValue")
27
+ public class ExtensionValue extends RubyObject {
28
+ private final Encoding binaryEncoding;
29
+
30
+ private RubyFixnum type;
31
+ private RubyString payload;
32
+
33
+ public ExtensionValue(Ruby runtime, RubyClass type) {
34
+ super(runtime, type);
35
+ this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
36
+ }
37
+
38
+ public static class ExtensionValueAllocator implements ObjectAllocator {
39
+ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
40
+ return new ExtensionValue(runtime, klass);
41
+ }
42
+ }
43
+
44
+ public static ExtensionValue newExtensionValue(Ruby runtime, int type, byte[] payload) {
45
+ ExtensionValue v = new ExtensionValue(runtime, runtime.getModule("MessagePack").getClass("ExtensionValue"));
46
+ ByteList byteList = new ByteList(payload, runtime.getEncodingService().getAscii8bitEncoding());
47
+ v.initialize(runtime.getCurrentContext(), runtime.newFixnum(type), runtime.newString(byteList));
48
+ return v;
49
+ }
50
+
51
+ @JRubyMethod(name = "initialize", required = 2, visibility = PRIVATE)
52
+ public IRubyObject initialize(ThreadContext ctx, IRubyObject type, IRubyObject payload) {
53
+ this.type = (RubyFixnum) type;
54
+ this.payload = (RubyString) payload;
55
+ return this;
56
+ }
57
+
58
+ @JRubyMethod(name = "to_msgpack")
59
+ public IRubyObject toMsgpack() {
60
+ ByteList payloadBytes = payload.getByteList();
61
+ int payloadSize = payloadBytes.length();
62
+ int outputSize = 0;
63
+ boolean fixSize = payloadSize == 1 || payloadSize == 2 || payloadSize == 4 || payloadSize == 8 || payloadSize == 16;
64
+ if (fixSize) {
65
+ outputSize = 2 + payloadSize;
66
+ } else if (payloadSize < 0x100) {
67
+ outputSize = 3 + payloadSize;
68
+ } else if (payloadSize < 0x10000) {
69
+ outputSize = 4 + payloadSize;
70
+ } else {
71
+ outputSize = 6 + payloadSize;
72
+ }
73
+ byte[] bytes = new byte[outputSize];
74
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
75
+ if (payloadSize == 1) {
76
+ buffer.put(FIXEXT1);
77
+ buffer.put((byte) type.getLongValue());
78
+ buffer.put((byte) payloadBytes.get(0));
79
+ } else if (payloadSize == 2) {
80
+ buffer.put(FIXEXT2);
81
+ buffer.put((byte) type.getLongValue());
82
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), 2);
83
+ } else if (payloadSize == 4) {
84
+ buffer.put(FIXEXT4);
85
+ buffer.put((byte) type.getLongValue());
86
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), 4);
87
+ } else if (payloadSize == 8) {
88
+ buffer.put(FIXEXT8);
89
+ buffer.put((byte) type.getLongValue());
90
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), 8);
91
+ } else if (payloadSize == 16) {
92
+ buffer.put(FIXEXT16);
93
+ buffer.put((byte) type.getLongValue());
94
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), 16);
95
+ } else if (payloadSize < 0x100) {
96
+ buffer.put(VAREXT8);
97
+ buffer.put((byte) payloadSize);
98
+ buffer.put((byte) type.getLongValue());
99
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), payloadSize);
100
+ } else if (payloadSize < 0x10000) {
101
+ buffer.put(VAREXT16);
102
+ buffer.putShort((short) payloadSize);
103
+ buffer.put((byte) type.getLongValue());
104
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), payloadSize);
105
+ } else {
106
+ buffer.put(VAREXT32);
107
+ buffer.putInt(payloadSize);
108
+ buffer.put((byte) type.getLongValue());
109
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), payloadSize);
110
+ }
111
+ return getRuntime().newString(new ByteList(bytes, binaryEncoding, false));
112
+ }
113
+
114
+ @JRubyMethod(name = {"to_s", "inspect"})
115
+ @Override
116
+ public IRubyObject to_s() {
117
+ IRubyObject payloadStr = payload.callMethod(getRuntime().getCurrentContext(), "inspect");
118
+ return getRuntime().newString(String.format("#<MessagePack::ExtensionValue @type=%d, @payload=%s>", type.getLongValue(), payloadStr));
119
+ }
120
+
121
+ @JRubyMethod(name = "hash")
122
+ @Override
123
+ public RubyFixnum hash() {
124
+ long hash = payload.hashCode() & (type.getLongValue() << 56);
125
+ return RubyFixnum.newFixnum(getRuntime(), hash);
126
+ }
127
+
128
+ @JRubyMethod(name = "eql?")
129
+ public IRubyObject eql_p(ThreadContext ctx, IRubyObject o) {
130
+ if (o instanceof ExtensionValue) {
131
+ ExtensionValue other = (ExtensionValue) o;
132
+ return getRuntime().newBoolean(this.type.callMethod(ctx, "eql?", other.type).isTrue() && this.payload.callMethod(ctx, "eql?", other.payload).isTrue());
133
+ }
134
+ return getRuntime().getFalse();
135
+ }
136
+ }
@@ -0,0 +1,113 @@
1
+ package org.msgpack.jruby;
2
+
3
+
4
+ import org.jruby.Ruby;
5
+ import org.jruby.RubyModule;
6
+ import org.jruby.RubyClass;
7
+ import org.jruby.RubyString;
8
+ import org.jruby.RubyNil;
9
+ import org.jruby.RubyBoolean;
10
+ import org.jruby.RubyHash;
11
+ import org.jruby.runtime.load.Library;
12
+ import org.jruby.runtime.builtin.IRubyObject;
13
+ import org.jruby.runtime.ThreadContext;
14
+ import org.jruby.runtime.Block;
15
+ import org.jruby.runtime.Visibility;
16
+ import org.jruby.anno.JRubyModule;
17
+ import org.jruby.anno.JRubyMethod;
18
+ import org.jruby.internal.runtime.methods.CallConfiguration;
19
+ import org.jruby.internal.runtime.methods.DynamicMethod;
20
+
21
+
22
+ public class MessagePackLibrary implements Library {
23
+ public void load(Ruby runtime, boolean wrap) {
24
+ RubyModule msgpackModule = runtime.defineModule("MessagePack");
25
+ msgpackModule.defineAnnotatedMethods(MessagePackModule.class);
26
+ RubyClass standardErrorClass = runtime.getStandardError();
27
+ RubyClass unpackErrorClass = msgpackModule.defineClassUnder("UnpackError", standardErrorClass, standardErrorClass.getAllocator());
28
+ RubyClass underflowErrorClass = msgpackModule.defineClassUnder("UnderflowError", unpackErrorClass, unpackErrorClass.getAllocator());
29
+ RubyClass extensionValueClass = msgpackModule.defineClassUnder("ExtensionValue", runtime.getObject(), new ExtensionValue.ExtensionValueAllocator());
30
+ extensionValueClass.defineAnnotatedMethods(ExtensionValue.class);
31
+ RubyClass packerClass = msgpackModule.defineClassUnder("Packer", runtime.getObject(), new Packer.PackerAllocator());
32
+ packerClass.defineAnnotatedMethods(Packer.class);
33
+ RubyClass unpackerClass = msgpackModule.defineClassUnder("Unpacker", runtime.getObject(), new Unpacker.UnpackerAllocator());
34
+ unpackerClass.defineAnnotatedMethods(Unpacker.class);
35
+ RubyClass bufferClass = msgpackModule.defineClassUnder("Buffer", runtime.getObject(), new Buffer.BufferAllocator());
36
+ bufferClass.defineAnnotatedMethods(Buffer.class);
37
+ installCoreExtensions(runtime);
38
+ }
39
+
40
+ private void installCoreExtensions(Ruby runtime) {
41
+ installCoreExtensions(
42
+ runtime,
43
+ runtime.getNilClass(),
44
+ runtime.getTrueClass(),
45
+ runtime.getFalseClass(),
46
+ runtime.getFixnum(),
47
+ runtime.getBignum(),
48
+ runtime.getFloat(),
49
+ runtime.getString(),
50
+ runtime.getArray(),
51
+ runtime.getHash(),
52
+ runtime.getSymbol()
53
+ );
54
+ }
55
+
56
+ private void installCoreExtensions(Ruby runtime, RubyClass... classes) {
57
+ for (RubyClass cls : classes) {
58
+ cls.addMethod("to_msgpack", createToMsgpackMethod(runtime, cls));
59
+ }
60
+ }
61
+
62
+ private DynamicMethod createToMsgpackMethod(final Ruby runtime, RubyClass cls) {
63
+ return new DynamicMethod(cls, Visibility.PUBLIC, CallConfiguration.FrameNoneScopeNone) {
64
+ @Override
65
+ public IRubyObject call(ThreadContext context, IRubyObject recv, RubyModule clazz, String name, IRubyObject[] args, Block block) {
66
+ IRubyObject[] allArgs = new IRubyObject[1 + args.length];
67
+ allArgs[0] = recv;
68
+ System.arraycopy(args, 0, allArgs, 1, args.length);
69
+ return MessagePackModule.pack(runtime.getCurrentContext(), null, allArgs);
70
+ }
71
+
72
+ @Override
73
+ public DynamicMethod dup() {
74
+ return this;
75
+ }
76
+ };
77
+ }
78
+
79
+ @JRubyModule(name = "MessagePack")
80
+ public static class MessagePackModule {
81
+ @JRubyMethod(module = true, required = 1, optional = 1, alias = {"dump"})
82
+ public static IRubyObject pack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) {
83
+ IRubyObject[] extraArgs = null;
84
+ if (args.length == 0) {
85
+ extraArgs = new IRubyObject[] {};
86
+ } else {
87
+ extraArgs = new IRubyObject[args.length - 1];
88
+ System.arraycopy(args, 1, extraArgs, 0, args.length - 1);
89
+ }
90
+ Packer packer = new Packer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Packer"));
91
+ packer.initialize(ctx, extraArgs);
92
+ packer.write(ctx, args[0]);
93
+ return packer.toS(ctx);
94
+ }
95
+
96
+ @JRubyMethod(module = true, required = 1, optional = 1, alias = {"load"})
97
+ public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) {
98
+ Decoder decoder = new Decoder(ctx.getRuntime(), args[0].asString().getBytes());
99
+ if (args.length > 1) {
100
+ if (args[args.length - 1] instanceof RubyHash) {
101
+ Ruby runtime = ctx.getRuntime();
102
+ IRubyObject symbolizeKeys = ((RubyHash) args[args.length - 1]).fastARef((IRubyObject) runtime.getSymbolTable().getSymbol("symbolize_keys"));
103
+ if (symbolizeKeys instanceof RubyNil || symbolizeKeys instanceof RubyBoolean.False) {
104
+ decoder.symbolizeKeys(false);
105
+ } else {
106
+ decoder.symbolizeKeys(true);
107
+ }
108
+ }
109
+ }
110
+ return decoder.next();
111
+ }
112
+ }
113
+ }