msgpack 0.7.0dev1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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("UnexpetedTypeError", unpackErrorClass, standardErrorClass.getAllocator());
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 = new Packer(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("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
- Decoder decoder = new Decoder(ctx.getRuntime(), args[0].asString().getBytes());
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 symbolizeKeys = hash.fastARef(ctx.getRuntime().newSymbol("symbolize_keys"));
115
- decoder.symbolizeKeys(symbolizeKeys != null && symbolizeKeys.isTrue());
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
- compatibilityMode = options.fastARef(ctx.getRuntime().newSymbol("compatibility_mode")).isTrue();
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
- @JRubyMethod(name = "write")
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
- this.data = null;
78
- this.data = decoder.next();
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
- each(ctx, block);
117
- return ctx.getRuntime().getNil();
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 != null) {
156
- try {
157
- return decoder.next();
158
- } catch (RaiseException re) {
159
- if (re.getException().getType() != underflowErrorClass) {
160
- throw re;
161
- } else {
162
- throw ctx.getRuntime().newEOFError();
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
- return ctx.getRuntime().getNil();
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
  }