msgpack 0.7.4 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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) {