msgpack 1.3.3 → 1.6.0

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/.rubocop.yml +2 -2
  4. data/ChangeLog +74 -0
  5. data/Gemfile +1 -1
  6. data/README.md +266 -0
  7. data/Rakefile +1 -9
  8. data/bench/bench.rb +78 -0
  9. data/bin/console +8 -0
  10. data/doclib/msgpack/factory.rb +47 -3
  11. data/doclib/msgpack/packer.rb +5 -4
  12. data/doclib/msgpack/unpacker.rb +2 -2
  13. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  14. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  15. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  16. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  17. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  18. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  19. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  20. data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
  21. data/ext/msgpack/buffer.c +42 -68
  22. data/ext/msgpack/buffer.h +59 -14
  23. data/ext/msgpack/buffer_class.c +90 -52
  24. data/ext/msgpack/compat.h +1 -111
  25. data/ext/msgpack/extconf.rb +45 -19
  26. data/ext/msgpack/factory_class.c +133 -43
  27. data/ext/msgpack/packer.c +60 -36
  28. data/ext/msgpack/packer.h +27 -25
  29. data/ext/msgpack/packer_class.c +84 -77
  30. data/ext/msgpack/packer_class.h +11 -0
  31. data/ext/msgpack/packer_ext_registry.c +24 -32
  32. data/ext/msgpack/packer_ext_registry.h +40 -33
  33. data/ext/msgpack/sysdep.h +5 -2
  34. data/ext/msgpack/unpacker.c +132 -115
  35. data/ext/msgpack/unpacker.h +23 -10
  36. data/ext/msgpack/unpacker_class.c +83 -78
  37. data/ext/msgpack/unpacker_class.h +11 -0
  38. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  39. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  40. data/lib/msgpack/bigint.rb +69 -0
  41. data/lib/msgpack/factory.rb +103 -0
  42. data/lib/msgpack/symbol.rb +21 -4
  43. data/lib/msgpack/time.rb +1 -1
  44. data/lib/msgpack/version.rb +4 -8
  45. data/lib/msgpack.rb +6 -12
  46. data/msgpack.gemspec +4 -6
  47. data/spec/bigint_spec.rb +26 -0
  48. data/spec/cruby/buffer_spec.rb +17 -0
  49. data/spec/factory_spec.rb +351 -12
  50. data/spec/msgpack_spec.rb +1 -1
  51. data/spec/packer_spec.rb +18 -0
  52. data/spec/spec_helper.rb +37 -3
  53. data/spec/timestamp_spec.rb +38 -0
  54. data/spec/unpacker_spec.rb +157 -4
  55. metadata +31 -61
  56. data/.travis.yml +0 -43
  57. data/README.rdoc +0 -225
  58. data/bench/pack.rb +0 -23
  59. data/bench/pack_log.rb +0 -33
  60. data/bench/pack_log_long.rb +0 -65
  61. data/bench/pack_symbols.rb +0 -28
  62. data/bench/run.sh +0 -14
  63. data/bench/run_long.sh +0 -35
  64. data/bench/run_symbols.sh +0 -26
  65. data/bench/unpack.rb +0 -21
  66. data/bench/unpack_log.rb +0 -34
  67. 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
 
@@ -1,10 +1,6 @@
1
1
  module MessagePack
2
- VERSION = "1.3.3"
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
- # https://github.com/rake-compiler/rake-compiler-dock/blob/master/History.md
8
- # * update RUBY_CC_VERSION in Rakefile
9
- # * 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.
10
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
@@ -18,16 +18,14 @@ Gem::Specification.new do |s|
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.extensions = ["ext/msgpack/extconf.rb"]
20
20
  end
21
- s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
21
+
22
+ s.required_ruby_version = ">= 2.4"
22
23
 
23
24
  s.add_development_dependency 'bundler'
24
25
  s.add_development_dependency 'rake'
25
- s.add_development_dependency 'rake-compiler', ['~> 1.0']
26
- if /java/ !~ RUBY_PLATFORM
27
- # NOTE: rake-compiler-dock SHOULD be updated for new Ruby versions
28
- s.add_development_dependency 'rake-compiler-dock', ['~> 1.0']
29
- end
26
+ s.add_development_dependency 'rake-compiler', ['>= 1.1.9']
30
27
  s.add_development_dependency 'rspec', ['~> 3.3']
31
28
  s.add_development_dependency 'yard'
32
29
  s.add_development_dependency 'json'
30
+ s.add_development_dependency 'benchmark-ips', ['~> 2.10.0']
33
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