msgpack 0.7.4 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -1
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +27 -14
  5. data/ChangeLog +89 -1
  6. data/Gemfile +6 -1
  7. data/README.rdoc +55 -1
  8. data/Rakefile +5 -1
  9. data/bench/pack_symbols.rb +28 -0
  10. data/bench/run_symbols.sh +26 -0
  11. data/doclib/msgpack.rb +2 -2
  12. data/doclib/msgpack/core_ext.rb +20 -20
  13. data/doclib/msgpack/factory.rb +33 -0
  14. data/doclib/msgpack/packer.rb +20 -0
  15. data/doclib/msgpack/time.rb +22 -0
  16. data/doclib/msgpack/timestamp.rb +44 -0
  17. data/ext/java/org/msgpack/jruby/Buffer.java +4 -0
  18. data/ext/java/org/msgpack/jruby/Encoder.java +48 -18
  19. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +67 -38
  20. data/ext/java/org/msgpack/jruby/Factory.java +20 -8
  21. data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +0 -92
  22. data/ext/java/org/msgpack/jruby/Packer.java +114 -11
  23. data/ext/java/org/msgpack/jruby/Unpacker.java +15 -8
  24. data/ext/msgpack/buffer.h +14 -0
  25. data/ext/msgpack/buffer_class.c +1 -1
  26. data/ext/msgpack/compat.h +10 -0
  27. data/ext/msgpack/factory_class.c +24 -17
  28. data/ext/msgpack/factory_class.h +0 -2
  29. data/ext/msgpack/packer.c +5 -4
  30. data/ext/msgpack/packer.h +13 -1
  31. data/ext/msgpack/packer_class.c +130 -43
  32. data/ext/msgpack/packer_class.h +0 -2
  33. data/ext/msgpack/packer_ext_registry.c +2 -2
  34. data/ext/msgpack/packer_ext_registry.h +64 -25
  35. data/ext/msgpack/rbinit.c +0 -2
  36. data/ext/msgpack/unpacker.c +3 -3
  37. data/ext/msgpack/unpacker_class.c +25 -56
  38. data/ext/msgpack/unpacker_class.h +0 -2
  39. data/ext/msgpack/unpacker_ext_registry.c +2 -2
  40. data/ext/msgpack/unpacker_ext_registry.h +3 -3
  41. data/lib/msgpack.rb +36 -0
  42. data/lib/msgpack/core_ext.rb +139 -0
  43. data/lib/msgpack/factory.rb +21 -0
  44. data/lib/msgpack/symbol.rb +9 -0
  45. data/lib/msgpack/time.rb +29 -0
  46. data/lib/msgpack/timestamp.rb +76 -0
  47. data/lib/msgpack/version.rb +8 -1
  48. data/msgpack.gemspec +6 -7
  49. data/spec/cruby/buffer_spec.rb +6 -1
  50. data/spec/factory_spec.rb +134 -0
  51. data/spec/msgpack_spec.rb +52 -0
  52. data/spec/packer_spec.rb +200 -0
  53. data/spec/timestamp_spec.rb +121 -0
  54. data/spec/unpacker_spec.rb +29 -0
  55. metadata +29 -23
  56. data/ext/msgpack/core_ext.c +0 -144
  57. data/ext/msgpack/core_ext.h +0 -26
@@ -19,6 +19,22 @@ module MessagePack
19
19
  def packer(*args)
20
20
  end
21
21
 
22
+ #
23
+ # Serialize the passed value
24
+ #
25
+ # If it could not serialize the object, it raises
26
+ # NoMethodError: undefined method `to_msgpack' for #<the_object>.
27
+ #
28
+ # @param obj [Object] object to serialize
29
+ # @param options [Hash]
30
+ # @return [String] serialized object
31
+ #
32
+ # See Packer#initialize for supported options.
33
+ #
34
+ def dump(obj, options={})
35
+ end
36
+ alias pack dump
37
+
22
38
  #
23
39
  # Creates a MessagePack::Unpacker instance, which has ext types already registered.
24
40
  # Options are passed to MessagePack::Unpacker#initialized.
@@ -28,6 +44,23 @@ module MessagePack
28
44
  def unpacker(*args)
29
45
  end
30
46
 
47
+ #
48
+ # Deserializes an object from the string or io and returns it.
49
+ #
50
+ # If there're not enough data to deserialize one object, this method raises EOFError.
51
+ # If data format is invalid, this method raises MessagePack::MalformedFormatError.
52
+ # If the object nests too deeply, this method raises MessagePack::StackError.
53
+ #
54
+ # @param data [String]
55
+ # @param options [Hash]
56
+ # @return [Object] deserialized object
57
+ #
58
+ # See Unpacker#initialize for supported options.
59
+ #
60
+ def load(data, options={})
61
+ end
62
+ alias unpack load
63
+
31
64
  #
32
65
  # Register a type and Class to be registered for packer and/or unpacker.
33
66
  # If options are not speicified, factory will use :to_msgpack_ext for packer, and
@@ -91,6 +91,12 @@ module MessagePack
91
91
  def write_nil
92
92
  end
93
93
 
94
+ #
95
+ # Serializes a string object as binary data. Same as write("string".encode(Encoding::BINARY)).
96
+ #
97
+ def write_bin(obj)
98
+ end
99
+
94
100
  #
95
101
  # Write a header of an array whose size is _n_.
96
102
  # For example, write_array_header(1).write(true) is same as write([ true ]).
@@ -109,6 +115,20 @@ module MessagePack
109
115
  def write_map_header(n)
110
116
  end
111
117
 
118
+ #
119
+ # Write a header of a binary string whose size is _n_. Useful if you want to append large binary data without loading it into memory at once.
120
+ # For example,
121
+ # MessagePack::Packer.new(io).write_bin_header(12).flush
122
+ # io.write('chunk1')
123
+ # io.write('chunk2')
124
+ # is the same as
125
+ # write('chunk1chunk2'.encode(Encoding::BINARY)).
126
+ #
127
+ # @return [Packer] self
128
+ #
129
+ def write_bin_header(n)
130
+ end
131
+
112
132
  #
113
133
  # Serializes _value_ as 32-bit single precision float into internal buffer.
114
134
  # _value_ will be approximated with the nearest possible single precision float, thus
@@ -0,0 +1,22 @@
1
+ module MessagePack
2
+
3
+ # MessagePack::Time provides packer and unpacker functions for a timestamp type.
4
+ # @example Setup for DefaultFactory
5
+ # MessagePack::DefaultFactory.register_type(
6
+ # MessagePack::Timestamp::TYPE,
7
+ # Time,
8
+ # packer: MessagePack::Time::Packer,
9
+ # unpacker: MessagePack::Time::Unpacker
10
+ # )
11
+ class Time
12
+ # A packer function that packs a Time instance to a MessagePack timestamp.
13
+ Packer = lambda { |payload|
14
+ # ...
15
+ }
16
+
17
+ # An unpacker function that unpacks a MessagePack timestamp to a Time instance.
18
+ Unpacker = lambda { |time|
19
+ # ...
20
+ }
21
+ end
22
+ end
@@ -0,0 +1,44 @@
1
+ module MessagePack
2
+ # A utility class for MessagePack timestamp type
3
+ class Timestamp
4
+ #
5
+ # The timestamp extension type defined in the MessagePack spec.
6
+ #
7
+ # See https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type for details.
8
+ #
9
+ TYPE = -1
10
+
11
+ # @return [Integer] Second part of the timestamp.
12
+ attr_reader :sec
13
+
14
+ # @return [Integer] Nanosecond part of the timestamp.
15
+ attr_reader :nsec
16
+
17
+ # @param [Integer] sec
18
+ # @param [Integer] nsec
19
+ def initialize(sec, nsec)
20
+ end
21
+
22
+ # @example An unpacker implementation for the Time class
23
+ # lambda do |payload|
24
+ # tv = MessagePack::Timestamp.from_msgpack_ext(payload)
25
+ # Time.at(tv.sec, tv.nsec, :nanosecond)
26
+ # end
27
+ #
28
+ # @param [String] data
29
+ # @return [MessagePack::Timestamp]
30
+ def self.from_msgpack_ext(data)
31
+ end
32
+
33
+ # @example A packer implementation for the Time class
34
+ # unpacker = lambda do |time|
35
+ # MessagePack::Timestamp.to_msgpack_ext(time.tv_sec, time.tv_nsec)
36
+ # end
37
+ #
38
+ # @param [Integer] sec
39
+ # @param [Integer] nsec
40
+ # @return [String]
41
+ def self.to_msgpack_ext(sec, nsec)
42
+ end
43
+ end
44
+ end
@@ -179,6 +179,10 @@ public class Buffer extends RubyObject {
179
179
  return skipCommon(ctx, length, true);
180
180
  }
181
181
 
182
+ public boolean hasIo() {
183
+ return io != null;
184
+ }
185
+
182
186
  @JRubyMethod(name = "to_s", alias = {"to_str"})
183
187
  public IRubyObject toS(ThreadContext ctx) {
184
188
  ensureReadMode();
@@ -3,9 +3,11 @@ package org.msgpack.jruby;
3
3
 
4
4
  import java.math.BigInteger;
5
5
  import java.nio.ByteBuffer;
6
+ import java.util.Arrays;
6
7
 
7
8
  import org.jruby.Ruby;
8
9
  import org.jruby.RubyObject;
10
+ import org.jruby.RubyModule;
9
11
  import org.jruby.RubyNil;
10
12
  import org.jruby.RubyBoolean;
11
13
  import org.jruby.RubyNumeric;
@@ -37,15 +39,18 @@ public class Encoder {
37
39
  private final boolean compatibilityMode;
38
40
  private final ExtensionRegistry registry;
39
41
 
42
+ public boolean hasSymbolExtType;
43
+
40
44
  private ByteBuffer buffer;
41
45
 
42
- public Encoder(Ruby runtime, boolean compatibilityMode, ExtensionRegistry registry) {
46
+ public Encoder(Ruby runtime, boolean compatibilityMode, ExtensionRegistry registry, boolean hasSymbolExtType) {
43
47
  this.runtime = runtime;
44
48
  this.buffer = ByteBuffer.allocate(CACHE_LINE_SIZE - ARRAY_HEADER_SIZE);
45
49
  this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
46
50
  this.utf8Encoding = UTF8Encoding.INSTANCE;
47
51
  this.compatibilityMode = compatibilityMode;
48
52
  this.registry = registry;
53
+ this.hasSymbolExtType = hasSymbolExtType;
49
54
  }
50
55
 
51
56
  public boolean isCompatibilityMode() {
@@ -86,6 +91,11 @@ public class Encoder {
86
91
  return readRubyString();
87
92
  }
88
93
 
94
+ public IRubyObject encodeBinHeader(int size) {
95
+ appendStringHeader(size, true);
96
+ return readRubyString();
97
+ }
98
+
89
99
  public IRubyObject encodeFloat32(RubyNumeric numeric) {
90
100
  appendFloat32(numeric);
91
101
  return readRubyString();
@@ -111,7 +121,11 @@ public class Encoder {
111
121
  } else if (object instanceof RubyString) {
112
122
  appendString((RubyString) object);
113
123
  } else if (object instanceof RubySymbol) {
114
- appendString(((RubySymbol) object).asString());
124
+ if (hasSymbolExtType) {
125
+ appendOther(object, destination);
126
+ } else {
127
+ appendString(((RubySymbol) object).asString());
128
+ }
115
129
  } else if (object instanceof RubyArray) {
116
130
  appendArray((RubyArray) object);
117
131
  } else if (object instanceof RubyHash) {
@@ -124,14 +138,18 @@ public class Encoder {
124
138
  }
125
139
 
126
140
  private void appendBignum(RubyBignum object) {
127
- BigInteger value = ((RubyBignum) object).getBigIntegerValue();
128
- if (value.bitLength() > 64 || (value.bitLength() > 63 && value.signum() < 0)) {
129
- throw runtime.newArgumentError(String.format("Cannot pack big integer: %s", value));
141
+ BigInteger value = object.getBigIntegerValue();
142
+ if (value.compareTo(RubyBignum.LONG_MIN) < 0 || value.compareTo(RubyBignum.LONG_MAX) > 0) {
143
+ if (value.bitLength() > 64 || (value.bitLength() > 63 && value.signum() < 0)) {
144
+ throw runtime.newArgumentError(String.format("Cannot pack big integer: %s", value));
145
+ }
146
+ ensureRemainingCapacity(9);
147
+ buffer.put(value.signum() < 0 ? INT64 : UINT64);
148
+ byte[] b = value.toByteArray();
149
+ buffer.put(b, b.length - 8, 8);
150
+ } else {
151
+ appendInteger(object);
130
152
  }
131
- ensureRemainingCapacity(9);
132
- buffer.put(value.signum() < 0 ? INT64 : UINT64);
133
- byte[] b = value.toByteArray();
134
- buffer.put(b, b.length - 8, 8);
135
153
  }
136
154
 
137
155
  private void appendInteger(RubyInteger object) {
@@ -208,14 +226,7 @@ public class Encoder {
208
226
  buffer.putFloat(value);
209
227
  }
210
228
 
211
- private void appendString(RubyString object) {
212
- Encoding encoding = object.getEncoding();
213
- boolean binary = !compatibilityMode && encoding == binaryEncoding;
214
- if (encoding != utf8Encoding && encoding != binaryEncoding) {
215
- object = (RubyString) ((RubyString) object).encode(runtime.getCurrentContext(), runtime.getEncodingService().getEncoding(utf8Encoding));
216
- }
217
- ByteList bytes = object.getByteList();
218
- int length = bytes.length();
229
+ private void appendStringHeader(int length, boolean binary) {
219
230
  if (length < 32 && !binary) {
220
231
  ensureRemainingCapacity(1 + length);
221
232
  buffer.put((byte) (length | FIXSTR));
@@ -232,6 +243,17 @@ public class Encoder {
232
243
  buffer.put(binary ? BIN32 : STR32);
233
244
  buffer.putInt((int) length);
234
245
  }
246
+ }
247
+
248
+ private void appendString(RubyString object) {
249
+ Encoding encoding = object.getEncoding();
250
+ boolean binary = !compatibilityMode && encoding == binaryEncoding;
251
+ if (encoding != utf8Encoding && encoding != binaryEncoding) {
252
+ object = (RubyString) ((RubyString) object).encode(runtime.getCurrentContext(), runtime.getEncodingService().getEncoding(utf8Encoding));
253
+ }
254
+ ByteList bytes = object.getByteList();
255
+ int length = bytes.length();
256
+ appendStringHeader(length, binary);
235
257
  buffer.put(bytes.unsafeBytes(), bytes.begin(), length);
236
258
  }
237
259
 
@@ -363,7 +385,15 @@ public class Encoder {
363
385
 
364
386
  private void appendOther(IRubyObject object, IRubyObject destination) {
365
387
  if (registry != null) {
366
- IRubyObject[] pair = registry.lookupPackerByClass(object.getType());
388
+ RubyModule lookupClass;
389
+
390
+ if (object.getType() == runtime.getSymbol()) {
391
+ lookupClass = object.getType();
392
+ } else {
393
+ lookupClass = object.getSingletonClass();
394
+ }
395
+
396
+ IRubyObject[] pair = registry.lookupPackerForObject(object);
367
397
  if (pair != null) {
368
398
  RubyString bytes = pair[0].callMethod(runtime.getCurrentContext(), "call", object).asString();
369
399
  int type = (int) ((RubyFixnum) pair[1]).getLongValue();
@@ -3,8 +3,9 @@ package org.msgpack.jruby;
3
3
  import org.jruby.Ruby;
4
4
  import org.jruby.RubyHash;
5
5
  import org.jruby.RubyArray;
6
- import org.jruby.RubyClass;
6
+ import org.jruby.RubyModule;
7
7
  import org.jruby.RubyFixnum;
8
+ import org.jruby.RubySymbol;
8
9
  import org.jruby.runtime.ThreadContext;
9
10
  import org.jruby.runtime.builtin.IRubyObject;
10
11
 
@@ -12,19 +13,19 @@ import java.util.Map;
12
13
  import java.util.HashMap;
13
14
 
14
15
  public class ExtensionRegistry {
15
- private final Map<RubyClass, ExtensionEntry> extensionsByClass;
16
- private final Map<RubyClass, ExtensionEntry> extensionsByAncestor;
16
+ private final Map<RubyModule, ExtensionEntry> extensionsByModule;
17
+ private final Map<RubyModule, ExtensionEntry> extensionsByAncestor;
17
18
  private final ExtensionEntry[] extensionsByTypeId;
18
19
 
19
20
  public ExtensionRegistry() {
20
- this(new HashMap<RubyClass, ExtensionEntry>());
21
+ this(new HashMap<RubyModule, ExtensionEntry>());
21
22
  }
22
23
 
23
- private ExtensionRegistry(Map<RubyClass, ExtensionEntry> extensionsByClass) {
24
- this.extensionsByClass = new HashMap<RubyClass, ExtensionEntry>(extensionsByClass);
25
- this.extensionsByAncestor = new HashMap<RubyClass, ExtensionEntry>();
24
+ private ExtensionRegistry(Map<RubyModule, ExtensionEntry> extensionsByModule) {
25
+ this.extensionsByModule = new HashMap<RubyModule, ExtensionEntry>(extensionsByModule);
26
+ this.extensionsByAncestor = new HashMap<RubyModule, ExtensionEntry>();
26
27
  this.extensionsByTypeId = new ExtensionEntry[256];
27
- for (ExtensionEntry entry : extensionsByClass.values()) {
28
+ for (ExtensionEntry entry : extensionsByModule.values()) {
28
29
  if (entry.hasUnpacker()) {
29
30
  extensionsByTypeId[entry.getTypeId() + 128] = entry;
30
31
  }
@@ -32,15 +33,15 @@ public class ExtensionRegistry {
32
33
  }
33
34
 
34
35
  public ExtensionRegistry dup() {
35
- return new ExtensionRegistry(extensionsByClass);
36
+ return new ExtensionRegistry(extensionsByModule);
36
37
  }
37
38
 
38
39
  public IRubyObject toInternalPackerRegistry(ThreadContext ctx) {
39
40
  RubyHash hash = RubyHash.newHash(ctx.getRuntime());
40
- for (RubyClass extensionClass : extensionsByClass.keySet()) {
41
- ExtensionEntry entry = extensionsByClass.get(extensionClass);
41
+ for (RubyModule extensionModule : extensionsByModule.keySet()) {
42
+ ExtensionEntry entry = extensionsByModule.get(extensionModule);
42
43
  if (entry.hasPacker()) {
43
- hash.put(extensionClass, entry.toPackerTuple(ctx));
44
+ hash.put(extensionModule, entry.toPackerTuple(ctx));
44
45
  }
45
46
  }
46
47
  return hash;
@@ -58,9 +59,9 @@ public class ExtensionRegistry {
58
59
  return hash;
59
60
  }
60
61
 
61
- public void put(RubyClass cls, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
62
- ExtensionEntry entry = new ExtensionEntry(cls, typeId, packerProc, packerArg, unpackerProc, unpackerArg);
63
- extensionsByClass.put(cls, entry);
62
+ public void put(RubyModule mod, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
63
+ ExtensionEntry entry = new ExtensionEntry(mod, typeId, packerProc, packerArg, unpackerProc, unpackerArg);
64
+ extensionsByModule.put(mod, entry);
64
65
  extensionsByTypeId[typeId + 128] = entry;
65
66
  extensionsByAncestor.clear();
66
67
  }
@@ -74,45 +75,73 @@ public class ExtensionRegistry {
74
75
  }
75
76
  }
76
77
 
77
- public IRubyObject[] lookupPackerByClass(RubyClass cls) {
78
- ExtensionEntry e = extensionsByClass.get(cls);
79
- if (e == null) {
80
- e = extensionsByAncestor.get(cls);
78
+ public IRubyObject[] lookupPackerForObject(IRubyObject object) {
79
+ RubyModule lookupClass = null;
80
+ IRubyObject[] pair;
81
+ /*
82
+ * Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
83
+ * String have no singleton class and raise a TypeError when trying to get
84
+ * it.
85
+ *
86
+ * Since all but symbols are already filtered out when reaching this code
87
+ * only symbols are checked here.
88
+ */
89
+ if (!(object instanceof RubySymbol)) {
90
+ lookupClass = object.getSingletonClass();
91
+ pair = fetchEntryByModule(lookupClass);
92
+ if (pair != null) {
93
+ return pair;
94
+ }
95
+ }
96
+
97
+ pair = fetchEntryByModule(object.getType());
98
+ if (pair != null) {
99
+ return pair;
100
+ }
101
+
102
+ if (lookupClass == null) {
103
+ lookupClass = object.getType(); // only for Symbol
104
+ }
105
+ ExtensionEntry e = findEntryByModuleOrAncestor(lookupClass);
106
+ if (e != null && e.hasPacker()) {
107
+ extensionsByAncestor.put(e.getExtensionModule(), e);
108
+ return e.toPackerProcTypeIdPair(lookupClass.getRuntime().getCurrentContext());
81
109
  }
110
+ return null;
111
+ }
112
+
113
+ private IRubyObject[] fetchEntryByModule(final RubyModule mod) {
114
+ ExtensionEntry e = extensionsByModule.get(mod);
82
115
  if (e == null) {
83
- e = findEntryByClassOrAncestor(cls);
84
- if (e != null) {
85
- extensionsByAncestor.put(e.getExtensionClass(), e);
86
- }
116
+ e = extensionsByAncestor.get(mod);
87
117
  }
88
118
  if (e != null && e.hasPacker()) {
89
- return e.toPackerProcTypeIdPair(cls.getRuntime().getCurrentContext());
90
- } else {
91
- return null;
119
+ return e.toPackerProcTypeIdPair(mod.getRuntime().getCurrentContext());
92
120
  }
121
+ return null;
93
122
  }
94
123
 
95
- private ExtensionEntry findEntryByClassOrAncestor(final RubyClass cls) {
96
- ThreadContext ctx = cls.getRuntime().getCurrentContext();
97
- for (RubyClass extensionClass : extensionsByClass.keySet()) {
98
- RubyArray ancestors = (RubyArray) cls.callMethod(ctx, "ancestors");
99
- if (ancestors.callMethod(ctx, "include?", extensionClass).isTrue()) {
100
- return extensionsByClass.get(extensionClass);
124
+ private ExtensionEntry findEntryByModuleOrAncestor(final RubyModule mod) {
125
+ ThreadContext ctx = mod.getRuntime().getCurrentContext();
126
+ for (RubyModule extensionModule : extensionsByModule.keySet()) {
127
+ RubyArray ancestors = (RubyArray) mod.callMethod(ctx, "ancestors");
128
+ if (ancestors.callMethod(ctx, "include?", extensionModule).isTrue()) {
129
+ return extensionsByModule.get(extensionModule);
101
130
  }
102
131
  }
103
132
  return null;
104
133
  }
105
134
 
106
135
  private static class ExtensionEntry {
107
- private final RubyClass cls;
136
+ private final RubyModule mod;
108
137
  private final int typeId;
109
138
  private final IRubyObject packerProc;
110
139
  private final IRubyObject packerArg;
111
140
  private final IRubyObject unpackerProc;
112
141
  private final IRubyObject unpackerArg;
113
142
 
114
- public ExtensionEntry(RubyClass cls, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
115
- this.cls = cls;
143
+ public ExtensionEntry(RubyModule mod, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
144
+ this.mod = mod;
116
145
  this.typeId = typeId;
117
146
  this.packerProc = packerProc;
118
147
  this.packerArg = packerArg;
@@ -120,8 +149,8 @@ public class ExtensionRegistry {
120
149
  this.unpackerArg = unpackerArg;
121
150
  }
122
151
 
123
- public RubyClass getExtensionClass() {
124
- return cls;
152
+ public RubyModule getExtensionModule() {
153
+ return mod;
125
154
  }
126
155
 
127
156
  public int getTypeId() {
@@ -149,7 +178,7 @@ public class ExtensionRegistry {
149
178
  }
150
179
 
151
180
  public RubyArray toUnpackerTuple(ThreadContext ctx) {
152
- return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {cls, unpackerProc, unpackerArg});
181
+ return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {mod, unpackerProc, unpackerArg});
153
182
  }
154
183
 
155
184
  public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {