msgpack 0.6.0-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +26 -0
- data/ChangeLog +129 -0
- data/Dockerfile +62 -0
- data/LICENSE +177 -0
- data/README.rdoc +141 -0
- data/Rakefile +68 -0
- data/bench/pack.rb +23 -0
- data/bench/pack_log.rb +33 -0
- data/bench/pack_log_long.rb +65 -0
- data/bench/run.sh +14 -0
- data/bench/run_long.sh +35 -0
- data/bench/unpack.rb +21 -0
- data/bench/unpack_log.rb +34 -0
- data/bench/unpack_log_long.rb +67 -0
- data/doclib/msgpack.rb +77 -0
- data/doclib/msgpack/buffer.rb +193 -0
- data/doclib/msgpack/core_ext.rb +101 -0
- data/doclib/msgpack/error.rb +14 -0
- data/doclib/msgpack/packer.rb +134 -0
- data/doclib/msgpack/unpacker.rb +146 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +221 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +201 -0
- data/ext/java/org/msgpack/jruby/Encoder.java +308 -0
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +136 -0
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +107 -0
- data/ext/java/org/msgpack/jruby/Packer.java +78 -0
- data/ext/java/org/msgpack/jruby/Types.java +37 -0
- data/ext/java/org/msgpack/jruby/Unpacker.java +170 -0
- data/ext/msgpack/buffer.c +695 -0
- data/ext/msgpack/buffer.h +447 -0
- data/ext/msgpack/buffer_class.c +507 -0
- data/ext/msgpack/buffer_class.h +32 -0
- data/ext/msgpack/compat.h +114 -0
- data/ext/msgpack/core_ext.c +129 -0
- data/ext/msgpack/core_ext.h +26 -0
- data/ext/msgpack/extconf.rb +30 -0
- data/ext/msgpack/packer.c +168 -0
- data/ext/msgpack/packer.h +441 -0
- data/ext/msgpack/packer_class.c +302 -0
- data/ext/msgpack/packer_class.h +30 -0
- data/ext/msgpack/rbinit.c +33 -0
- data/ext/msgpack/rmem.c +94 -0
- data/ext/msgpack/rmem.h +109 -0
- data/ext/msgpack/sysdep.h +115 -0
- data/ext/msgpack/sysdep_endian.h +50 -0
- data/ext/msgpack/sysdep_types.h +46 -0
- data/ext/msgpack/unpacker.c +771 -0
- data/ext/msgpack/unpacker.h +122 -0
- data/ext/msgpack/unpacker_class.c +405 -0
- data/ext/msgpack/unpacker_class.h +32 -0
- data/lib/msgpack.rb +13 -0
- data/lib/msgpack/version.rb +3 -0
- data/msgpack.gemspec +31 -0
- data/msgpack.org.md +46 -0
- data/spec/cases.json +1 -0
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +39 -0
- data/spec/cruby/buffer_io_spec.rb +256 -0
- data/spec/cruby/buffer_packer.rb +29 -0
- data/spec/cruby/buffer_spec.rb +572 -0
- data/spec/cruby/buffer_unpacker.rb +19 -0
- data/spec/cruby/packer_spec.rb +120 -0
- data/spec/cruby/unpacker_spec.rb +305 -0
- data/spec/format_spec.rb +282 -0
- data/spec/jruby/benchmarks/shootout_bm.rb +73 -0
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +25 -0
- data/spec/jruby/msgpack/unpacker_spec.rb +290 -0
- data/spec/jruby/msgpack_spec.rb +142 -0
- data/spec/pack_spec.rb +67 -0
- data/spec/random_compat.rb +24 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/unpack_spec.rb +60 -0
- metadata +208 -0
@@ -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,107 @@
|
|
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 && !args[args.length - 1].isNil()) {
|
100
|
+
RubyHash hash = args[args.length - 1].convertToHash();
|
101
|
+
IRubyObject symbolizeKeys = hash.fastARef(ctx.getRuntime().newSymbol("symbolize_keys"));
|
102
|
+
decoder.symbolizeKeys(symbolizeKeys != null && symbolizeKeys.isTrue());
|
103
|
+
}
|
104
|
+
return decoder.next();
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
import org.jruby.Ruby;
|
5
|
+
import org.jruby.RubyClass;
|
6
|
+
import org.jruby.RubyObject;
|
7
|
+
import org.jruby.RubyHash;
|
8
|
+
import org.jruby.RubyIO;
|
9
|
+
import org.jruby.RubyInteger;
|
10
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
11
|
+
import org.jruby.anno.JRubyClass;
|
12
|
+
import org.jruby.anno.JRubyMethod;
|
13
|
+
import org.jruby.runtime.ThreadContext;
|
14
|
+
import org.jruby.runtime.ObjectAllocator;
|
15
|
+
import org.jruby.util.ByteList;
|
16
|
+
|
17
|
+
|
18
|
+
@JRubyClass(name="MessagePack::Packer")
|
19
|
+
public class Packer extends RubyObject {
|
20
|
+
private Buffer buffer;
|
21
|
+
private Encoder encoder;
|
22
|
+
|
23
|
+
public Packer(Ruby runtime, RubyClass type) {
|
24
|
+
super(runtime, type);
|
25
|
+
}
|
26
|
+
|
27
|
+
static class PackerAllocator implements ObjectAllocator {
|
28
|
+
public IRubyObject allocate(Ruby runtime, RubyClass type) {
|
29
|
+
return new Packer(runtime, type);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
@JRubyMethod(name = "initialize", optional = 2)
|
34
|
+
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
35
|
+
this.encoder = new Encoder(ctx.getRuntime());
|
36
|
+
this.buffer = new Buffer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Buffer"));
|
37
|
+
this.buffer.initialize(ctx, args);
|
38
|
+
return this;
|
39
|
+
}
|
40
|
+
|
41
|
+
@JRubyMethod(name = "write")
|
42
|
+
public IRubyObject write(ThreadContext ctx, IRubyObject obj) {
|
43
|
+
return buffer.write(ctx, encoder.encode(obj, this));
|
44
|
+
}
|
45
|
+
|
46
|
+
@JRubyMethod(name = "write_nil")
|
47
|
+
public IRubyObject writeNil(ThreadContext ctx) {
|
48
|
+
return write(ctx, null);
|
49
|
+
}
|
50
|
+
|
51
|
+
@JRubyMethod(name = "write_array_header")
|
52
|
+
public IRubyObject writeArrayHeader(ThreadContext ctx, IRubyObject size) {
|
53
|
+
int s = (int) size.convertToInteger().getLongValue();
|
54
|
+
return buffer.write(ctx, encoder.encodeArrayHeader(s));
|
55
|
+
}
|
56
|
+
|
57
|
+
@JRubyMethod(name = "write_map_header")
|
58
|
+
public IRubyObject writeMapHeader(ThreadContext ctx, IRubyObject size) {
|
59
|
+
int s = (int) size.convertToInteger().getLongValue();
|
60
|
+
return buffer.write(ctx, encoder.encodeMapHeader(s));
|
61
|
+
}
|
62
|
+
|
63
|
+
@JRubyMethod(name = "to_s")
|
64
|
+
public IRubyObject toS(ThreadContext ctx) {
|
65
|
+
return buffer.toS(ctx);
|
66
|
+
}
|
67
|
+
|
68
|
+
@JRubyMethod(name = "buffer")
|
69
|
+
public IRubyObject buffer(ThreadContext ctx) {
|
70
|
+
return buffer;
|
71
|
+
}
|
72
|
+
|
73
|
+
@JRubyMethod(name = "flush")
|
74
|
+
public IRubyObject flush(ThreadContext ctx) {
|
75
|
+
return buffer.flush(ctx);
|
76
|
+
}
|
77
|
+
|
78
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
public interface Types {
|
5
|
+
public static final byte FIXSTR = (byte) 0xa0; // This is actually not header byte, but prefix bit mask
|
6
|
+
public static final byte NIL = (byte) 0xc0;
|
7
|
+
public static final byte FALSE = (byte) 0xc2;
|
8
|
+
public static final byte TRUE = (byte) 0xc3;
|
9
|
+
public static final byte BIN8 = (byte) 0xc4;
|
10
|
+
public static final byte BIN16 = (byte) 0xc5;
|
11
|
+
public static final byte BIN32 = (byte) 0xc6;
|
12
|
+
public static final byte VAREXT8 = (byte) 0xc7;
|
13
|
+
public static final byte VAREXT16 = (byte) 0xc8;
|
14
|
+
public static final byte VAREXT32 = (byte) 0xc9;
|
15
|
+
public static final byte FLOAT32 = (byte) 0xca;
|
16
|
+
public static final byte FLOAT64 = (byte) 0xcb;
|
17
|
+
public static final byte UINT8 = (byte) 0xcc;
|
18
|
+
public static final byte UINT16 = (byte) 0xcd;
|
19
|
+
public static final byte UINT32 = (byte) 0xce;
|
20
|
+
public static final byte UINT64 = (byte) 0xcf;
|
21
|
+
public static final byte INT8 = (byte) 0xd0;
|
22
|
+
public static final byte INT16 = (byte) 0xd1;
|
23
|
+
public static final byte INT32 = (byte) 0xd2;
|
24
|
+
public static final byte INT64 = (byte) 0xd3;
|
25
|
+
public static final byte FIXEXT1 = (byte) 0xd4;
|
26
|
+
public static final byte FIXEXT2 = (byte) 0xd5;
|
27
|
+
public static final byte FIXEXT4 = (byte) 0xd6;
|
28
|
+
public static final byte FIXEXT8 = (byte) 0xd7;
|
29
|
+
public static final byte FIXEXT16 = (byte) 0xd8;
|
30
|
+
public static final byte STR8 = (byte) 0xd9;
|
31
|
+
public static final byte STR16 = (byte) 0xda;
|
32
|
+
public static final byte STR32 = (byte) 0xdb;
|
33
|
+
public static final byte ARY16 = (byte) 0xdc;
|
34
|
+
public static final byte ARY32 = (byte) 0xdd;
|
35
|
+
public static final byte MAP16 = (byte) 0xde;
|
36
|
+
public static final byte MAP32 = (byte) 0xdf;
|
37
|
+
}
|
@@ -0,0 +1,170 @@
|
|
1
|
+
package org.msgpack.jruby;
|
2
|
+
|
3
|
+
|
4
|
+
import org.jruby.Ruby;
|
5
|
+
import org.jruby.RubyClass;
|
6
|
+
import org.jruby.RubyString;
|
7
|
+
import org.jruby.RubyObject;
|
8
|
+
import org.jruby.RubyHash;
|
9
|
+
import org.jruby.RubyNumeric;
|
10
|
+
import org.jruby.RubyIO;
|
11
|
+
import org.jruby.exceptions.RaiseException;
|
12
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
13
|
+
import org.jruby.runtime.Block;
|
14
|
+
import org.jruby.runtime.ObjectAllocator;
|
15
|
+
import org.jruby.runtime.ThreadContext;
|
16
|
+
import org.jruby.anno.JRubyClass;
|
17
|
+
import org.jruby.anno.JRubyMethod;
|
18
|
+
import org.jruby.util.ByteList;
|
19
|
+
import org.jruby.ext.stringio.StringIO;
|
20
|
+
|
21
|
+
import static org.jruby.runtime.Visibility.PRIVATE;
|
22
|
+
|
23
|
+
|
24
|
+
@JRubyClass(name="MessagePack::Unpacker")
|
25
|
+
public class Unpacker extends RubyObject {
|
26
|
+
private IRubyObject stream;
|
27
|
+
private IRubyObject data;
|
28
|
+
private Decoder decoder;
|
29
|
+
private final RubyClass underflowErrorClass;
|
30
|
+
|
31
|
+
public Unpacker(Ruby runtime, RubyClass type) {
|
32
|
+
super(runtime, type);
|
33
|
+
this.underflowErrorClass = runtime.getModule("MessagePack").getClass("UnderflowError");
|
34
|
+
}
|
35
|
+
|
36
|
+
static class UnpackerAllocator implements ObjectAllocator {
|
37
|
+
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
38
|
+
return new Unpacker(runtime, klass);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
@JRubyMethod(name = "initialize", optional = 1, visibility = PRIVATE)
|
43
|
+
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
44
|
+
if (args.length > 0) {
|
45
|
+
if (args[args.length - 1] instanceof RubyHash) {
|
46
|
+
//TODO: symbolize_keys
|
47
|
+
} else if (!(args[0] instanceof RubyHash)) {
|
48
|
+
setStream(ctx, args[0]);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return this;
|
52
|
+
}
|
53
|
+
|
54
|
+
@JRubyMethod(required = 2)
|
55
|
+
public IRubyObject execute(ThreadContext ctx, IRubyObject data, IRubyObject offset) {
|
56
|
+
return executeLimit(ctx, data, offset, null);
|
57
|
+
}
|
58
|
+
|
59
|
+
@JRubyMethod(name = "execute_limit", required = 3)
|
60
|
+
public IRubyObject executeLimit(ThreadContext ctx, IRubyObject str, IRubyObject off, IRubyObject lim) {
|
61
|
+
RubyString input = str.asString();
|
62
|
+
int offset = RubyNumeric.fix2int(off);
|
63
|
+
int limit = lim == null || lim.isNil() ? -1 : RubyNumeric.fix2int(lim);
|
64
|
+
ByteList byteList = input.getByteList();
|
65
|
+
if (limit == -1) {
|
66
|
+
limit = byteList.length() - offset;
|
67
|
+
}
|
68
|
+
Decoder decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin() + offset, limit);
|
69
|
+
try {
|
70
|
+
this.data = null;
|
71
|
+
this.data = decoder.next();
|
72
|
+
} catch (RaiseException re) {
|
73
|
+
if (re.getException().getType() != underflowErrorClass) {
|
74
|
+
throw re;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return ctx.getRuntime().newFixnum(decoder.offset());
|
78
|
+
}
|
79
|
+
|
80
|
+
@JRubyMethod(name = "data")
|
81
|
+
public IRubyObject getData(ThreadContext ctx) {
|
82
|
+
if (data == null) {
|
83
|
+
return ctx.getRuntime().getNil();
|
84
|
+
} else {
|
85
|
+
return data;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
@JRubyMethod(name = "finished?")
|
90
|
+
public IRubyObject finished_p(ThreadContext ctx) {
|
91
|
+
return data == null ? ctx.getRuntime().getFalse() : ctx.getRuntime().getTrue();
|
92
|
+
}
|
93
|
+
|
94
|
+
@JRubyMethod(required = 1)
|
95
|
+
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
96
|
+
ByteList byteList = data.asString().getByteList();
|
97
|
+
if (decoder == null) {
|
98
|
+
decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
99
|
+
} else {
|
100
|
+
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
101
|
+
}
|
102
|
+
return ctx.getRuntime().getNil();
|
103
|
+
}
|
104
|
+
|
105
|
+
@JRubyMethod(name = "feed_each", required = 1)
|
106
|
+
public IRubyObject feedEach(ThreadContext ctx, IRubyObject data, Block block) {
|
107
|
+
feed(ctx, data);
|
108
|
+
each(ctx, block);
|
109
|
+
return ctx.getRuntime().getNil();
|
110
|
+
}
|
111
|
+
|
112
|
+
@JRubyMethod
|
113
|
+
public IRubyObject each(ThreadContext ctx, Block block) {
|
114
|
+
if (block.isGiven()) {
|
115
|
+
if (decoder != null) {
|
116
|
+
try {
|
117
|
+
while (decoder.hasNext()) {
|
118
|
+
block.yield(ctx, decoder.next());
|
119
|
+
}
|
120
|
+
} catch (RaiseException re) {
|
121
|
+
if (re.getException().getType() != underflowErrorClass) {
|
122
|
+
throw re;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
return this;
|
127
|
+
} else {
|
128
|
+
return callMethod(ctx, "to_enum");
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
@JRubyMethod
|
133
|
+
public IRubyObject fill(ThreadContext ctx) {
|
134
|
+
return ctx.getRuntime().getNil();
|
135
|
+
}
|
136
|
+
|
137
|
+
@JRubyMethod
|
138
|
+
public IRubyObject reset(ThreadContext ctx) {
|
139
|
+
if (decoder != null) {
|
140
|
+
decoder.reset();
|
141
|
+
}
|
142
|
+
return ctx.getRuntime().getNil();
|
143
|
+
}
|
144
|
+
|
145
|
+
@JRubyMethod(name = "stream")
|
146
|
+
public IRubyObject getStream(ThreadContext ctx) {
|
147
|
+
if (stream == null) {
|
148
|
+
return ctx.getRuntime().getNil();
|
149
|
+
} else {
|
150
|
+
return stream;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
@JRubyMethod(name = "stream=", required = 1)
|
155
|
+
public IRubyObject setStream(ThreadContext ctx, IRubyObject stream) {
|
156
|
+
RubyString str;
|
157
|
+
if (stream instanceof StringIO) {
|
158
|
+
str = stream.callMethod(ctx, "string").asString();
|
159
|
+
} else if (stream instanceof RubyIO) {
|
160
|
+
str = stream.callMethod(ctx, "read").asString();
|
161
|
+
} else {
|
162
|
+
throw ctx.getRuntime().newTypeError(stream, "IO");
|
163
|
+
}
|
164
|
+
ByteList byteList = str.getByteList();
|
165
|
+
this.stream = stream;
|
166
|
+
this.decoder = null;
|
167
|
+
this.decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
168
|
+
return getStream(ctx);
|
169
|
+
}
|
170
|
+
}
|