msgpack 0.6.2 → 0.7.0dev1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +33 -0
  3. data/README.rdoc +2 -6
  4. data/Rakefile +9 -0
  5. data/appveyor.yml +18 -0
  6. data/doclib/msgpack/error.rb +6 -1
  7. data/doclib/msgpack/extension_value.rb +9 -0
  8. data/doclib/msgpack/factory.rb +68 -0
  9. data/doclib/msgpack/packer.rb +38 -0
  10. data/doclib/msgpack/unpacker.rb +39 -2
  11. data/ext/java/org/msgpack/jruby/Buffer.java +4 -0
  12. data/ext/java/org/msgpack/jruby/Decoder.java +44 -0
  13. data/ext/java/org/msgpack/jruby/Encoder.java +46 -4
  14. data/ext/java/org/msgpack/jruby/ExtensionValue.java +55 -60
  15. data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +18 -5
  16. data/ext/java/org/msgpack/jruby/Packer.java +17 -4
  17. data/ext/java/org/msgpack/jruby/Unpacker.java +59 -2
  18. data/ext/msgpack/buffer_class.c +2 -2
  19. data/ext/msgpack/buffer_class.h +1 -1
  20. data/ext/msgpack/compat.h +12 -0
  21. data/ext/msgpack/core_ext.c +15 -0
  22. data/ext/msgpack/extconf.rb +4 -1
  23. data/ext/msgpack/extension_value_class.c +34 -0
  24. data/ext/msgpack/extension_value_class.h +31 -0
  25. data/ext/msgpack/factory_class.c +213 -0
  26. data/ext/msgpack/factory_class.h +35 -0
  27. data/ext/msgpack/packer.c +14 -7
  28. data/ext/msgpack/packer.h +46 -8
  29. data/ext/msgpack/packer_class.c +92 -45
  30. data/ext/msgpack/packer_class.h +4 -2
  31. data/ext/msgpack/packer_ext_registry.c +87 -0
  32. data/ext/msgpack/packer_ext_registry.h +101 -0
  33. data/ext/msgpack/rbinit.c +4 -0
  34. data/ext/msgpack/unpacker.c +128 -23
  35. data/ext/msgpack/unpacker.h +11 -0
  36. data/ext/msgpack/unpacker_class.c +117 -38
  37. data/ext/msgpack/unpacker_class.h +4 -2
  38. data/ext/msgpack/unpacker_ext_registry.c +68 -0
  39. data/ext/msgpack/unpacker_ext_registry.h +62 -0
  40. data/lib/msgpack.rb +4 -0
  41. data/lib/msgpack/factory.rb +60 -0
  42. data/lib/msgpack/packer.rb +28 -0
  43. data/lib/msgpack/unpacker.rb +28 -0
  44. data/lib/msgpack/version.rb +1 -1
  45. data/msgpack.gemspec +4 -3
  46. data/spec/cruby/buffer_io_spec.rb +2 -3
  47. data/spec/cruby/buffer_spec.rb +1 -3
  48. data/spec/cruby/unpacker_spec.rb +14 -2
  49. data/spec/ext_value_spec.rb +99 -0
  50. data/spec/exttypes.rb +51 -0
  51. data/spec/factory_spec.rb +236 -0
  52. data/spec/jruby/msgpack/unpacker_spec.rb +25 -0
  53. data/spec/{jruby/msgpack_spec.rb → msgpack_spec.rb} +1 -1
  54. data/spec/pack_spec.rb +0 -6
  55. data/spec/packer_spec.rb +95 -0
  56. data/spec/spec_helper.rb +12 -1
  57. data/spec/unpack_spec.rb +1 -4
  58. data/spec/unpacker_spec.rb +133 -0
  59. metadata +53 -15
  60. data/Dockerfile +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 504d2e79f6495ca1e39421dc878ec2108f317fc5
4
- data.tar.gz: b433d02ec1d26ac55341af24c04384b5e8442dee
3
+ metadata.gz: e934ddd7840719b64ca248c14b5cb3e81ed4c0fd
4
+ data.tar.gz: 2bd6ef14c3c873241be2911fe0666dc5526e9351
5
5
  SHA512:
6
- metadata.gz: 45aaa1839c144714fc3efed75acf446e01f455a20010c92951fba275f27cd652319cd444b2a18eb59ffcd11e5d328fad133d410f4087f7ceb9fad7f60145be04
7
- data.tar.gz: b9320514ce04bda3cd8f7ffd344a32251db8ccdef7ea8d81c39a044a0b89f55e3536f6e122b7e4f7e580a227bbadd52f4fcf56de3c4d597fa6d3d1858f4b6b27
6
+ metadata.gz: 857b591765e1b4bb0a0efac427e729e278168eee8bdfdd47bc9b1a86f30edfdecedc4a81626709da5d21fb25988485c243532d3d87d9c3cde1b9a47c30c2624b
7
+ data.tar.gz: a616c639a3c3cc8029d1bc93d8821f60ad85799995016e7cf579a0875380de21b598a0dbad608db728fc8301ce993453db1d7605ae189e51af2aa04f2e712624
@@ -0,0 +1,33 @@
1
+ # This configuration was generated by `rubocop --auto-gen-config`
2
+ # on 2015-03-09 17:42:55 +0100 using RuboCop version 0.29.1.
3
+ # The point is for the user to remove these configuration records
4
+ # one by one as the offenses are removed from the code base.
5
+ # Note that changes in the inspected code, or installation of new
6
+ # versions of RuboCop, may require this file to be generated again.
7
+
8
+ # Offense count: 3
9
+ Lint/AmbiguousOperator:
10
+ Enabled: false
11
+
12
+ # Offense count: 1
13
+ # Configuration parameters: AllowSafeAssignment.
14
+ Lint/AssignmentInCondition:
15
+ Enabled: false
16
+
17
+ # Offense count: 1
18
+ Lint/Eval:
19
+ Enabled: false
20
+
21
+ # Offense count: 3
22
+ # Cop supports --auto-correct.
23
+ Lint/UnusedBlockArgument:
24
+ Enabled: false
25
+
26
+ # Offense count: 35
27
+ # Cop supports --auto-correct.
28
+ Lint/UnusedMethodArgument:
29
+ Enabled: false
30
+
31
+ # Offense count: 128
32
+ Lint/Void:
33
+ Enabled: false
@@ -123,16 +123,12 @@ Then, you can run the tasks as follows:
123
123
 
124
124
  == How to build -mingw32 rubygems
125
125
 
126
- MessagePack mingw32/64 rubygems build process uses {Docker}[https://docs.docker.com/].
126
+ MessagePack mingw32/64 rubygems build process uses {rake-compiler-dock}[https://github.com/rake-compiler/rake-compiler-dock]. Run:
127
127
 
128
- Set up docker environment at first, and then run docker container to build gems, with shared directory "pkg".
129
-
130
- docker run -it --rm -v `pwd`/pkg:/home/ubuntu/msgpack-ruby/pkg msgpack/msgpack-rubygem-crosscompile
128
+ rake build:windows
131
129
 
132
130
  Once this step successes, target gems exist in pkg/msgpack-*-{x86,x64}-mingw32.gem.
133
131
 
134
- See also: https://registry.hub.docker.com/u/msgpack/msgpack-rubygem-crosscompile/
135
-
136
132
  = Copyright
137
133
 
138
134
  Author:: Sadayuki Furuhashi <frsyuki@gmail.com>
data/Rakefile CHANGED
@@ -52,6 +52,7 @@ else
52
52
  ext.ext_dir = 'ext/msgpack'
53
53
  ext.cross_compile = true
54
54
  ext.lib_dir = File.join(*['lib', 'msgpack', ENV['FAT_DIR']].compact)
55
+ # cross_platform names are of MRI's platform name
55
56
  ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
56
57
  end
57
58
 
@@ -63,6 +64,14 @@ else
63
64
  end
64
65
  end
65
66
 
67
+ namespace :build do
68
+ desc 'Build gems for Windows per rake-compiler-dock'
69
+ task :windows do
70
+ require 'rake_compiler_dock'
71
+ RakeCompilerDock.sh 'bundle && rake cross native gem RUBY_CC_VERSION=1.9.3:2.0.0:2.1.6:2.2.2'
72
+ end
73
+ end
74
+
66
75
  CLEAN.include('lib/msgpack/msgpack.*')
67
76
 
68
77
  task :default => [:spec, :build, :doc]
@@ -0,0 +1,18 @@
1
+ ---
2
+ install:
3
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
4
+ - ruby --version
5
+ - gem --version
6
+ - bundle install
7
+ build: off
8
+ test_script:
9
+ - bundle exec rake -rdevkit
10
+
11
+ environment:
12
+ matrix:
13
+ - ruby_version: "200"
14
+ - ruby_version: "200-x64"
15
+ - ruby_version: "21"
16
+ - ruby_version: "21-x64"
17
+ - ruby_version: "22"
18
+ - ruby_version: "22-x64"
@@ -9,6 +9,11 @@ module MessagePack
9
9
  class StackError < UnpackError
10
10
  end
11
11
 
12
- class TypeError < StandardError
12
+ class UnexpectedTypeError < UnpackError
13
+ include TypeError
14
+ end
15
+
16
+ class UnknownExtTypeError < UnpackError
17
+ include TypeError
13
18
  end
14
19
  end
@@ -0,0 +1,9 @@
1
+ module MessagePack
2
+
3
+ #
4
+ # MessagePack::ExtensionValue is a struct to represent unknown ext type object.
5
+ # Its contents are accessed by type and payload (messagepack bytes representation) methods.
6
+ # And it is extended to add to_msgpack object.
7
+ #
8
+ ExtensionValue = Struct.new(:type, :payload)
9
+ end
@@ -0,0 +1,68 @@
1
+ module MessagePack
2
+ #
3
+ # MessagePack::Factory is a class to generate Packer and Unpacker which has
4
+ # same set of ext types.
5
+ #
6
+ class Factory
7
+ #
8
+ # Creates a MessagePack::Factory instance
9
+ #
10
+ def initialize
11
+ end
12
+
13
+ #
14
+ # Creates a MessagePack::Packer instance, which has ext types already registered.
15
+ # Options are passed to MessagePack::Packer#initialized.
16
+ #
17
+ # See also Packer#initialize for options.
18
+ #
19
+ def packer(*args)
20
+ end
21
+
22
+ #
23
+ # Creates a MessagePack::Unpacker instance, which has ext types already registered.
24
+ # Options are passed to MessagePack::Unpacker#initialized.
25
+ #
26
+ # See also Unpacker#initialize for options.
27
+ #
28
+ def unpacker(*args)
29
+ end
30
+
31
+ #
32
+ # Register a type and Class to be registered for packer and/or unpacker.
33
+ # If options are not speicified, factory will use :to_msgpack_ext for packer, and
34
+ # :from_msgpack_ext for unpacker.
35
+ #
36
+ # @param type [Fixnum] type id of registered Class (0-127)
37
+ # @param klass [Class] Class to be associated with type id
38
+ # @param options [Hash] specify method name or Proc which are used by packer/unpacker
39
+ # @return nil
40
+ #
41
+ # Supported options:
42
+ #
43
+ # * *:packer* specify symbol or proc object for packer
44
+ # * *:unpacker* specify symbol or proc object for unpacker
45
+ #
46
+ def register_type(type, klass, options={})
47
+ end
48
+
49
+ #
50
+ # Returns a list of registered types, ordered by type id.
51
+ #
52
+ # @param selector [Symbol] specify to list types registered for :packer, :unpacker or :both (default)
53
+ # @return Array
54
+ #
55
+ def registered_types(selector=:both)
56
+ end
57
+
58
+ #
59
+ # Returns true/false which indicate specified class or type id is registered or not.
60
+ #
61
+ # @param klass_or_type [Class or Fixnum] Class or type id (0-127) to be checked
62
+ # @param selector [Symbol] specify to check for :packer, :unpacker or :both (default)
63
+ # @return true or false
64
+ #
65
+ def type_registered?(klass_or_type, selector=:both)
66
+ end
67
+ end
68
+ end
@@ -26,6 +26,44 @@ module MessagePack
26
26
  def initialize(*args)
27
27
  end
28
28
 
29
+ #
30
+ # Register a new ext type to serialize it. This method should be called with one of
31
+ # method name or block, which returns bytes(ASCII-8BIT String) representation of
32
+ # object to be serialized.
33
+ #
34
+ # @overload register_type(type, klass, &block)
35
+ # @param type [Fixnum] type id (0-127) user defined type id for specified Class
36
+ # @param klass [Class] Class to be serialized with speicifed type id
37
+ # @yieldparam object [Object] object to be serialized
38
+ #
39
+ # @overload register_type(type, klass, method_name)
40
+ # @param type [Fixnum] type id (0-127) user defined type id for specified Class
41
+ # @param klass [Class] Class to be serialized with speicifed type id
42
+ # @param method_name [Symbol] method which returns bytes of serialized representation
43
+ #
44
+ # @return nil
45
+ #
46
+ def register_type(type, klass, method_name, &block)
47
+ end
48
+
49
+ #
50
+ # Returns a list of registered types, ordered by type id.
51
+ # Each element is a Hash object includes keys :type, :class and :packer.
52
+ #
53
+ # @return Array
54
+ #
55
+ def registered_types
56
+ end
57
+
58
+ #
59
+ # Returns true/false which indicate specified class or type id is registered or not.
60
+ #
61
+ # @param klass_or_type [Class or Fixnum] Class or type id (0-127) to be checked
62
+ # @return true or false
63
+ #
64
+ def type_registered?(klass_or_type)
65
+ end
66
+
29
67
  #
30
68
  # Internal buffer
31
69
  #
@@ -19,12 +19,49 @@ module MessagePack
19
19
  # Supported options:
20
20
  #
21
21
  # * *:symbolize_keys* deserialize keys of Hash objects as Symbol instead of String
22
+ # * *:allow_unknown_ext* allow to deserialize ext type object with unknown type id as ExtensionValue instance. Otherwise (by default), unpacker throws UnknownExtTypeError.
22
23
  #
23
24
  # See also Buffer#initialize for other options.
24
25
  #
25
26
  def initialize(*args)
26
27
  end
27
28
 
29
+ #
30
+ # Register a new ext type to deserialize it. This method should be called with
31
+ # Class and its class method name, or block, which returns a instance object.
32
+ #
33
+ # @overload register_type(type, &block)
34
+ # @param type [Fixnum] type id (0-127) user defined type id for specified deserializer block
35
+ # @yieldparam data [String] bytes(ASCII-8BIT String) represents serialized object, to be deserialized
36
+ #
37
+ # @overload register_type(type, klass, class_method_name)
38
+ # @param type [Fixnum] type id (0-127) user defined type id for specified Class
39
+ # @param klass [Class] Class to be serialized with speicifed type id
40
+ # @param class_method_name [Symbol] class method which returns an instance object
41
+ #
42
+ # @return nil
43
+ #
44
+ def register_type(type, klass, method_name, &block)
45
+ end
46
+
47
+ #
48
+ # Returns a list of registered types, ordered by type id.
49
+ # Each element is a Hash object includes keys :type, :class and :unpacker.
50
+ #
51
+ # @return Array
52
+ #
53
+ def registered_types
54
+ end
55
+
56
+ #
57
+ # Returns true/false which indicate specified class or type id is registered or not.
58
+ #
59
+ # @param klass_or_type [Class or Fixnum] Class or type id (0-127) to be checked
60
+ # @return true or false
61
+ #
62
+ def type_registered?(klass_or_type)
63
+ end
64
+
28
65
  #
29
66
  # Internal buffer
30
67
  #
@@ -77,7 +114,7 @@ module MessagePack
77
114
  # Read a header of an array and returns its size.
78
115
  # It converts a serialized array into a stream of elements.
79
116
  #
80
- # If the serialized object is not an array, it raises MessagePack::TypeError.
117
+ # If the serialized object is not an array, it raises MessagePack::UnexpectedTypeError.
81
118
  # If there're not enough data, this method raises EOFError.
82
119
  #
83
120
  # @return [Integer] size of the array
@@ -89,7 +126,7 @@ module MessagePack
89
126
  # Reads a header of an map and returns its size.
90
127
  # It converts a serialized map into a stream of key-value pairs.
91
128
  #
92
- # If the serialized object is not a map, it raises MessagePack::TypeError.
129
+ # If the serialized object is not a map, it raises MessagePack::UnexpectedTypeError.
93
130
  # If there're not enough data, this method raises EOFError.
94
131
  #
95
132
  # @return [Integer] size of the map
@@ -81,6 +81,10 @@ public class Buffer extends RubyObject {
81
81
 
82
82
  @JRubyMethod(name = "clear")
83
83
  public IRubyObject clear(ThreadContext ctx) {
84
+ if (!writeMode) {
85
+ buffer.compact();
86
+ writeMode = true;
87
+ }
84
88
  buffer.clear();
85
89
  return ctx.getRuntime().getNil();
86
90
  }
@@ -29,6 +29,7 @@ public class Decoder implements Iterator<IRubyObject> {
29
29
  private final Encoding utf8Encoding;
30
30
  private final RubyClass unpackErrorClass;
31
31
  private final RubyClass underflowErrorClass;
32
+ private final RubyClass unexpectedTypeErrorClass;
32
33
 
33
34
  private ByteBuffer buffer;
34
35
  private boolean symbolizeKeys;
@@ -47,6 +48,7 @@ public class Decoder implements Iterator<IRubyObject> {
47
48
  this.utf8Encoding = UTF8Encoding.INSTANCE;
48
49
  this.unpackErrorClass = runtime.getModule("MessagePack").getClass("UnpackError");
49
50
  this.underflowErrorClass = runtime.getModule("MessagePack").getClass("UnderflowError");
51
+ this.unexpectedTypeErrorClass = runtime.getModule("MessagePack").getClass("UnexpectedTypeError");
50
52
  feed(bytes, offset, length);
51
53
  }
52
54
 
@@ -135,6 +137,48 @@ public class Decoder implements Iterator<IRubyObject> {
135
137
  return buffer.remaining() > 0;
136
138
  }
137
139
 
140
+ public IRubyObject read_array_header() {
141
+ int position = buffer.position();
142
+ try {
143
+ byte b = buffer.get();
144
+ if ((b & 0xf0) == 0x90) {
145
+ return runtime.newFixnum(b & 0x0f);
146
+ } else if (b == ARY16) {
147
+ return runtime.newFixnum(buffer.getShort() & 0xffff);
148
+ } else if (b == ARY32) {
149
+ return runtime.newFixnum(buffer.getInt());
150
+ }
151
+ throw runtime.newRaiseException(unexpectedTypeErrorClass, "unexpected type");
152
+ } catch (RaiseException re) {
153
+ buffer.position(position);
154
+ throw re;
155
+ } catch (BufferUnderflowException bue) {
156
+ buffer.position(position);
157
+ throw runtime.newRaiseException(underflowErrorClass, "Not enough bytes available");
158
+ }
159
+ }
160
+
161
+ public IRubyObject read_map_header() {
162
+ int position = buffer.position();
163
+ try {
164
+ byte b = buffer.get();
165
+ if ((b & 0xf0) == 0x80) {
166
+ return runtime.newFixnum(b & 0x0f);
167
+ } else if (b == MAP16) {
168
+ return runtime.newFixnum(buffer.getShort() & 0xffff);
169
+ } else if (b == MAP32) {
170
+ return runtime.newFixnum(buffer.getInt());
171
+ }
172
+ throw runtime.newRaiseException(unexpectedTypeErrorClass, "unexpected type");
173
+ } catch (RaiseException re) {
174
+ buffer.position(position);
175
+ throw re;
176
+ } catch (BufferUnderflowException bue) {
177
+ buffer.position(position);
178
+ throw runtime.newRaiseException(underflowErrorClass, "Not enough bytes available");
179
+ }
180
+ }
181
+
138
182
  @Override
139
183
  public IRubyObject next() {
140
184
  int position = buffer.position();
@@ -25,7 +25,6 @@ import org.jcodings.specific.UTF8Encoding;
25
25
 
26
26
  import static org.msgpack.jruby.Types.*;
27
27
 
28
-
29
28
  public class Encoder {
30
29
 
31
30
  private static final int CACHE_LINE_SIZE = 64;
@@ -105,10 +104,10 @@ public class Encoder {
105
104
  appendArray((RubyArray) object);
106
105
  } else if (object instanceof RubyHash) {
107
106
  appendHash((RubyHash) object);
108
- } else if (object.respondsTo("to_msgpack")) {
109
- appendCustom(object, destination);
107
+ } else if (object instanceof ExtensionValue) {
108
+ appendExtensionValue((ExtensionValue) object);
110
109
  } else {
111
- throw runtime.newArgumentError(String.format("Cannot pack type: %s", object.getClass().getName()));
110
+ appendCustom(object, destination);
112
111
  }
113
112
  }
114
113
 
@@ -296,6 +295,49 @@ public class Encoder {
296
295
  }
297
296
  }
298
297
 
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
+ int payloadSize = payloadBytes.length();
305
+ int outputSize = 0;
306
+ boolean fixSize = payloadSize == 1 || payloadSize == 2 || payloadSize == 4 || payloadSize == 8 || payloadSize == 16;
307
+ if (fixSize) {
308
+ outputSize = 2 + payloadSize;
309
+ } else if (payloadSize < 0x100) {
310
+ outputSize = 3 + payloadSize;
311
+ } else if (payloadSize < 0x10000) {
312
+ outputSize = 4 + payloadSize;
313
+ } else {
314
+ outputSize = 6 + payloadSize;
315
+ }
316
+ ensureRemainingCapacity(outputSize);
317
+ if (payloadSize == 1) {
318
+ buffer.put(FIXEXT1);
319
+ } else if (payloadSize == 2) {
320
+ buffer.put(FIXEXT2);
321
+ } else if (payloadSize == 4) {
322
+ buffer.put(FIXEXT4);
323
+ } else if (payloadSize == 8) {
324
+ buffer.put(FIXEXT8);
325
+ } else if (payloadSize == 16) {
326
+ buffer.put(FIXEXT16);
327
+ } else if (payloadSize < 0x100) {
328
+ buffer.put(VAREXT8);
329
+ buffer.put((byte) payloadSize);
330
+ } else if (payloadSize < 0x10000) {
331
+ buffer.put(VAREXT16);
332
+ buffer.putShort((short) payloadSize);
333
+ } else {
334
+ buffer.put(VAREXT32);
335
+ buffer.putInt(payloadSize);
336
+ }
337
+ buffer.put((byte) type);
338
+ buffer.put(payloadBytes.unsafeBytes(), payloadBytes.begin(), payloadSize);
339
+ }
340
+
299
341
  private void appendCustom(IRubyObject object, IRubyObject destination) {
300
342
  if (destination == null) {
301
343
  IRubyObject result = object.callMethod(runtime.getCurrentContext(), "to_msgpack");