msgpack 0.7.0dev1-x86-mingw32 → 0.7.0-x86-mingw32

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd6035b0d75707751b69ca90c4c63f9a8ea89830
4
- data.tar.gz: badbbfc937ecc5b7f17f2f7121aa00bc2a96b50b
3
+ metadata.gz: 0d0e3d42a5abee5ed3099e8784636b4bcbf10731
4
+ data.tar.gz: f40232648f4ec2efa26b3874ebe3de519a2196e5
5
5
  SHA512:
6
- metadata.gz: a9a314193b1be2e3f4f28ce8a9b9a4548277785b1d4491e0c5622abdadbd7b455ffc6cffaac44570844a79e3b153fe68a4ec75cdb3de61916cc9cb441b23b93a
7
- data.tar.gz: 8453bf28dd958198d67365018897171b01d41642dca3c9c60162fe90576171243c675c7068ee8658b374c711f61ab52a8f3ae020ff622e480a7ce90266b0fabf
6
+ metadata.gz: a162332df41c000debc176cdd0d9cce9a67da29d2a20d3e7d9704d3726e541abf89be49517d36e9a4e8c9f6100bd811f793d1ba97e44f8de645bd4f1db50c497
7
+ data.tar.gz: 9cebb8ccc7f423f20c9784e01718e8ec098a7e3f00f4379ad208e3efddd71b48e275cd137f965e72b74f33067a5d730b3a191429eae4a1288da7cbb83250396f
data/.gitignore CHANGED
@@ -11,6 +11,7 @@ Gemfile*
11
11
  pkg
12
12
  test/debug.log
13
13
  *~
14
+ *.swp
14
15
  /rdoc
15
16
  tmp
16
17
  .classpath
@@ -24,3 +24,5 @@ matrix:
24
24
  allow_failures:
25
25
  - rvm: ruby-head
26
26
  - rvm: jruby-head
27
+ - rvm: jruby-19mode
28
+ os: osx
data/ChangeLog CHANGED
@@ -1,3 +1,11 @@
1
+ 2015-10-24 version 0.7.0:
2
+
3
+ * Add extention types support.
4
+ * Fix to share almost all test cases between CRuby and JRuby implementations.
5
+ * Fixed JRuby implementation to raise UnknownExtTypeError for unregistered ext type ids
6
+ instead to generate MessagePack::ExtensionValue instances.
7
+ (Specify `allow_unknown_ext: true` as unpacker option for v0.6.x behavior.)
8
+
1
9
  2015-07-22 version 0.6.2:
2
10
 
3
11
  * Fix release workflow: Ruby 2.1 and 2.2 are supported for Windows (2.0 is omitted)
@@ -36,7 +36,6 @@ or build msgpack-ruby and install:
36
36
  * Exchange objects between software components written in different languages
37
37
  * You'll need a flexible but efficient format so that components exchange objects while keeping compatibility
38
38
 
39
-
40
39
  = Portability
41
40
 
42
41
  MessagePack for Ruby should run on x86, ARM, PowerPC, SPARC and other CPU architectures.
@@ -92,6 +91,32 @@ or event-driven style which works well with EventMachine:
92
91
 
93
92
  See {API reference}[http://ruby.msgpack.org/MessagePack/Unpacker.html] for details.
94
93
 
94
+ = Extension Types
95
+
96
+ Packer and Unpacker support {Extension types of MessagePack}[https://github.com/msgpack/msgpack/blob/master/spec.md#types-extension-type].
97
+
98
+ # register how to serialize custom class at first
99
+ pk = MessagePack::Packer.new(io)
100
+ pk.register_type(0x01, MyClass1, :to_msgpack_ext) # equal to pk.register_type(0x01, MyClass)
101
+ pk.register_type(0x02, MyClass2){|obj| obj.how_to_serialize() } # blocks also available
102
+
103
+ # almost same API for unpacker
104
+ uk = MessagePack::Unpacker.new()
105
+ uk.register_type(0x01, MyClass1, :from_msgpack_ext)
106
+ uk.register_type(0x02){|data| MyClass2.create_from_serialized_data(data) }
107
+
108
+ MessagePack::Factory is to create packer and unpacker which have same extention types.
109
+
110
+ factory = MessagePack::Factory.new
111
+ factory.register_type(0x01, MyClass1) # same with next line
112
+ factory.register_type(0x01, MyClass1, packer: :to_msgpack_ext, unpacker: :from_msgpack_ext)
113
+ pk = factory.packer(options_for_packer)
114
+ uk = factory.unpacker(options_for_unpacker)
115
+
116
+ For *MessagePack.pack* and *MessagePack.unpack*, default packer/unpacker refer *MessagePack::DefaultFactory*. Call *MessagePack::DefaultFactory.register_type* to enable types process globally.
117
+
118
+ MessagePack::DefaultFactory.register_type(0x03, MyClass3)
119
+ MessagePack.unpack(data_with_ext_typeid_03) #=> MyClass3 instance
95
120
 
96
121
  = Buffer API
97
122
 
@@ -129,9 +154,18 @@ MessagePack mingw32/64 rubygems build process uses {rake-compiler-dock}[https://
129
154
 
130
155
  Once this step successes, target gems exist in pkg/msgpack-*-{x86,x64}-mingw32.gem.
131
156
 
157
+ == Updating documents
158
+
159
+ Online documents (http://ruby.msgpack.org) is generated from gh-pages branch.
160
+ Following commands update documents in gh-pages branch:
161
+
162
+ bundle exec rake doc
163
+ git checkout gh-pages
164
+ cp doc/* ./ -a
165
+
132
166
  = Copyright
133
167
 
134
168
  Author:: Sadayuki Furuhashi <frsyuki@gmail.com>
135
- Copyright:: Copyright (c) 2008-2013 Sadayuki Furuhashi
169
+ Copyright:: Copyright (c) 2008-2015 Sadayuki Furuhashi
136
170
  License:: Apache License, Version 2.0
137
171
 
@@ -12,6 +12,7 @@ import org.jruby.RubyObject;
12
12
  import org.jruby.RubyClass;
13
13
  import org.jruby.RubyBignum;
14
14
  import org.jruby.RubyString;
15
+ import org.jruby.RubyArray;
15
16
  import org.jruby.RubyHash;
16
17
  import org.jruby.exceptions.RaiseException;
17
18
  import org.jruby.runtime.builtin.IRubyObject;
@@ -29,33 +30,58 @@ public class Decoder implements Iterator<IRubyObject> {
29
30
  private final Encoding utf8Encoding;
30
31
  private final RubyClass unpackErrorClass;
31
32
  private final RubyClass underflowErrorClass;
33
+ private final RubyClass malformedFormatErrorClass;
34
+ private final RubyClass stackErrorClass;
32
35
  private final RubyClass unexpectedTypeErrorClass;
36
+ private final RubyClass unknownExtTypeErrorClass;
33
37
 
38
+ private ExtensionRegistry registry;
34
39
  private ByteBuffer buffer;
35
40
  private boolean symbolizeKeys;
41
+ private boolean allowUnknownExt;
36
42
 
37
43
  public Decoder(Ruby runtime) {
38
- this(runtime, new byte[] {}, 0, 0);
44
+ this(runtime, null, new byte[] {}, 0, 0, false, false);
45
+ }
46
+
47
+ public Decoder(Ruby runtime, ExtensionRegistry registry) {
48
+ this(runtime, registry, new byte[] {}, 0, 0, false, false);
39
49
  }
40
50
 
41
51
  public Decoder(Ruby runtime, byte[] bytes) {
42
- this(runtime, bytes, 0, bytes.length);
52
+ this(runtime, null, bytes, 0, bytes.length, false, false);
53
+ }
54
+
55
+ public Decoder(Ruby runtime, ExtensionRegistry registry, byte[] bytes) {
56
+ this(runtime, registry, bytes, 0, bytes.length, false, false);
57
+ }
58
+
59
+ public Decoder(Ruby runtime, ExtensionRegistry registry, byte[] bytes, boolean symbolizeKeys, boolean allowUnknownExt) {
60
+ this(runtime, registry, bytes, 0, bytes.length, symbolizeKeys, allowUnknownExt);
61
+ }
62
+
63
+ public Decoder(Ruby runtime, ExtensionRegistry registry, byte[] bytes, int offset, int length) {
64
+ this(runtime, registry, bytes, offset, length, false, false);
43
65
  }
44
66
 
45
- public Decoder(Ruby runtime, byte[] bytes, int offset, int length) {
67
+ public Decoder(Ruby runtime, ExtensionRegistry registry, byte[] bytes, int offset, int length, boolean symbolizeKeys, boolean allowUnknownExt) {
46
68
  this.runtime = runtime;
69
+ this.registry = registry;
70
+ this.symbolizeKeys = symbolizeKeys;
71
+ this.allowUnknownExt = allowUnknownExt;
47
72
  this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
48
73
  this.utf8Encoding = UTF8Encoding.INSTANCE;
49
74
  this.unpackErrorClass = runtime.getModule("MessagePack").getClass("UnpackError");
50
75
  this.underflowErrorClass = runtime.getModule("MessagePack").getClass("UnderflowError");
76
+ this.malformedFormatErrorClass = runtime.getModule("MessagePack").getClass("MalformedFormatError");
77
+ this.stackErrorClass = runtime.getModule("MessagePack").getClass("StackError");
51
78
  this.unexpectedTypeErrorClass = runtime.getModule("MessagePack").getClass("UnexpectedTypeError");
79
+ this.unknownExtTypeErrorClass = runtime.getModule("MessagePack").getClass("UnknownExtTypeError");
80
+ this.symbolizeKeys = symbolizeKeys;
81
+ this.allowUnknownExt = allowUnknownExt;
52
82
  feed(bytes, offset, length);
53
83
  }
54
84
 
55
- public void symbolizeKeys(boolean symbolize) {
56
- this.symbolizeKeys = symbolize;
57
- }
58
-
59
85
  public void feed(byte[] bytes) {
60
86
  feed(bytes, 0, bytes.length);
61
87
  }
@@ -73,7 +99,7 @@ public class Decoder implements Iterator<IRubyObject> {
73
99
  }
74
100
 
75
101
  public void reset() {
76
- buffer.rewind();
102
+ buffer = null;
77
103
  }
78
104
 
79
105
  public int offset() {
@@ -118,7 +144,20 @@ public class Decoder implements Iterator<IRubyObject> {
118
144
  private IRubyObject consumeExtension(int size) {
119
145
  int type = buffer.get();
120
146
  byte[] payload = readBytes(size);
121
- return ExtensionValue.newExtensionValue(runtime, type, payload);
147
+
148
+ if (registry != null) {
149
+ IRubyObject proc = registry.lookupUnpackerByTypeId(type);
150
+ if (proc != null) {
151
+ ByteList byteList = new ByteList(payload, runtime.getEncodingService().getAscii8bitEncoding());
152
+ return proc.callMethod(runtime.getCurrentContext(), "call", runtime.newString(byteList));
153
+ }
154
+ }
155
+
156
+ if (this.allowUnknownExt) {
157
+ return ExtensionValue.newExtensionValue(runtime, type, payload);
158
+ }
159
+
160
+ throw runtime.newRaiseException(unknownExtTypeErrorClass, "unexpected extension type");
122
161
  }
123
162
 
124
163
  private byte[] readBytes(int size) {
@@ -142,11 +181,11 @@ public class Decoder implements Iterator<IRubyObject> {
142
181
  try {
143
182
  byte b = buffer.get();
144
183
  if ((b & 0xf0) == 0x90) {
145
- return runtime.newFixnum(b & 0x0f);
184
+ return runtime.newFixnum(b & 0x0f);
146
185
  } else if (b == ARY16) {
147
- return runtime.newFixnum(buffer.getShort() & 0xffff);
186
+ return runtime.newFixnum(buffer.getShort() & 0xffff);
148
187
  } else if (b == ARY32) {
149
- return runtime.newFixnum(buffer.getInt());
188
+ return runtime.newFixnum(buffer.getInt());
150
189
  }
151
190
  throw runtime.newRaiseException(unexpectedTypeErrorClass, "unexpected type");
152
191
  } catch (RaiseException re) {
@@ -163,11 +202,11 @@ public class Decoder implements Iterator<IRubyObject> {
163
202
  try {
164
203
  byte b = buffer.get();
165
204
  if ((b & 0xf0) == 0x80) {
166
- return runtime.newFixnum(b & 0x0f);
205
+ return runtime.newFixnum(b & 0x0f);
167
206
  } else if (b == MAP16) {
168
- return runtime.newFixnum(buffer.getShort() & 0xffff);
207
+ return runtime.newFixnum(buffer.getShort() & 0xffff);
169
208
  } else if (b == MAP32) {
170
- return runtime.newFixnum(buffer.getInt());
209
+ return runtime.newFixnum(buffer.getInt());
171
210
  }
172
211
  throw runtime.newRaiseException(unexpectedTypeErrorClass, "unexpected type");
173
212
  } catch (RaiseException re) {
@@ -233,7 +272,7 @@ public class Decoder implements Iterator<IRubyObject> {
233
272
  default: return runtime.newFixnum(b);
234
273
  }
235
274
  buffer.position(position);
236
- throw runtime.newRaiseException(unpackErrorClass, "Illegal byte sequence");
275
+ throw runtime.newRaiseException(malformedFormatErrorClass, "Illegal byte sequence");
237
276
  } catch (RaiseException re) {
238
277
  buffer.position(position);
239
278
  throw re;
@@ -34,15 +34,21 @@ public class Encoder {
34
34
  private final Encoding binaryEncoding;
35
35
  private final Encoding utf8Encoding;
36
36
  private final boolean compatibilityMode;
37
+ private final ExtensionRegistry registry;
37
38
 
38
39
  private ByteBuffer buffer;
39
40
 
40
- public Encoder(Ruby runtime, boolean compatibilityMode) {
41
+ public Encoder(Ruby runtime, boolean compatibilityMode, ExtensionRegistry registry) {
41
42
  this.runtime = runtime;
42
43
  this.buffer = ByteBuffer.allocate(CACHE_LINE_SIZE - ARRAY_HEADER_SIZE);
43
44
  this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
44
45
  this.utf8Encoding = UTF8Encoding.INSTANCE;
45
46
  this.compatibilityMode = compatibilityMode;
47
+ this.registry = registry;
48
+ }
49
+
50
+ public boolean isCompatibilityMode() {
51
+ return compatibilityMode;
46
52
  }
47
53
 
48
54
  private void ensureRemainingCapacity(int c) {
@@ -107,7 +113,7 @@ public class Encoder {
107
113
  } else if (object instanceof ExtensionValue) {
108
114
  appendExtensionValue((ExtensionValue) object);
109
115
  } else {
110
- appendCustom(object, destination);
116
+ appendOther(object, destination);
111
117
  }
112
118
  }
113
119
 
@@ -295,12 +301,7 @@ public class Encoder {
295
301
  }
296
302
  }
297
303
 
298
- private void appendExtensionValue(ExtensionValue object) {
299
- long type = ((RubyFixnum)object.get_type()).getLongValue();
300
- if (type < -128 || type > 127) {
301
- throw object.getRuntime().newRangeError(String.format("integer %d too big to convert to `signed char'", type));
302
- }
303
- ByteList payloadBytes = ((RubyString)object.payload()).getByteList();
304
+ private void appendExt(int type, ByteList payloadBytes) {
304
305
  int payloadSize = payloadBytes.length();
305
306
  int outputSize = 0;
306
307
  boolean fixSize = payloadSize == 1 || payloadSize == 2 || payloadSize == 4 || payloadSize == 8 || payloadSize == 16;
@@ -338,6 +339,28 @@ public class Encoder {
338
339
  buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), payloadSize);
339
340
  }
340
341
 
342
+ private void appendExtensionValue(ExtensionValue object) {
343
+ long type = ((RubyFixnum)object.get_type()).getLongValue();
344
+ if (type < -128 || type > 127) {
345
+ throw object.getRuntime().newRangeError(String.format("integer %d too big to convert to `signed char'", type));
346
+ }
347
+ ByteList payloadBytes = ((RubyString)object.payload()).getByteList();
348
+ appendExt((int) type, payloadBytes);
349
+ }
350
+
351
+ private void appendOther(IRubyObject object, IRubyObject destination) {
352
+ if (registry != null) {
353
+ IRubyObject[] pair = registry.lookupPackerByClass(object.getType());
354
+ if (pair != null) {
355
+ RubyString bytes = pair[0].callMethod(runtime.getCurrentContext(), "call", object).asString();
356
+ int type = (int) ((RubyFixnum) pair[1]).getLongValue();
357
+ appendExt(type, bytes.getByteList());
358
+ return;
359
+ }
360
+ }
361
+ appendCustom(object, destination);
362
+ }
363
+
341
364
  private void appendCustom(IRubyObject object, IRubyObject destination) {
342
365
  if (destination == null) {
343
366
  IRubyObject result = object.callMethod(runtime.getCurrentContext(), "to_msgpack");
@@ -0,0 +1,159 @@
1
+ package org.msgpack.jruby;
2
+
3
+ import org.jruby.Ruby;
4
+ import org.jruby.RubyHash;
5
+ import org.jruby.RubyArray;
6
+ import org.jruby.RubyClass;
7
+ import org.jruby.RubyFixnum;
8
+ import org.jruby.runtime.ThreadContext;
9
+ import org.jruby.runtime.builtin.IRubyObject;
10
+
11
+ import java.util.Map;
12
+ import java.util.HashMap;
13
+
14
+ public class ExtensionRegistry {
15
+ private final Map<RubyClass, ExtensionEntry> extensionsByClass;
16
+ private final Map<RubyClass, ExtensionEntry> extensionsByAncestor;
17
+ private final ExtensionEntry[] extensionsByTypeId;
18
+
19
+ public ExtensionRegistry() {
20
+ this(new HashMap<RubyClass, ExtensionEntry>());
21
+ }
22
+
23
+ private ExtensionRegistry(Map<RubyClass, ExtensionEntry> extensionsByClass) {
24
+ this.extensionsByClass = new HashMap<RubyClass, ExtensionEntry>(extensionsByClass);
25
+ this.extensionsByAncestor = new HashMap<RubyClass, ExtensionEntry>();
26
+ this.extensionsByTypeId = new ExtensionEntry[256];
27
+ for (ExtensionEntry entry : extensionsByClass.values()) {
28
+ if (entry.hasUnpacker()) {
29
+ extensionsByTypeId[entry.getTypeId() + 128] = entry;
30
+ }
31
+ }
32
+ }
33
+
34
+ public ExtensionRegistry dup() {
35
+ return new ExtensionRegistry(extensionsByClass);
36
+ }
37
+
38
+ public IRubyObject toInternalPackerRegistry(ThreadContext ctx) {
39
+ RubyHash hash = RubyHash.newHash(ctx.getRuntime());
40
+ for (RubyClass extensionClass : extensionsByClass.keySet()) {
41
+ ExtensionEntry entry = extensionsByClass.get(extensionClass);
42
+ if (entry.hasPacker()) {
43
+ hash.put(extensionClass, entry.toPackerTuple(ctx));
44
+ }
45
+ }
46
+ return hash;
47
+ }
48
+
49
+ public IRubyObject toInternalUnpackerRegistry(ThreadContext ctx) {
50
+ RubyHash hash = RubyHash.newHash(ctx.getRuntime());
51
+ for (int typeIdIndex = 0 ; typeIdIndex < 256 ; typeIdIndex++) {
52
+ ExtensionEntry entry = extensionsByTypeId[typeIdIndex];
53
+ if (entry != null && entry.hasUnpacker()) {
54
+ IRubyObject typeId = RubyFixnum.newFixnum(ctx.getRuntime(), typeIdIndex - 128);
55
+ hash.put(typeId, entry.toUnpackerTuple(ctx));
56
+ }
57
+ }
58
+ return hash;
59
+ }
60
+
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);
64
+ extensionsByTypeId[typeId + 128] = entry;
65
+ extensionsByAncestor.clear();
66
+ }
67
+
68
+ public IRubyObject lookupUnpackerByTypeId(int typeId) {
69
+ ExtensionEntry e = extensionsByTypeId[typeId + 128];
70
+ if (e != null && e.hasUnpacker()) {
71
+ return e.getUnpackerProc();
72
+ } else {
73
+ return null;
74
+ }
75
+ }
76
+
77
+ public IRubyObject[] lookupPackerByClass(RubyClass cls) {
78
+ ExtensionEntry e = extensionsByClass.get(cls);
79
+ if (e == null) {
80
+ e = extensionsByAncestor.get(cls);
81
+ }
82
+ if (e == null) {
83
+ e = findEntryByClassOrAncestor(cls);
84
+ if (e != null) {
85
+ extensionsByAncestor.put(e.getExtensionClass(), e);
86
+ }
87
+ }
88
+ if (e != null && e.hasPacker()) {
89
+ return e.toPackerProcTypeIdPair(cls.getRuntime().getCurrentContext());
90
+ } else {
91
+ return null;
92
+ }
93
+ }
94
+
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);
101
+ }
102
+ }
103
+ return null;
104
+ }
105
+
106
+ private static class ExtensionEntry {
107
+ private final RubyClass cls;
108
+ private final int typeId;
109
+ private final IRubyObject packerProc;
110
+ private final IRubyObject packerArg;
111
+ private final IRubyObject unpackerProc;
112
+ private final IRubyObject unpackerArg;
113
+
114
+ public ExtensionEntry(RubyClass cls, int typeId, IRubyObject packerProc, IRubyObject packerArg, IRubyObject unpackerProc, IRubyObject unpackerArg) {
115
+ this.cls = cls;
116
+ this.typeId = typeId;
117
+ this.packerProc = packerProc;
118
+ this.packerArg = packerArg;
119
+ this.unpackerProc = unpackerProc;
120
+ this.unpackerArg = unpackerArg;
121
+ }
122
+
123
+ public RubyClass getExtensionClass() {
124
+ return cls;
125
+ }
126
+
127
+ public int getTypeId() {
128
+ return typeId;
129
+ }
130
+
131
+ public boolean hasPacker() {
132
+ return packerProc != null;
133
+ }
134
+
135
+ public boolean hasUnpacker() {
136
+ return unpackerProc != null;
137
+ }
138
+
139
+ public IRubyObject getPackerProc() {
140
+ return packerProc;
141
+ }
142
+
143
+ public IRubyObject getUnpackerProc() {
144
+ return unpackerProc;
145
+ }
146
+
147
+ public RubyArray toPackerTuple(ThreadContext ctx) {
148
+ return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {RubyFixnum.newFixnum(ctx.getRuntime(), typeId), packerProc, packerArg});
149
+ }
150
+
151
+ public RubyArray toUnpackerTuple(ThreadContext ctx) {
152
+ return RubyArray.newArray(ctx.getRuntime(), new IRubyObject[] {cls, unpackerProc, unpackerArg});
153
+ }
154
+
155
+ public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {
156
+ return new IRubyObject[] {packerProc, RubyFixnum.newFixnum(ctx.getRuntime(), typeId)};
157
+ }
158
+ }
159
+ }