msgpack 0.7.0dev1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -0
- data/ChangeLog +8 -0
- data/README.rdoc +36 -2
- data/ext/java/org/msgpack/jruby/Decoder.java +55 -16
- data/ext/java/org/msgpack/jruby/Encoder.java +31 -8
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +159 -0
- data/ext/java/org/msgpack/jruby/Factory.java +117 -0
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +23 -6
- data/ext/java/org/msgpack/jruby/Packer.java +65 -6
- data/ext/java/org/msgpack/jruby/Unpacker.java +104 -22
- data/ext/msgpack/packer_class.c +7 -0
- data/ext/msgpack/packer_ext_registry.c +0 -8
- data/ext/msgpack/packer_ext_registry.h +0 -3
- data/ext/msgpack/unpacker_class.c +14 -0
- data/ext/msgpack/unpacker_ext_registry.c +0 -6
- data/ext/msgpack/unpacker_ext_registry.h +0 -3
- data/lib/msgpack/version.rb +1 -1
- data/msgpack.gemspec +5 -3
- data/spec/cruby/unpacker_spec.rb +0 -247
- data/spec/factory_spec.rb +0 -3
- data/spec/jruby/{msgpack/unpacker_spec.rb → unpacker_spec.rb} +30 -159
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +135 -4
- data/spec/unpacker_spec.rb +465 -6
- metadata +10 -8
- data/spec/cruby/packer_spec.rb +0 -138
@@ -0,0 +1,117 @@
|
|
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.RubyArray;
|
8
|
+
import org.jruby.RubyHash;
|
9
|
+
import org.jruby.RubyIO;
|
10
|
+
import org.jruby.RubyInteger;
|
11
|
+
import org.jruby.RubyFixnum;
|
12
|
+
import org.jruby.RubyString;
|
13
|
+
import org.jruby.RubySymbol;
|
14
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
15
|
+
import org.jruby.anno.JRubyClass;
|
16
|
+
import org.jruby.anno.JRubyMethod;
|
17
|
+
import org.jruby.runtime.ThreadContext;
|
18
|
+
import org.jruby.runtime.ObjectAllocator;
|
19
|
+
import org.jruby.util.ByteList;
|
20
|
+
|
21
|
+
import static org.jruby.runtime.Visibility.PRIVATE;
|
22
|
+
|
23
|
+
@JRubyClass(name="MessagePack::Factory")
|
24
|
+
public class Factory extends RubyObject {
|
25
|
+
private final Ruby runtime;
|
26
|
+
private final ExtensionRegistry extensionRegistry;
|
27
|
+
|
28
|
+
public Factory(Ruby runtime, RubyClass type) {
|
29
|
+
super(runtime, type);
|
30
|
+
this.runtime = runtime;
|
31
|
+
this.extensionRegistry = new ExtensionRegistry();
|
32
|
+
}
|
33
|
+
|
34
|
+
static class FactoryAllocator implements ObjectAllocator {
|
35
|
+
public IRubyObject allocate(Ruby runtime, RubyClass type) {
|
36
|
+
return new Factory(runtime, type);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
public ExtensionRegistry extensionRegistry() {
|
41
|
+
return extensionRegistry.dup();
|
42
|
+
}
|
43
|
+
|
44
|
+
@JRubyMethod(name = "initialize")
|
45
|
+
public IRubyObject initialize(ThreadContext ctx) {
|
46
|
+
return this;
|
47
|
+
}
|
48
|
+
|
49
|
+
@JRubyMethod(name = "packer", optional = 1)
|
50
|
+
public Packer packer(ThreadContext ctx, IRubyObject[] args) {
|
51
|
+
return Packer.newPacker(ctx, extensionRegistry(), args);
|
52
|
+
}
|
53
|
+
|
54
|
+
@JRubyMethod(name = "unpacker", optional = 1)
|
55
|
+
public Unpacker unpacker(ThreadContext ctx, IRubyObject[] args) {
|
56
|
+
return Unpacker.newUnpacker(ctx, extensionRegistry(), args);
|
57
|
+
}
|
58
|
+
|
59
|
+
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
|
60
|
+
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
|
61
|
+
return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {
|
62
|
+
extensionRegistry.toInternalPackerRegistry(ctx),
|
63
|
+
extensionRegistry.toInternalUnpackerRegistry(ctx)
|
64
|
+
});
|
65
|
+
}
|
66
|
+
|
67
|
+
@JRubyMethod(name = "register_type", required = 2, optional = 1)
|
68
|
+
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args) {
|
69
|
+
Ruby runtime = ctx.getRuntime();
|
70
|
+
IRubyObject type = args[0];
|
71
|
+
IRubyObject klass = args[1];
|
72
|
+
|
73
|
+
IRubyObject packerArg;
|
74
|
+
IRubyObject unpackerArg;
|
75
|
+
if (args.length == 2) {
|
76
|
+
packerArg = runtime.newSymbol("to_msgpack_ext");
|
77
|
+
unpackerArg = runtime.newSymbol("from_msgpack_ext");
|
78
|
+
} else if (args.length == 3) {
|
79
|
+
if (args[args.length - 1] instanceof RubyHash) {
|
80
|
+
RubyHash options = (RubyHash) args[args.length - 1];
|
81
|
+
packerArg = options.fastARef(runtime.newSymbol("packer"));
|
82
|
+
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
|
83
|
+
} else {
|
84
|
+
throw runtime.newArgumentError(String.format("expected Hash but found %s.", args[args.length - 1].getType().getName()));
|
85
|
+
}
|
86
|
+
} else {
|
87
|
+
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
|
88
|
+
}
|
89
|
+
|
90
|
+
long typeId = ((RubyFixnum) type).getLongValue();
|
91
|
+
if (typeId < -128 || typeId > 127) {
|
92
|
+
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
93
|
+
}
|
94
|
+
|
95
|
+
if (!(klass instanceof RubyClass)) {
|
96
|
+
throw runtime.newArgumentError(String.format("expected Class but found %s.", klass.getType().getName()));
|
97
|
+
}
|
98
|
+
RubyClass extClass = (RubyClass) klass;
|
99
|
+
|
100
|
+
IRubyObject packerProc = runtime.getNil();
|
101
|
+
IRubyObject unpackerProc = runtime.getNil();
|
102
|
+
if (packerArg != null) {
|
103
|
+
packerProc = packerArg.callMethod(ctx, "to_proc");
|
104
|
+
}
|
105
|
+
if (unpackerArg != null) {
|
106
|
+
if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
|
107
|
+
unpackerProc = extClass.method(unpackerArg.callMethod(ctx, "to_sym"));
|
108
|
+
} else {
|
109
|
+
unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
extensionRegistry.put(extClass, (int) typeId, packerProc, packerArg, unpackerProc, unpackerArg);
|
114
|
+
|
115
|
+
return runtime.getNil();
|
116
|
+
}
|
117
|
+
}
|
@@ -20,15 +20,20 @@ import org.jruby.internal.runtime.methods.DynamicMethod;
|
|
20
20
|
|
21
21
|
|
22
22
|
public class MessagePackLibrary implements Library {
|
23
|
+
public static Factory defaultFactory;
|
24
|
+
|
23
25
|
public void load(Ruby runtime, boolean wrap) {
|
24
26
|
RubyModule msgpackModule = runtime.defineModule("MessagePack");
|
25
27
|
msgpackModule.defineAnnotatedMethods(MessagePackModule.class);
|
26
28
|
RubyClass standardErrorClass = runtime.getStandardError();
|
27
29
|
RubyClass unpackErrorClass = msgpackModule.defineClassUnder("UnpackError", standardErrorClass, standardErrorClass.getAllocator());
|
28
30
|
RubyClass underflowErrorClass = msgpackModule.defineClassUnder("UnderflowError", unpackErrorClass, unpackErrorClass.getAllocator());
|
31
|
+
RubyClass malformedFormatErrorClass = msgpackModule.defineClassUnder("MalformedFormatError", unpackErrorClass, unpackErrorClass.getAllocator());
|
32
|
+
RubyClass stackErrorClass = msgpackModule.defineClassUnder("StackError", unpackErrorClass, unpackErrorClass.getAllocator());
|
29
33
|
RubyModule typeErrorModule = msgpackModule.defineModuleUnder("TypeError");
|
30
|
-
RubyClass unexpectedTypeErrorClass = msgpackModule.defineClassUnder("
|
34
|
+
RubyClass unexpectedTypeErrorClass = msgpackModule.defineClassUnder("UnexpectedTypeError", unpackErrorClass, unpackErrorClass.getAllocator());
|
31
35
|
unexpectedTypeErrorClass.includeModule(typeErrorModule);
|
36
|
+
RubyClass unknownExtTypeErrorClass = msgpackModule.defineClassUnder("UnknownExtTypeError", unpackErrorClass, unpackErrorClass.getAllocator());
|
32
37
|
RubyClass extensionValueClass = msgpackModule.defineClassUnder("ExtensionValue", runtime.getObject(), new ExtensionValue.ExtensionValueAllocator());
|
33
38
|
extensionValueClass.defineAnnotatedMethods(ExtensionValue.class);
|
34
39
|
RubyClass packerClass = msgpackModule.defineClassUnder("Packer", runtime.getObject(), new Packer.PackerAllocator());
|
@@ -37,6 +42,11 @@ public class MessagePackLibrary implements Library {
|
|
37
42
|
unpackerClass.defineAnnotatedMethods(Unpacker.class);
|
38
43
|
RubyClass bufferClass = msgpackModule.defineClassUnder("Buffer", runtime.getObject(), new Buffer.BufferAllocator());
|
39
44
|
bufferClass.defineAnnotatedMethods(Buffer.class);
|
45
|
+
RubyClass factoryClass = msgpackModule.defineClassUnder("Factory", runtime.getObject(), new Factory.FactoryAllocator());
|
46
|
+
factoryClass.defineAnnotatedMethods(Factory.class);
|
47
|
+
defaultFactory = new Factory(runtime, factoryClass);
|
48
|
+
defaultFactory.initialize(runtime.getCurrentContext());
|
49
|
+
msgpackModule.defineConstant("DefaultFactory", defaultFactory);
|
40
50
|
installCoreExtensions(runtime);
|
41
51
|
}
|
42
52
|
|
@@ -100,20 +110,27 @@ public class MessagePackLibrary implements Library {
|
|
100
110
|
extraArgs = new IRubyObject[args.length - 1];
|
101
111
|
System.arraycopy(args, 1, extraArgs, 0, args.length - 1);
|
102
112
|
}
|
103
|
-
Packer packer =
|
104
|
-
packer.initialize(ctx, extraArgs);
|
113
|
+
Packer packer = MessagePackLibrary.defaultFactory.packer(ctx, extraArgs);
|
105
114
|
packer.write(ctx, args[0]);
|
106
115
|
return packer.toS(ctx);
|
107
116
|
}
|
108
117
|
|
109
118
|
@JRubyMethod(module = true, required = 1, optional = 1, alias = {"load"})
|
110
119
|
public static IRubyObject unpack(ThreadContext ctx, IRubyObject recv, IRubyObject[] args) {
|
111
|
-
|
120
|
+
ExtensionRegistry registry = MessagePackLibrary.defaultFactory.extensionRegistry();
|
121
|
+
|
122
|
+
boolean symbolizeKeys = false;
|
123
|
+
boolean allowUnknownExt = false;
|
112
124
|
if (args.length > 1 && !args[args.length - 1].isNil()) {
|
113
125
|
RubyHash hash = args[args.length - 1].convertToHash();
|
114
|
-
IRubyObject
|
115
|
-
|
126
|
+
IRubyObject symbolizeKeysVal = hash.fastARef(ctx.getRuntime().newSymbol("symbolize_keys"));
|
127
|
+
symbolizeKeys = symbolizeKeysVal != null && symbolizeKeysVal.isTrue();
|
128
|
+
IRubyObject allowUnknownExtVal = hash.fastARef(ctx.getRuntime().newSymbol("allow_unknown_ext"));
|
129
|
+
allowUnknownExt = (allowUnknownExtVal != null && allowUnknownExtVal.isTrue());
|
116
130
|
}
|
131
|
+
byte[] bytes = args[0].asString().getBytes();
|
132
|
+
Decoder decoder = new Decoder(ctx.getRuntime(), registry, bytes, 0, bytes.length, symbolizeKeys, allowUnknownExt);
|
133
|
+
|
117
134
|
return decoder.next();
|
118
135
|
}
|
119
136
|
}
|
@@ -4,9 +4,12 @@ package org.msgpack.jruby;
|
|
4
4
|
import org.jruby.Ruby;
|
5
5
|
import org.jruby.RubyClass;
|
6
6
|
import org.jruby.RubyObject;
|
7
|
+
import org.jruby.RubyArray;
|
7
8
|
import org.jruby.RubyHash;
|
8
9
|
import org.jruby.RubyIO;
|
9
10
|
import org.jruby.RubyInteger;
|
11
|
+
import org.jruby.RubyFixnum;
|
12
|
+
import org.jruby.runtime.Block;
|
10
13
|
import org.jruby.runtime.builtin.IRubyObject;
|
11
14
|
import org.jruby.anno.JRubyClass;
|
12
15
|
import org.jruby.anno.JRubyMethod;
|
@@ -14,19 +17,22 @@ import org.jruby.runtime.ThreadContext;
|
|
14
17
|
import org.jruby.runtime.ObjectAllocator;
|
15
18
|
import org.jruby.util.ByteList;
|
16
19
|
|
20
|
+
import static org.jruby.runtime.Visibility.PRIVATE;
|
17
21
|
|
18
22
|
@JRubyClass(name="MessagePack::Packer")
|
19
23
|
public class Packer extends RubyObject {
|
24
|
+
public ExtensionRegistry registry;
|
20
25
|
private Buffer buffer;
|
21
26
|
private Encoder encoder;
|
22
27
|
|
23
|
-
public Packer(Ruby runtime, RubyClass type) {
|
28
|
+
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry) {
|
24
29
|
super(runtime, type);
|
30
|
+
this.registry = registry;
|
25
31
|
}
|
26
32
|
|
27
33
|
static class PackerAllocator implements ObjectAllocator {
|
28
34
|
public IRubyObject allocate(Ruby runtime, RubyClass type) {
|
29
|
-
return new Packer(runtime, type);
|
35
|
+
return new Packer(runtime, type, null);
|
30
36
|
}
|
31
37
|
}
|
32
38
|
|
@@ -35,15 +41,68 @@ public class Packer extends RubyObject {
|
|
35
41
|
boolean compatibilityMode = false;
|
36
42
|
if (args.length > 0 && args[args.length - 1] instanceof RubyHash) {
|
37
43
|
RubyHash options = (RubyHash) args[args.length - 1];
|
38
|
-
|
44
|
+
IRubyObject mode = options.fastARef(ctx.getRuntime().newSymbol("compatibility_mode"));
|
45
|
+
compatibilityMode = (mode != null) && mode.isTrue();
|
39
46
|
}
|
40
|
-
this.encoder = new Encoder(ctx.getRuntime(), compatibilityMode);
|
47
|
+
this.encoder = new Encoder(ctx.getRuntime(), compatibilityMode, registry);
|
41
48
|
this.buffer = new Buffer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Buffer"));
|
42
49
|
this.buffer.initialize(ctx, args);
|
50
|
+
this.registry = new ExtensionRegistry();
|
43
51
|
return this;
|
44
52
|
}
|
45
53
|
|
46
|
-
|
54
|
+
public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, IRubyObject[] args) {
|
55
|
+
Packer packer = new Packer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Packer"), extRegistry);
|
56
|
+
packer.initialize(ctx, args);
|
57
|
+
return packer;
|
58
|
+
}
|
59
|
+
|
60
|
+
@JRubyMethod(name = "compatibility_mode?")
|
61
|
+
public IRubyObject isCompatibilityMode(ThreadContext ctx) {
|
62
|
+
return encoder.isCompatibilityMode() ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
|
63
|
+
}
|
64
|
+
|
65
|
+
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
|
66
|
+
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
|
67
|
+
return registry.toInternalPackerRegistry(ctx);
|
68
|
+
}
|
69
|
+
|
70
|
+
@JRubyMethod(name = "register_type", required = 2, optional = 1)
|
71
|
+
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
72
|
+
Ruby runtime = ctx.getRuntime();
|
73
|
+
IRubyObject type = args[0];
|
74
|
+
IRubyObject klass = args[1];
|
75
|
+
|
76
|
+
IRubyObject arg;
|
77
|
+
IRubyObject proc;
|
78
|
+
if (args.length == 2) {
|
79
|
+
if (! block.isGiven()) {
|
80
|
+
throw runtime.newLocalJumpErrorNoBlock();
|
81
|
+
}
|
82
|
+
proc = block.getProcObject();
|
83
|
+
arg = proc;
|
84
|
+
} else if (args.length == 3) {
|
85
|
+
arg = args[2];
|
86
|
+
proc = arg.callMethod(ctx, "to_proc");
|
87
|
+
} else {
|
88
|
+
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
|
89
|
+
}
|
90
|
+
|
91
|
+
long typeId = ((RubyFixnum) type).getLongValue();
|
92
|
+
if (typeId < -128 || typeId > 127) {
|
93
|
+
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
94
|
+
}
|
95
|
+
|
96
|
+
if (!(klass instanceof RubyClass)) {
|
97
|
+
throw runtime.newArgumentError(String.format("expected Class but found %s.", klass.getType().getName()));
|
98
|
+
}
|
99
|
+
RubyClass extClass = (RubyClass) klass;
|
100
|
+
|
101
|
+
registry.put(extClass, (int) typeId, proc, arg, null, null);
|
102
|
+
return runtime.getNil();
|
103
|
+
}
|
104
|
+
|
105
|
+
@JRubyMethod(name = "write", alias = { "pack" })
|
47
106
|
public IRubyObject write(ThreadContext ctx, IRubyObject obj) {
|
48
107
|
buffer.write(ctx, encoder.encode(obj, this));
|
49
108
|
return this;
|
@@ -69,7 +128,7 @@ public class Packer extends RubyObject {
|
|
69
128
|
return this;
|
70
129
|
}
|
71
130
|
|
72
|
-
@JRubyMethod(name = "to_s")
|
131
|
+
@JRubyMethod(name = "to_s", alias = { "to_str" })
|
73
132
|
public IRubyObject toS(ThreadContext ctx) {
|
74
133
|
return buffer.toS(ctx);
|
75
134
|
}
|
@@ -1,12 +1,16 @@
|
|
1
1
|
package org.msgpack.jruby;
|
2
2
|
|
3
|
+
import java.util.Arrays;
|
3
4
|
|
4
5
|
import org.jruby.Ruby;
|
5
6
|
import org.jruby.RubyClass;
|
6
7
|
import org.jruby.RubyString;
|
7
8
|
import org.jruby.RubyObject;
|
9
|
+
import org.jruby.RubyArray;
|
8
10
|
import org.jruby.RubyHash;
|
9
11
|
import org.jruby.RubyNumeric;
|
12
|
+
import org.jruby.RubyFixnum;
|
13
|
+
import org.jruby.RubyProc;
|
10
14
|
import org.jruby.RubyIO;
|
11
15
|
import org.jruby.exceptions.RaiseException;
|
12
16
|
import org.jruby.runtime.builtin.IRubyObject;
|
@@ -20,17 +24,24 @@ import org.jruby.ext.stringio.StringIO;
|
|
20
24
|
|
21
25
|
import static org.jruby.runtime.Visibility.PRIVATE;
|
22
26
|
|
23
|
-
|
24
27
|
@JRubyClass(name="MessagePack::Unpacker")
|
25
28
|
public class Unpacker extends RubyObject {
|
29
|
+
private final ExtensionRegistry registry;
|
30
|
+
|
26
31
|
private IRubyObject stream;
|
27
32
|
private IRubyObject data;
|
28
33
|
private Decoder decoder;
|
29
34
|
private final RubyClass underflowErrorClass;
|
30
35
|
private boolean symbolizeKeys;
|
36
|
+
private boolean allowUnknownExt;
|
31
37
|
|
32
38
|
public Unpacker(Ruby runtime, RubyClass type) {
|
39
|
+
this(runtime, type, new ExtensionRegistry());
|
40
|
+
}
|
41
|
+
|
42
|
+
public Unpacker(Ruby runtime, RubyClass type, ExtensionRegistry registry) {
|
33
43
|
super(runtime, type);
|
44
|
+
this.registry = registry;
|
34
45
|
this.underflowErrorClass = runtime.getModule("MessagePack").getClass("UnderflowError");
|
35
46
|
}
|
36
47
|
|
@@ -43,6 +54,7 @@ public class Unpacker extends RubyObject {
|
|
43
54
|
@JRubyMethod(name = "initialize", optional = 1, visibility = PRIVATE)
|
44
55
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
45
56
|
symbolizeKeys = false;
|
57
|
+
allowUnknownExt = false;
|
46
58
|
if (args.length > 0) {
|
47
59
|
if (args[args.length - 1] instanceof RubyHash) {
|
48
60
|
RubyHash options = (RubyHash) args[args.length - 1];
|
@@ -50,6 +62,10 @@ public class Unpacker extends RubyObject {
|
|
50
62
|
if (sk != null) {
|
51
63
|
symbolizeKeys = sk.isTrue();
|
52
64
|
}
|
65
|
+
IRubyObject au = options.fastARef(ctx.getRuntime().newSymbol("allow_unknown_ext"));
|
66
|
+
if (au != null) {
|
67
|
+
allowUnknownExt = au.isTrue();
|
68
|
+
}
|
53
69
|
} else if (!(args[0] instanceof RubyHash)) {
|
54
70
|
setStream(ctx, args[0]);
|
55
71
|
}
|
@@ -57,6 +73,61 @@ public class Unpacker extends RubyObject {
|
|
57
73
|
return this;
|
58
74
|
}
|
59
75
|
|
76
|
+
public static Unpacker newUnpacker(ThreadContext ctx, ExtensionRegistry extRegistry, IRubyObject[] args) {
|
77
|
+
Unpacker unpacker = new Unpacker(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Unpacker"), extRegistry);
|
78
|
+
unpacker.initialize(ctx, args);
|
79
|
+
return unpacker;
|
80
|
+
}
|
81
|
+
|
82
|
+
@JRubyMethod(name = "symbolize_keys?")
|
83
|
+
public IRubyObject isSymbolizeKeys(ThreadContext ctx) {
|
84
|
+
return symbolizeKeys ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
|
85
|
+
}
|
86
|
+
|
87
|
+
@JRubyMethod(name = "allow_unknown_ext?")
|
88
|
+
public IRubyObject isAllowUnknownExt(ThreadContext ctx) {
|
89
|
+
return allowUnknownExt ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
|
90
|
+
}
|
91
|
+
|
92
|
+
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
|
93
|
+
public IRubyObject registeredTypesInternal(ThreadContext ctx) {
|
94
|
+
return registry.toInternalUnpackerRegistry(ctx);
|
95
|
+
}
|
96
|
+
|
97
|
+
@JRubyMethod(name = "register_type", required = 1, optional = 2)
|
98
|
+
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
99
|
+
Ruby runtime = ctx.getRuntime();
|
100
|
+
IRubyObject type = args[0];
|
101
|
+
|
102
|
+
RubyClass extClass;
|
103
|
+
IRubyObject arg;
|
104
|
+
IRubyObject proc;
|
105
|
+
if (args.length == 1) {
|
106
|
+
if (! block.isGiven()) {
|
107
|
+
throw runtime.newLocalJumpErrorNoBlock();
|
108
|
+
}
|
109
|
+
proc = RubyProc.newProc(runtime, block, block.type);
|
110
|
+
if (proc == null)
|
111
|
+
System.err.println("proc from Block is null");
|
112
|
+
arg = proc;
|
113
|
+
extClass = null;
|
114
|
+
} else if (args.length == 3) {
|
115
|
+
extClass = (RubyClass) args[1];
|
116
|
+
arg = args[2];
|
117
|
+
proc = extClass.method(arg);
|
118
|
+
} else {
|
119
|
+
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
|
120
|
+
}
|
121
|
+
|
122
|
+
long typeId = ((RubyFixnum) type).getLongValue();
|
123
|
+
if (typeId < -128 || typeId > 127) {
|
124
|
+
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
125
|
+
}
|
126
|
+
|
127
|
+
registry.put(extClass, (int) typeId, null, null, proc, arg);
|
128
|
+
return runtime.getNil();
|
129
|
+
}
|
130
|
+
|
60
131
|
@JRubyMethod(required = 2)
|
61
132
|
public IRubyObject execute(ThreadContext ctx, IRubyObject data, IRubyObject offset) {
|
62
133
|
return executeLimit(ctx, data, offset, null);
|
@@ -71,11 +142,10 @@ public class Unpacker extends RubyObject {
|
|
71
142
|
if (limit == -1) {
|
72
143
|
limit = byteList.length() - offset;
|
73
144
|
}
|
74
|
-
Decoder decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin() + offset, limit);
|
75
|
-
decoder.symbolizeKeys(symbolizeKeys);
|
145
|
+
Decoder decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, allowUnknownExt);
|
76
146
|
try {
|
77
|
-
|
78
|
-
|
147
|
+
data = null;
|
148
|
+
data = decoder.next();
|
79
149
|
} catch (RaiseException re) {
|
80
150
|
if (re.getException().getType() != underflowErrorClass) {
|
81
151
|
throw re;
|
@@ -102,8 +172,7 @@ public class Unpacker extends RubyObject {
|
|
102
172
|
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
103
173
|
ByteList byteList = data.asString().getByteList();
|
104
174
|
if (decoder == null) {
|
105
|
-
decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
106
|
-
decoder.symbolizeKeys(symbolizeKeys);
|
175
|
+
decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, allowUnknownExt);
|
107
176
|
} else {
|
108
177
|
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
109
178
|
}
|
@@ -113,8 +182,12 @@ public class Unpacker extends RubyObject {
|
|
113
182
|
@JRubyMethod(name = "feed_each", required = 1)
|
114
183
|
public IRubyObject feedEach(ThreadContext ctx, IRubyObject data, Block block) {
|
115
184
|
feed(ctx, data);
|
116
|
-
|
117
|
-
|
185
|
+
if (block.isGiven()) {
|
186
|
+
each(ctx, block);
|
187
|
+
return ctx.getRuntime().getNil();
|
188
|
+
} else {
|
189
|
+
return callMethod(ctx, "to_enum");
|
190
|
+
}
|
118
191
|
}
|
119
192
|
|
120
193
|
@JRubyMethod
|
@@ -150,20 +223,30 @@ public class Unpacker extends RubyObject {
|
|
150
223
|
return ctx.getRuntime().getNil();
|
151
224
|
}
|
152
225
|
|
153
|
-
@JRubyMethod
|
226
|
+
@JRubyMethod(name = "read", alias = { "unpack" })
|
154
227
|
public IRubyObject read(ThreadContext ctx) {
|
155
|
-
if (decoder
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
228
|
+
if (decoder == null) {
|
229
|
+
throw ctx.getRuntime().newEOFError();
|
230
|
+
}
|
231
|
+
try {
|
232
|
+
return decoder.next();
|
233
|
+
} catch (RaiseException re) {
|
234
|
+
if (re.getException().getType() != underflowErrorClass) {
|
235
|
+
throw re;
|
236
|
+
} else {
|
237
|
+
throw ctx.getRuntime().newEOFError();
|
164
238
|
}
|
165
239
|
}
|
166
|
-
|
240
|
+
}
|
241
|
+
|
242
|
+
@JRubyMethod(name = "skip")
|
243
|
+
public IRubyObject skip(ThreadContext ctx) {
|
244
|
+
throw ctx.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
|
245
|
+
}
|
246
|
+
|
247
|
+
@JRubyMethod(name = "skip_nil")
|
248
|
+
public IRubyObject skipNil(ThreadContext ctx) {
|
249
|
+
throw ctx.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
|
167
250
|
}
|
168
251
|
|
169
252
|
@JRubyMethod
|
@@ -220,8 +303,7 @@ public class Unpacker extends RubyObject {
|
|
220
303
|
ByteList byteList = str.getByteList();
|
221
304
|
this.stream = stream;
|
222
305
|
this.decoder = null;
|
223
|
-
this.decoder = new Decoder(ctx.getRuntime(), byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
224
|
-
decoder.symbolizeKeys(symbolizeKeys);
|
306
|
+
this.decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, allowUnknownExt);
|
225
307
|
return getStream(ctx);
|
226
308
|
}
|
227
309
|
}
|