msgpack 0.6.0pre1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +26 -0
  4. data/ChangeLog +117 -0
  5. data/Dockerfile +30 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +177 -0
  8. data/README.rdoc +129 -0
  9. data/Rakefile +114 -0
  10. data/bench/pack.rb +23 -0
  11. data/bench/pack_log.rb +33 -0
  12. data/bench/pack_log_long.rb +65 -0
  13. data/bench/run.sh +14 -0
  14. data/bench/run_long.sh +35 -0
  15. data/bench/unpack.rb +21 -0
  16. data/bench/unpack_log.rb +34 -0
  17. data/bench/unpack_log_long.rb +67 -0
  18. data/cross-build.sh +9 -0
  19. data/doclib/msgpack/buffer.rb +193 -0
  20. data/doclib/msgpack/core_ext.rb +101 -0
  21. data/doclib/msgpack/error.rb +14 -0
  22. data/doclib/msgpack/packer.rb +134 -0
  23. data/doclib/msgpack/unpacker.rb +146 -0
  24. data/doclib/msgpack.rb +77 -0
  25. data/ext/java/org/msgpack/jruby/Buffer.java +221 -0
  26. data/ext/java/org/msgpack/jruby/Decoder.java +201 -0
  27. data/ext/java/org/msgpack/jruby/Encoder.java +308 -0
  28. data/ext/java/org/msgpack/jruby/ExtensionValue.java +136 -0
  29. data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +107 -0
  30. data/ext/java/org/msgpack/jruby/Packer.java +78 -0
  31. data/ext/java/org/msgpack/jruby/Types.java +37 -0
  32. data/ext/java/org/msgpack/jruby/Unpacker.java +170 -0
  33. data/ext/msgpack/buffer.c +695 -0
  34. data/ext/msgpack/buffer.h +447 -0
  35. data/ext/msgpack/buffer_class.c +507 -0
  36. data/ext/msgpack/buffer_class.h +32 -0
  37. data/ext/msgpack/compat.h +113 -0
  38. data/ext/msgpack/core_ext.c +129 -0
  39. data/ext/msgpack/core_ext.h +26 -0
  40. data/ext/msgpack/extconf.rb +28 -0
  41. data/ext/msgpack/packer.c +168 -0
  42. data/ext/msgpack/packer.h +441 -0
  43. data/ext/msgpack/packer_class.c +302 -0
  44. data/ext/msgpack/packer_class.h +30 -0
  45. data/ext/msgpack/rbinit.c +33 -0
  46. data/ext/msgpack/rmem.c +94 -0
  47. data/ext/msgpack/rmem.h +109 -0
  48. data/ext/msgpack/sysdep.h +115 -0
  49. data/ext/msgpack/sysdep_endian.h +50 -0
  50. data/ext/msgpack/sysdep_types.h +46 -0
  51. data/ext/msgpack/unpacker.c +771 -0
  52. data/ext/msgpack/unpacker.h +122 -0
  53. data/ext/msgpack/unpacker_class.c +405 -0
  54. data/ext/msgpack/unpacker_class.h +32 -0
  55. data/lib/msgpack/msgpack.so +0 -0
  56. data/lib/msgpack/version.rb +3 -0
  57. data/lib/msgpack.rb +13 -0
  58. data/msgpack.gemspec +31 -0
  59. data/msgpack.org.md +46 -0
  60. data/spec/cases.json +1 -0
  61. data/spec/cases.msg +0 -0
  62. data/spec/cases_compact.msg +0 -0
  63. data/spec/cases_spec.rb +39 -0
  64. data/spec/cruby/buffer_io_spec.rb +256 -0
  65. data/spec/cruby/buffer_packer.rb +29 -0
  66. data/spec/cruby/buffer_spec.rb +572 -0
  67. data/spec/cruby/buffer_unpacker.rb +19 -0
  68. data/spec/cruby/packer_spec.rb +120 -0
  69. data/spec/cruby/unpacker_spec.rb +305 -0
  70. data/spec/format_spec.rb +282 -0
  71. data/spec/jruby/benchmarks/shootout_bm.rb +73 -0
  72. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +25 -0
  73. data/spec/jruby/msgpack/unpacker_spec.rb +290 -0
  74. data/spec/jruby/msgpack_spec.rb +142 -0
  75. data/spec/pack_spec.rb +67 -0
  76. data/spec/random_compat.rb +24 -0
  77. data/spec/spec_helper.rb +27 -0
  78. data/spec/unpack_spec.rb +60 -0
  79. metadata +209 -0
@@ -0,0 +1,146 @@
1
+ module MessagePack
2
+
3
+ #
4
+ # MessagePack::Unpacker is a class to deserialize objects.
5
+ #
6
+ class Unpacker
7
+ #
8
+ # Creates a MessagePack::Unpacker instance.
9
+ #
10
+ # @overload initialize(options={})
11
+ # @param options [Hash]
12
+ #
13
+ # @overload initialize(io, options={})
14
+ # @param io [IO]
15
+ # @param options [Hash]
16
+ # This unpacker reads data from the _io_ to fill the internal buffer.
17
+ # _io_ must respond to readpartial(length [,string]) or read(length [,string]) method.
18
+ #
19
+ # Supported options:
20
+ #
21
+ # * *:symbolize_keys* deserialize keys of Hash objects as Symbol instead of String
22
+ #
23
+ # See also Buffer#initialize for other options.
24
+ #
25
+ def initialize(*args)
26
+ end
27
+
28
+ #
29
+ # Internal buffer
30
+ #
31
+ # @return [MessagePack::Buffer]
32
+ #
33
+ attr_reader :buffer
34
+
35
+ #
36
+ # Deserializes an object from the io or internal buffer and returns it.
37
+ #
38
+ # This method reads data from io into the internal buffer and deserializes an object
39
+ # from the buffer. It repeats reading data from the io until enough data is available
40
+ # to deserialize at least one object. After deserializing one object, unused data is
41
+ # left in the internal buffer.
42
+ #
43
+ # If there're not enough data to deserialize one object, this method raises EOFError.
44
+ # If data format is invalid, this method raises MessagePack::MalformedFormatError.
45
+ # If the object nests too deeply, this method raises MessagePack::StackError.
46
+ #
47
+ # @return [Object] deserialized object
48
+ #
49
+ def read
50
+ end
51
+
52
+ alias unpack read
53
+
54
+ #
55
+ # Deserializes an object and ignores it. This method is faster than _read_.
56
+ #
57
+ # This method could raise the same errors with _read_.
58
+ #
59
+ # @return nil
60
+ #
61
+ def skip
62
+ end
63
+
64
+ #
65
+ # Deserializes a nil value if it exists and returns _true_.
66
+ # Otherwise, if a byte exists but the byte doesn't represent nil value,
67
+ # returns _false_.
68
+ #
69
+ # If there're not enough data, this method raises EOFError.
70
+ #
71
+ # @return [Boolean]
72
+ #
73
+ def skip_nil
74
+ end
75
+
76
+ #
77
+ # Read a header of an array and returns its size.
78
+ # It converts a serialized array into a stream of elements.
79
+ #
80
+ # If the serialized object is not an array, it raises MessagePack::TypeError.
81
+ # If there're not enough data, this method raises EOFError.
82
+ #
83
+ # @return [Integer] size of the array
84
+ #
85
+ def read_array_header
86
+ end
87
+
88
+ #
89
+ # Reads a header of an map and returns its size.
90
+ # It converts a serialized map into a stream of key-value pairs.
91
+ #
92
+ # If the serialized object is not a map, it raises MessagePack::TypeError.
93
+ # If there're not enough data, this method raises EOFError.
94
+ #
95
+ # @return [Integer] size of the map
96
+ #
97
+ def read_map_header
98
+ end
99
+
100
+ #
101
+ # Appends data into the internal buffer.
102
+ # This method is equivalent to unpacker.buffer.append(data).
103
+ #
104
+ # @param data [String]
105
+ # @return [Unpacker] self
106
+ #
107
+ def feed(data)
108
+ end
109
+
110
+ #
111
+ # Repeats to deserialize objects.
112
+ #
113
+ # It repeats until the io or internal buffer does not include any complete objects.
114
+ #
115
+ # If the an IO is set, it repeats to read data from the IO when the buffer
116
+ # becomes empty until the IO raises EOFError.
117
+ #
118
+ # This method could raise same errors with _read_ excepting EOFError.
119
+ #
120
+ # @yieldparam object [Object] deserialized object
121
+ # @return nil
122
+ #
123
+ def each(&block)
124
+ end
125
+
126
+ #
127
+ # Appends data into the internal buffer and repeats to deserialize objects.
128
+ # This method is equivalent to unpacker.feed(data) && unpacker.each { ... }.
129
+ #
130
+ # @param data [String]
131
+ # @yieldparam object [Object] deserialized object
132
+ # @return nil
133
+ #
134
+ def feed_each(data, &block)
135
+ end
136
+
137
+ #
138
+ # Clears the internal buffer and resets deserialization state of the unpacker.
139
+ #
140
+ # @return nil
141
+ #
142
+ def reset
143
+ end
144
+ end
145
+
146
+ end
data/doclib/msgpack.rb ADDED
@@ -0,0 +1,77 @@
1
+
2
+ module MessagePack
3
+ #
4
+ # Serializes an object into an IO or String.
5
+ #
6
+ # @overload dump(obj, options={})
7
+ # @param obj [Object] object to be serialized
8
+ # @param options [Hash]
9
+ # @return [String] serialized data
10
+ #
11
+ # @overload dump(obj, io, options={})
12
+ # @param obj [Object] object to be serialized
13
+ # @param io [IO]
14
+ # @param options [Hash]
15
+ # @return [IO]
16
+ #
17
+ # See Packer#initialize for supported options.
18
+ #
19
+ def self.dump(obj)
20
+ end
21
+
22
+ #
23
+ # Serializes an object into an IO or String. Alias of dump.
24
+ #
25
+ # @overload pack(obj, options={})
26
+ # @param obj [Object] object to be serialized
27
+ # @param options [Hash]
28
+ # @return [String] serialized data
29
+ #
30
+ # @overload pack(obj, io, options={})
31
+ # @param obj [Object] object to be serialized
32
+ # @param io [IO]
33
+ # @param options [Hash]
34
+ # @return [IO]
35
+ #
36
+ # See Packer#initialize for supported options.
37
+ #
38
+ def self.pack(obj)
39
+ end
40
+
41
+ #
42
+ # Deserializes an object from an IO or String.
43
+ #
44
+ # @overload load(string, options={})
45
+ # @param string [String] data to deserialize
46
+ # @param options [Hash]
47
+ #
48
+ # @overload load(io, options={})
49
+ # @param io [IO]
50
+ # @param options [Hash]
51
+ #
52
+ # @return [Object] deserialized object
53
+ #
54
+ # See Unpacker#initialize for supported options.
55
+ #
56
+ def self.load(src, options={})
57
+ end
58
+
59
+ #
60
+ # Deserializes an object from an IO or String. Alias of load.
61
+ #
62
+ # @overload unpack(string, options={})
63
+ # @param string [String] data to deserialize
64
+ # @param options [Hash]
65
+ #
66
+ # @overload unpack(io, options={})
67
+ # @param io [IO]
68
+ # @param options [Hash]
69
+ #
70
+ # @return [Object] deserialized object
71
+ #
72
+ # See Unpacker#initialize for supported options.
73
+ #
74
+ def self.unpack(src, options={})
75
+ end
76
+ end
77
+
@@ -0,0 +1,221 @@
1
+ package org.msgpack.jruby;
2
+
3
+
4
+ import java.nio.ByteBuffer;
5
+
6
+ import org.jruby.Ruby;
7
+ import org.jruby.RubyClass;
8
+ import org.jruby.RubyObject;
9
+ import org.jruby.RubyHash;
10
+ import org.jruby.RubyIO;
11
+ import org.jruby.RubyInteger;
12
+ import org.jruby.runtime.builtin.IRubyObject;
13
+ import org.jruby.anno.JRubyClass;
14
+ import org.jruby.anno.JRubyMethod;
15
+ import org.jruby.runtime.ThreadContext;
16
+ import org.jruby.runtime.ObjectAllocator;
17
+ import org.jruby.util.ByteList;
18
+
19
+ import org.jcodings.Encoding;
20
+
21
+
22
+ @JRubyClass(name="MessagePack::Buffer")
23
+ public class Buffer extends RubyObject {
24
+ private RubyHash options;
25
+ private IRubyObject io;
26
+ private ByteBuffer buffer;
27
+ private boolean writeMode;
28
+ private Encoding binaryEncoding;
29
+
30
+ private static final int CACHE_LINE_SIZE = 64;
31
+ private static final int ARRAY_HEADER_SIZE = 24;
32
+
33
+ public Buffer(Ruby runtime, RubyClass type) {
34
+ super(runtime, type);
35
+ }
36
+
37
+ static class BufferAllocator implements ObjectAllocator {
38
+ public IRubyObject allocate(Ruby runtime, RubyClass type) {
39
+ return new Buffer(runtime, type);
40
+ }
41
+ }
42
+
43
+ @JRubyMethod(name = "initialize", optional = 2)
44
+ public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
45
+ if (args.length > 0) {
46
+ if (args[0].respondsTo("read") && args[0].respondsTo("write")) {
47
+ this.io = args[0];
48
+ }
49
+ if (args[args.length - 1] instanceof RubyHash) {
50
+ this.options = (RubyHash) args[args.length - 1];
51
+ }
52
+ }
53
+ this.buffer = ByteBuffer.allocate(CACHE_LINE_SIZE - ARRAY_HEADER_SIZE);
54
+ this.writeMode = true;
55
+ this.binaryEncoding = ctx.getRuntime().getEncodingService().getAscii8bitEncoding();
56
+ return this;
57
+ }
58
+
59
+ private void ensureRemainingCapacity(int c) {
60
+ if (!writeMode) {
61
+ buffer.compact();
62
+ writeMode = true;
63
+ }
64
+ if (buffer.remaining() < c) {
65
+ int newLength = Math.max(buffer.capacity() + (buffer.capacity() >> 1), buffer.capacity() + c);
66
+ newLength += CACHE_LINE_SIZE - ((ARRAY_HEADER_SIZE + newLength) % CACHE_LINE_SIZE);
67
+ buffer = ByteBuffer.allocate(newLength).put(buffer.array(), 0, buffer.position());
68
+ }
69
+ }
70
+
71
+ private void ensureReadMode() {
72
+ if (writeMode) {
73
+ buffer.flip();
74
+ writeMode = false;
75
+ }
76
+ }
77
+
78
+ private int rawSize() {
79
+ if (writeMode) {
80
+ return buffer.position();
81
+ } else {
82
+ return buffer.limit() - buffer.position();
83
+ }
84
+ }
85
+
86
+ @JRubyMethod(name = "clear")
87
+ public IRubyObject clear(ThreadContext ctx) {
88
+ buffer.clear();
89
+ return ctx.getRuntime().getNil();
90
+ }
91
+
92
+ @JRubyMethod(name = "size")
93
+ public IRubyObject size(ThreadContext ctx) {
94
+ return ctx.getRuntime().newFixnum(rawSize());
95
+ }
96
+
97
+ @JRubyMethod(name = "empty?")
98
+ public IRubyObject isEmpty(ThreadContext ctx) {
99
+ return rawSize() == 0 ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
100
+ }
101
+
102
+ private IRubyObject bufferWrite(ThreadContext ctx, IRubyObject str) {
103
+ ByteList bytes = str.asString().getByteList();
104
+ int length = bytes.length();
105
+ ensureRemainingCapacity(length);
106
+ buffer.put(bytes.unsafeBytes(), bytes.begin(), length);
107
+ return ctx.getRuntime().newFixnum(length);
108
+
109
+ }
110
+
111
+ @JRubyMethod(name = "write", alias = {"<<"})
112
+ public IRubyObject write(ThreadContext ctx, IRubyObject str) {
113
+ if (io == null) {
114
+ return bufferWrite(ctx, str);
115
+ } else {
116
+ return io.callMethod(ctx, "write", str);
117
+ }
118
+ }
119
+
120
+ private void feed(ThreadContext ctx) {
121
+ if (io != null) {
122
+ bufferWrite(ctx, io.callMethod(ctx, "read"));
123
+ }
124
+ }
125
+
126
+ private IRubyObject readCommon(ThreadContext ctx, IRubyObject[] args, boolean raiseOnUnderflow) {
127
+ feed(ctx);
128
+ int length = rawSize();
129
+ if (args != null && args.length == 1) {
130
+ length = (int) args[0].convertToInteger().getLongValue();
131
+ }
132
+ if (raiseOnUnderflow && rawSize() < length) {
133
+ throw ctx.getRuntime().newEOFError();
134
+ }
135
+ int readLength = Math.min(length, rawSize());
136
+ if (readLength == 0 && length > 0) {
137
+ return ctx.getRuntime().getNil();
138
+ } else if (readLength == 0) {
139
+ return ctx.getRuntime().newString();
140
+ } else {
141
+ ensureReadMode();
142
+ byte[] bytes = new byte[readLength];
143
+ buffer.get(bytes);
144
+ ByteList byteList = new ByteList(bytes, binaryEncoding);
145
+ return ctx.getRuntime().newString(byteList);
146
+ }
147
+ }
148
+
149
+ @JRubyMethod(name = "read", optional = 1)
150
+ public IRubyObject read(ThreadContext ctx, IRubyObject[] args) {
151
+ return readCommon(ctx, args, false);
152
+ }
153
+
154
+ @JRubyMethod(name = "read_all", optional = 1)
155
+ public IRubyObject readAll(ThreadContext ctx, IRubyObject[] args) {
156
+ return readCommon(ctx, args, true);
157
+ }
158
+
159
+ private IRubyObject skipCommon(ThreadContext ctx, IRubyObject _length, boolean raiseOnUnderflow) {
160
+ feed(ctx);
161
+ int length = (int) _length.convertToInteger().getLongValue();
162
+ if (raiseOnUnderflow && rawSize() < length) {
163
+ throw ctx.getRuntime().newEOFError();
164
+ }
165
+ ensureReadMode();
166
+ int skipLength = Math.min(length, rawSize());
167
+ buffer.position(buffer.position() + skipLength);
168
+ return ctx.getRuntime().newFixnum(skipLength);
169
+ }
170
+
171
+ @JRubyMethod(name = "skip")
172
+ public IRubyObject skip(ThreadContext ctx, IRubyObject length) {
173
+ return skipCommon(ctx, length, false);
174
+ }
175
+
176
+ @JRubyMethod(name = "skip_all")
177
+ public IRubyObject skipAll(ThreadContext ctx, IRubyObject length) {
178
+ return skipCommon(ctx, length, true);
179
+ }
180
+
181
+ @JRubyMethod(name = "to_s", alias = {"to_str"})
182
+ public IRubyObject toS(ThreadContext ctx) {
183
+ ensureReadMode();
184
+ int length = buffer.limit() - buffer.position();
185
+ ByteList str = new ByteList(buffer.array(), buffer.position(), length, binaryEncoding, true);
186
+ return ctx.getRuntime().newString(str);
187
+ }
188
+
189
+ @JRubyMethod(name = "to_a")
190
+ public IRubyObject toA(ThreadContext ctx) {
191
+ return ctx.getRuntime().newArray(toS(ctx));
192
+ }
193
+
194
+ @JRubyMethod(name = "io")
195
+ public IRubyObject getIo(ThreadContext ctx) {
196
+ return io == null ? ctx.getRuntime().getNil() : io;
197
+ }
198
+
199
+ @JRubyMethod(name = "flush")
200
+ public IRubyObject flush(ThreadContext ctx) {
201
+ if (io == null) {
202
+ return ctx.getRuntime().getNil();
203
+ } else {
204
+ return io.callMethod(ctx, "flush");
205
+ }
206
+ }
207
+
208
+ @JRubyMethod(name = "close")
209
+ public IRubyObject close(ThreadContext ctx) {
210
+ if (io == null) {
211
+ return ctx.getRuntime().getNil();
212
+ } else {
213
+ return io.callMethod(ctx, "close");
214
+ }
215
+ }
216
+
217
+ @JRubyMethod(name = "write_to")
218
+ public IRubyObject writeTo(ThreadContext ctx, IRubyObject io) {
219
+ return io.callMethod(ctx, "write", readCommon(ctx, null, false));
220
+ }
221
+ }
@@ -0,0 +1,201 @@
1
+ package org.msgpack.jruby;
2
+
3
+
4
+ import java.math.BigInteger;
5
+ import java.nio.ByteBuffer;
6
+ import java.nio.BufferUnderflowException;
7
+ import java.util.Iterator;
8
+ import java.util.Arrays;
9
+
10
+ import org.jruby.Ruby;
11
+ import org.jruby.RubyObject;
12
+ import org.jruby.RubyClass;
13
+ import org.jruby.RubyBignum;
14
+ import org.jruby.RubyString;
15
+ import org.jruby.RubyHash;
16
+ import org.jruby.exceptions.RaiseException;
17
+ import org.jruby.runtime.builtin.IRubyObject;
18
+ import org.jruby.util.ByteList;
19
+
20
+ import org.jcodings.Encoding;
21
+ import org.jcodings.specific.UTF8Encoding;
22
+
23
+ import static org.msgpack.jruby.Types.*;
24
+
25
+
26
+ public class Decoder implements Iterator<IRubyObject> {
27
+ private final Ruby runtime;
28
+ private final Encoding binaryEncoding;
29
+ private final Encoding utf8Encoding;
30
+ private final RubyClass unpackErrorClass;
31
+ private final RubyClass underflowErrorClass;
32
+
33
+ private ByteBuffer buffer;
34
+ private boolean symbolizeKeys;
35
+
36
+ public Decoder(Ruby runtime) {
37
+ this(runtime, new byte[] {}, 0, 0);
38
+ }
39
+
40
+ public Decoder(Ruby runtime, byte[] bytes) {
41
+ this(runtime, bytes, 0, bytes.length);
42
+ }
43
+
44
+ public Decoder(Ruby runtime, byte[] bytes, int offset, int length) {
45
+ this.runtime = runtime;
46
+ this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
47
+ this.utf8Encoding = UTF8Encoding.INSTANCE;
48
+ this.unpackErrorClass = runtime.getModule("MessagePack").getClass("UnpackError");
49
+ this.underflowErrorClass = runtime.getModule("MessagePack").getClass("UnderflowError");
50
+ feed(bytes, offset, length);
51
+ }
52
+
53
+ public void symbolizeKeys(boolean symbolize) {
54
+ this.symbolizeKeys = symbolize;
55
+ }
56
+
57
+ public void feed(byte[] bytes) {
58
+ feed(bytes, 0, bytes.length);
59
+ }
60
+
61
+ public void feed(byte[] bytes, int offset, int length) {
62
+ if (buffer == null) {
63
+ buffer = ByteBuffer.wrap(bytes, offset, length);
64
+ } else {
65
+ ByteBuffer newBuffer = ByteBuffer.allocate(buffer.remaining() + length);
66
+ newBuffer.put(buffer);
67
+ newBuffer.put(bytes, offset, length);
68
+ newBuffer.flip();
69
+ buffer = newBuffer;
70
+ }
71
+ }
72
+
73
+ public void reset() {
74
+ buffer.rewind();
75
+ }
76
+
77
+ public int offset() {
78
+ return buffer.position();
79
+ }
80
+
81
+ private IRubyObject consumeUnsignedLong() {
82
+ long value = buffer.getLong();
83
+ if (value < 0) {
84
+ return RubyBignum.newBignum(runtime, BigInteger.valueOf(value & ((1L<<63)-1)).setBit(63));
85
+ } else {
86
+ return runtime.newFixnum(value);
87
+ }
88
+ }
89
+
90
+ private IRubyObject consumeString(int size, Encoding encoding) {
91
+ byte[] bytes = readBytes(size);
92
+ ByteList byteList = new ByteList(bytes, encoding);
93
+ return runtime.newString(byteList);
94
+ }
95
+
96
+ private IRubyObject consumeArray(int size) {
97
+ IRubyObject[] elements = new IRubyObject[size];
98
+ for (int i = 0; i < size; i++) {
99
+ elements[i] = next();
100
+ }
101
+ return runtime.newArray(elements);
102
+ }
103
+
104
+ private IRubyObject consumeHash(int size) {
105
+ RubyHash hash = RubyHash.newHash(runtime);
106
+ for (int i = 0; i < size; i++) {
107
+ IRubyObject key = next();
108
+ if (this.symbolizeKeys && key instanceof RubyString) {
109
+ key = ((RubyString) key).intern();
110
+ }
111
+ hash.fastASet(key, next());
112
+ }
113
+ return hash;
114
+ }
115
+
116
+ private IRubyObject consumeExtension(int size) {
117
+ int type = buffer.get();
118
+ byte[] payload = readBytes(size);
119
+ return ExtensionValue.newExtensionValue(runtime, type, payload);
120
+ }
121
+
122
+ private byte[] readBytes(int size) {
123
+ byte[] payload = new byte[size];
124
+ buffer.get(payload);
125
+ return payload;
126
+ }
127
+
128
+ @Override
129
+ public void remove() {
130
+ throw new UnsupportedOperationException();
131
+ }
132
+
133
+ @Override
134
+ public boolean hasNext() {
135
+ return buffer.remaining() > 0;
136
+ }
137
+
138
+ @Override
139
+ public IRubyObject next() {
140
+ int position = buffer.position();
141
+ try {
142
+ byte b = buffer.get();
143
+ outer: switch ((b >> 4) & 0xf) {
144
+ case 0x8: return consumeHash(b & 0x0f);
145
+ case 0x9: return consumeArray(b & 0x0f);
146
+ case 0xa:
147
+ case 0xb: return consumeString(b & 0x1f, utf8Encoding);
148
+ case 0xc:
149
+ switch (b) {
150
+ case NIL: return runtime.getNil();
151
+ case FALSE: return runtime.getFalse();
152
+ case TRUE: return runtime.getTrue();
153
+ case BIN8: return consumeString(buffer.get() & 0xff, binaryEncoding);
154
+ case BIN16: return consumeString(buffer.getShort() & 0xffff, binaryEncoding);
155
+ case BIN32: return consumeString(buffer.getInt(), binaryEncoding);
156
+ case VAREXT8: return consumeExtension(buffer.get());
157
+ case VAREXT16: return consumeExtension(buffer.getShort());
158
+ case VAREXT32: return consumeExtension(buffer.getInt());
159
+ case FLOAT32: return runtime.newFloat(buffer.getFloat());
160
+ case FLOAT64: return runtime.newFloat(buffer.getDouble());
161
+ case UINT8: return runtime.newFixnum(buffer.get() & 0xffL);
162
+ case UINT16: return runtime.newFixnum(buffer.getShort() & 0xffffL);
163
+ case UINT32: return runtime.newFixnum(buffer.getInt() & 0xffffffffL);
164
+ case UINT64: return consumeUnsignedLong();
165
+ default: break outer;
166
+ }
167
+ case 0xd:
168
+ switch (b) {
169
+ case INT8: return runtime.newFixnum(buffer.get());
170
+ case INT16: return runtime.newFixnum(buffer.getShort());
171
+ case INT32: return runtime.newFixnum(buffer.getInt());
172
+ case INT64: return runtime.newFixnum(buffer.getLong());
173
+ case FIXEXT1: return consumeExtension(1);
174
+ case FIXEXT2: return consumeExtension(2);
175
+ case FIXEXT4: return consumeExtension(4);
176
+ case FIXEXT8: return consumeExtension(8);
177
+ case FIXEXT16: return consumeExtension(16);
178
+ case STR8: return consumeString(buffer.get() & 0xff, utf8Encoding);
179
+ case STR16: return consumeString(buffer.getShort() & 0xffff, utf8Encoding);
180
+ case STR32: return consumeString(buffer.getInt(), utf8Encoding);
181
+ case ARY16: return consumeArray(buffer.getShort() & 0xffff);
182
+ case ARY32: return consumeArray(buffer.getInt());
183
+ case MAP16: return consumeHash(buffer.getShort() & 0xffff);
184
+ case MAP32: return consumeHash(buffer.getInt());
185
+ default: break outer;
186
+ }
187
+ case 0xe:
188
+ case 0xf: return runtime.newFixnum((0x1f & b) - 0x20);
189
+ default: return runtime.newFixnum(b);
190
+ }
191
+ buffer.position(position);
192
+ throw runtime.newRaiseException(unpackErrorClass, "Illegal byte sequence");
193
+ } catch (RaiseException re) {
194
+ buffer.position(position);
195
+ throw re;
196
+ } catch (BufferUnderflowException bue) {
197
+ buffer.position(position);
198
+ throw runtime.newRaiseException(underflowErrorClass, "Not enough bytes available");
199
+ }
200
+ }
201
+ }