msgpack 1.3.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/.gitignore +3 -1
  4. data/.rubocop.yml +2 -2
  5. data/ChangeLog +86 -0
  6. data/Gemfile +3 -0
  7. data/README.md +266 -0
  8. data/Rakefile +1 -9
  9. data/bench/bench.rb +78 -0
  10. data/bin/console +8 -0
  11. data/doclib/msgpack/factory.rb +47 -3
  12. data/doclib/msgpack/packer.rb +5 -4
  13. data/doclib/msgpack/time.rb +1 -1
  14. data/doclib/msgpack/unpacker.rb +2 -2
  15. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  16. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  17. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  18. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  19. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  20. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  21. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  22. data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
  23. data/ext/msgpack/buffer.c +42 -68
  24. data/ext/msgpack/buffer.h +59 -14
  25. data/ext/msgpack/buffer_class.c +90 -52
  26. data/ext/msgpack/compat.h +1 -111
  27. data/ext/msgpack/extconf.rb +45 -19
  28. data/ext/msgpack/factory_class.c +133 -43
  29. data/ext/msgpack/packer.c +60 -36
  30. data/ext/msgpack/packer.h +27 -25
  31. data/ext/msgpack/packer_class.c +84 -77
  32. data/ext/msgpack/packer_class.h +11 -0
  33. data/ext/msgpack/packer_ext_registry.c +24 -32
  34. data/ext/msgpack/packer_ext_registry.h +40 -33
  35. data/ext/msgpack/sysdep.h +5 -2
  36. data/ext/msgpack/unpacker.c +132 -115
  37. data/ext/msgpack/unpacker.h +23 -10
  38. data/ext/msgpack/unpacker_class.c +83 -81
  39. data/ext/msgpack/unpacker_class.h +11 -0
  40. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  41. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  42. data/lib/msgpack/bigint.rb +69 -0
  43. data/lib/msgpack/factory.rb +103 -0
  44. data/lib/msgpack/symbol.rb +21 -4
  45. data/lib/msgpack/time.rb +1 -1
  46. data/lib/msgpack/timestamp.rb +1 -1
  47. data/lib/msgpack/version.rb +4 -7
  48. data/lib/msgpack.rb +6 -12
  49. data/msgpack.gemspec +4 -7
  50. data/spec/bigint_spec.rb +26 -0
  51. data/spec/cruby/buffer_spec.rb +17 -0
  52. data/spec/factory_spec.rb +351 -12
  53. data/spec/msgpack_spec.rb +1 -1
  54. data/spec/packer_spec.rb +18 -0
  55. data/spec/spec_helper.rb +37 -3
  56. data/spec/timestamp_spec.rb +42 -0
  57. data/spec/unpacker_spec.rb +157 -4
  58. metadata +32 -62
  59. data/.travis.yml +0 -43
  60. data/README.rdoc +0 -225
  61. data/bench/pack.rb +0 -23
  62. data/bench/pack_log.rb +0 -33
  63. data/bench/pack_log_long.rb +0 -65
  64. data/bench/pack_symbols.rb +0 -28
  65. data/bench/run.sh +0 -14
  66. data/bench/run_long.sh +0 -35
  67. data/bench/run_symbols.sh +0 -26
  68. data/bench/unpack.rb +0 -21
  69. data/bench/unpack_log.rb +0 -34
  70. data/bench/unpack_log_long.rb +0 -67
@@ -77,5 +77,108 @@ module MessagePack
77
77
  packer.full_pack
78
78
  end
79
79
  alias :pack :dump
80
+
81
+ def pool(size = 1, **options)
82
+ Pool.new(
83
+ frozen? ? self : dup.freeze,
84
+ size,
85
+ options.empty? ? nil : options,
86
+ )
87
+ end
88
+
89
+ class Pool
90
+ if RUBY_ENGINE == "ruby"
91
+ class AbstractPool
92
+ def initialize(size, &block)
93
+ @size = size
94
+ @new_member = block
95
+ @members = []
96
+ end
97
+
98
+ def checkout
99
+ @members.pop || @new_member.call
100
+ end
101
+
102
+ def checkin(member)
103
+ # If the pool is already full, we simply drop the extra member.
104
+ # This is because contrary to a connection pool, creating an extra instance
105
+ # is extremely unlikely to cause some kind of resource exhaustion.
106
+ #
107
+ # We could cycle the members (keep the newer one) but first It's more work and second
108
+ # the older member might have been created pre-fork, so it might be at least partially
109
+ # in shared memory.
110
+ if member && @members.size < @size
111
+ member.reset
112
+ @members << member
113
+ end
114
+ end
115
+ end
116
+ else
117
+ class AbstractPool
118
+ def initialize(size, &block)
119
+ @size = size
120
+ @new_member = block
121
+ @members = []
122
+ @mutex = Mutex.new
123
+ end
124
+
125
+ def checkout
126
+ @mutex.synchronize { @members.pop } || @new_member.call
127
+ end
128
+
129
+ def checkin(member)
130
+ @mutex.synchronize do
131
+ if member && @members.size < @size
132
+ member.reset
133
+ @members << member
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ class PackerPool < AbstractPool
141
+ private
142
+
143
+ def reset(packer)
144
+ packer.clear
145
+ end
146
+ end
147
+
148
+ class UnpackerPool < AbstractPool
149
+ private
150
+
151
+ def reset(unpacker)
152
+ unpacker.reset
153
+ end
154
+ end
155
+
156
+ def initialize(factory, size, options = nil)
157
+ options = nil if !options || options.empty?
158
+ @factory = factory
159
+ @packers = PackerPool.new(size) { factory.packer(options) }
160
+ @unpackers = UnpackerPool.new(size) { factory.unpacker(options) }
161
+ end
162
+
163
+ def load(data)
164
+ unpacker = @unpackers.checkout
165
+ begin
166
+ unpacker.feed_reference(data)
167
+ unpacker.full_unpack
168
+ ensure
169
+ @unpackers.checkin(unpacker)
170
+ end
171
+ end
172
+
173
+ def dump(object)
174
+ packer = @packers.checkout
175
+ begin
176
+ packer.write(object)
177
+ packer.full_pack
178
+ ensure
179
+ @packers.checkin(packer)
180
+ end
181
+ end
182
+ end
80
183
  end
81
184
  end
@@ -1,9 +1,26 @@
1
1
  class Symbol
2
- def to_msgpack_ext
3
- [to_s].pack('A*')
2
+ # to_msgpack_ext is supposed to return a binary string.
3
+ # The canonical way to do it for symbols would be:
4
+ # [to_s].pack('A*')
5
+ # However in this instance we can take a shortcut
6
+ if method_defined?(:name)
7
+ alias_method :to_msgpack_ext, :name
8
+ else
9
+ alias_method :to_msgpack_ext, :to_s
4
10
  end
5
11
 
6
12
  def self.from_msgpack_ext(data)
7
- data.unpack('A*').first.to_sym
13
+ # from_msgpack_ext is supposed to parse a binary string.
14
+ # The canonical way to do it for symbols would be:
15
+ # data.unpack1('A*').to_sym
16
+ # However in this instance we can take a shortcut
17
+
18
+ # We assume the string encoding is UTF-8, and let Ruby create either
19
+ # an ASCII symbol or UTF-8 symbol.
20
+ data.force_encoding(Encoding::UTF_8).to_sym
21
+ rescue EncodingError
22
+ # If somehow the string wasn't valid UTF-8 not valid ASCII, we fallback
23
+ # to what has been the historical behavior of creating a binary symbol
24
+ data.force_encoding(Encoding::BINARY).to_sym
8
25
  end
9
- end
26
+ end
data/lib/msgpack/time.rb CHANGED
@@ -18,7 +18,7 @@ module MessagePack
18
18
  else
19
19
  lambda do |payload|
20
20
  tv = MessagePack::Timestamp.from_msgpack_ext(payload)
21
- ::Time.at(tv.sec, tv.nsec / 1000.0)
21
+ ::Time.at(tv.sec, tv.nsec / 1000.0r)
22
22
  end
23
23
  end
24
24
 
@@ -55,7 +55,7 @@ module MessagePack
55
55
  else
56
56
  # timestamp64 (nsec: uint30be, sec: uint34be)
57
57
  nsec30 = nsec << 2
58
- sec_high2 = sec << 32 # high 2 bits (`x & 0b11` is redandunt)
58
+ sec_high2 = sec >> 32 # high 2 bits (`x & 0b11` is redandunt)
59
59
  sec_low32 = sec & 0xffffffff # low 32 bits
60
60
  [nsec30 | sec_high2, sec_low32].pack('L>2')
61
61
  end
@@ -1,9 +1,6 @@
1
1
  module MessagePack
2
- VERSION = "1.3.0"
3
-
4
- # NOTE for msgpack-ruby maintainer:
5
- # Check these things to release new binaryes for new Ruby versions (especially for Windows):
6
- # * versions/supports of rake-compiler & rake-compiler-dock
7
- # * update RUBY_CC_VERSION in Rakefile
8
- # * check Ruby dependency of released mswin gem details
2
+ VERSION = "1.6.0"
3
+ # Note for maintainers:
4
+ # Don't miss building/releasing the JRuby version (rake buld:java)
5
+ # See "How to build -java rubygems" in README for more details.
9
6
  end
data/lib/msgpack.rb CHANGED
@@ -1,15 +1,10 @@
1
1
  require "msgpack/version"
2
2
 
3
3
  if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" # This is same with `/java/ =~ RUBY_VERSION`
4
- require "java"
5
4
  require "msgpack/msgpack.jar"
6
- org.msgpack.jruby.MessagePackLibrary.new.load(JRuby.runtime, false)
5
+ JRuby::Util.load_ext("org.msgpack.jruby.MessagePackLibrary")
7
6
  else
8
- begin
9
- require "msgpack/#{RUBY_VERSION[/\d+.\d+/]}/msgpack"
10
- rescue LoadError
11
- require "msgpack/msgpack"
12
- end
7
+ require "msgpack/msgpack"
13
8
  end
14
9
 
15
10
  require "msgpack/packer"
@@ -22,16 +17,15 @@ require "msgpack/time"
22
17
 
23
18
  module MessagePack
24
19
  DefaultFactory = MessagePack::Factory.new
25
- DEFAULT_EMPTY_PARAMS = {}.freeze
26
20
 
27
21
  def load(src, param = nil)
28
22
  unpacker = nil
29
23
 
30
24
  if src.is_a? String
31
- unpacker = DefaultFactory.unpacker param || DEFAULT_EMPTY_PARAMS
25
+ unpacker = DefaultFactory.unpacker param
32
26
  unpacker.feed_reference src
33
27
  else
34
- unpacker = DefaultFactory.unpacker src, param || DEFAULT_EMPTY_PARAMS
28
+ unpacker = DefaultFactory.unpacker src, param
35
29
  end
36
30
 
37
31
  unpacker.full_unpack
@@ -41,8 +35,8 @@ module MessagePack
41
35
  module_function :load
42
36
  module_function :unpack
43
37
 
44
- def pack(v, *rest)
45
- packer = DefaultFactory.packer(*rest)
38
+ def pack(v, io = nil, options = nil)
39
+ packer = DefaultFactory.packer(io, options)
46
40
  packer.write v
47
41
  packer.full_pack
48
42
  end
data/msgpack.gemspec CHANGED
@@ -10,7 +10,6 @@ Gem::Specification.new do |s|
10
10
  s.email = ["frsyuki@gmail.com", "theo@iconara.net", "tagomoris@gmail.com"]
11
11
  s.license = "Apache 2.0"
12
12
  s.homepage = "http://msgpack.org/"
13
- s.rubyforge_project = "msgpack"
14
13
  s.require_paths = ["lib"]
15
14
  if /java/ =~ RUBY_PLATFORM
16
15
  s.files = Dir['lib/**/*.rb', 'lib/**/*.jar']
@@ -19,16 +18,14 @@ Gem::Specification.new do |s|
19
18
  s.files = `git ls-files`.split("\n")
20
19
  s.extensions = ["ext/msgpack/extconf.rb"]
21
20
  end
22
- s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
21
+
22
+ s.required_ruby_version = ">= 2.4"
23
23
 
24
24
  s.add_development_dependency 'bundler'
25
25
  s.add_development_dependency 'rake'
26
- s.add_development_dependency 'rake-compiler', ['~> 1.0']
27
- if /java/ !~ RUBY_PLATFORM
28
- # NOTE: rake-compiler-dock SHOULD be updated for new Ruby versions
29
- s.add_development_dependency 'rake-compiler-dock', ['~> 0.7.0']
30
- end
26
+ s.add_development_dependency 'rake-compiler', ['>= 1.1.9']
31
27
  s.add_development_dependency 'rspec', ['~> 3.3']
32
28
  s.add_development_dependency 'yard'
33
29
  s.add_development_dependency 'json'
30
+ s.add_development_dependency 'benchmark-ips', ['~> 2.10.0']
34
31
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe MessagePack::Bigint do
4
+ it 'serialize and deserialize arbitrary sized integer' do
5
+ [
6
+ 1,
7
+ -1,
8
+ 120938120391283122132313,
9
+ -21903120391203912391023920332103,
10
+ 210290021321301203912933021323,
11
+ ].each do |int|
12
+ expect(MessagePack::Bigint.from_msgpack_ext(MessagePack::Bigint.to_msgpack_ext(int))).to be == int
13
+ end
14
+ end
15
+
16
+ it 'has a stable format' do
17
+ {
18
+ 120938120391283122132313 => "\x00\x9F\xF4UY\x11\x92\x9A?\x00\x00\x19\x9C".b,
19
+ -21903120391203912391023920332103 => "\x01/\xB2\xBDG\xBD\xDE\xAA\xEBt\xCC\x8A\xC1\x00\x00\x01\x14".b,
20
+ 210290021321301203912933021323 => "\x00\xC4\xD8\x96\x8Bm\xCB\xC7\x03\xA7{\xD4\"\x00\x00\x00\x02".b,
21
+ }.each do |int, payload|
22
+ expect(MessagePack::Bigint.to_msgpack_ext(int)).to be == payload
23
+ expect(MessagePack::Bigint.from_msgpack_ext(payload)).to be == int
24
+ end
25
+ end
26
+ end
@@ -572,4 +572,21 @@ describe Buffer do
572
572
  end
573
573
  }
574
574
  end
575
+
576
+ it "defines a function for ObjectSpace.memsize_of" do
577
+ skip "JRuby doesn't support ObjectSpace.memsize_of" if IS_JRUBY
578
+
579
+ buffer = MessagePack::Buffer.new
580
+ empty_size = ObjectSpace.memsize_of(buffer)
581
+ expect(empty_size).to be < 400
582
+ 10.times do
583
+ buffer << "a" * 500
584
+ end
585
+ memsize = ObjectSpace.memsize_of(buffer)
586
+ expect(memsize).to be > empty_size
587
+ buffer.read(10)
588
+ expect(ObjectSpace.memsize_of(buffer)).to be == memsize
589
+ buffer.read_all
590
+ expect(ObjectSpace.memsize_of(buffer)).to be == empty_size
591
+ end
575
592
  end