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.
- checksums.yaml +5 -5
- data/.gitignore +3 -1
- data/.rubocop.yml +3 -0
- data/.travis.yml +27 -14
- data/ChangeLog +89 -1
- data/Gemfile +6 -1
- data/README.rdoc +55 -1
- data/Rakefile +5 -1
- data/bench/pack_symbols.rb +28 -0
- data/bench/run_symbols.sh +26 -0
- data/doclib/msgpack.rb +2 -2
- data/doclib/msgpack/core_ext.rb +20 -20
- data/doclib/msgpack/factory.rb +33 -0
- data/doclib/msgpack/packer.rb +20 -0
- data/doclib/msgpack/time.rb +22 -0
- data/doclib/msgpack/timestamp.rb +44 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +4 -0
- data/ext/java/org/msgpack/jruby/Encoder.java +48 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +67 -38
- data/ext/java/org/msgpack/jruby/Factory.java +20 -8
- data/ext/java/org/msgpack/jruby/MessagePackLibrary.java +0 -92
- data/ext/java/org/msgpack/jruby/Packer.java +114 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +15 -8
- data/ext/msgpack/buffer.h +14 -0
- data/ext/msgpack/buffer_class.c +1 -1
- data/ext/msgpack/compat.h +10 -0
- data/ext/msgpack/factory_class.c +24 -17
- data/ext/msgpack/factory_class.h +0 -2
- data/ext/msgpack/packer.c +5 -4
- data/ext/msgpack/packer.h +13 -1
- data/ext/msgpack/packer_class.c +130 -43
- data/ext/msgpack/packer_class.h +0 -2
- data/ext/msgpack/packer_ext_registry.c +2 -2
- data/ext/msgpack/packer_ext_registry.h +64 -25
- data/ext/msgpack/rbinit.c +0 -2
- data/ext/msgpack/unpacker.c +3 -3
- data/ext/msgpack/unpacker_class.c +25 -56
- data/ext/msgpack/unpacker_class.h +0 -2
- data/ext/msgpack/unpacker_ext_registry.c +2 -2
- data/ext/msgpack/unpacker_ext_registry.h +3 -3
- data/lib/msgpack.rb +36 -0
- data/lib/msgpack/core_ext.rb +139 -0
- data/lib/msgpack/factory.rb +21 -0
- data/lib/msgpack/symbol.rb +9 -0
- data/lib/msgpack/time.rb +29 -0
- data/lib/msgpack/timestamp.rb +76 -0
- data/lib/msgpack/version.rb +8 -1
- data/msgpack.gemspec +6 -7
- data/spec/cruby/buffer_spec.rb +6 -1
- data/spec/factory_spec.rb +134 -0
- data/spec/msgpack_spec.rb +52 -0
- data/spec/packer_spec.rb +200 -0
- data/spec/timestamp_spec.rb +121 -0
- data/spec/unpacker_spec.rb +29 -0
- metadata +29 -23
- data/ext/msgpack/core_ext.c +0 -144
- data/ext/msgpack/core_ext.h +0 -26
@@ -0,0 +1,139 @@
|
|
1
|
+
module MessagePack
|
2
|
+
module CoreExt
|
3
|
+
def to_msgpack(packer_or_io = nil)
|
4
|
+
if packer_or_io
|
5
|
+
if packer_or_io.is_a?(MessagePack::Packer)
|
6
|
+
to_msgpack_with_packer packer_or_io
|
7
|
+
else
|
8
|
+
MessagePack.pack(self, packer_or_io)
|
9
|
+
end
|
10
|
+
else
|
11
|
+
MessagePack.pack(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class NilClass
|
18
|
+
include MessagePack::CoreExt
|
19
|
+
|
20
|
+
private
|
21
|
+
def to_msgpack_with_packer(packer)
|
22
|
+
packer.write_nil
|
23
|
+
packer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class TrueClass
|
28
|
+
include MessagePack::CoreExt
|
29
|
+
|
30
|
+
private
|
31
|
+
def to_msgpack_with_packer(packer)
|
32
|
+
packer.write_true
|
33
|
+
packer
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class FalseClass
|
38
|
+
include MessagePack::CoreExt
|
39
|
+
|
40
|
+
private
|
41
|
+
def to_msgpack_with_packer(packer)
|
42
|
+
packer.write_false
|
43
|
+
packer
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Float
|
48
|
+
include MessagePack::CoreExt
|
49
|
+
|
50
|
+
private
|
51
|
+
def to_msgpack_with_packer(packer)
|
52
|
+
packer.write_float self
|
53
|
+
packer
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class String
|
58
|
+
include MessagePack::CoreExt
|
59
|
+
|
60
|
+
private
|
61
|
+
def to_msgpack_with_packer(packer)
|
62
|
+
packer.write_string self
|
63
|
+
packer
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Array
|
68
|
+
include MessagePack::CoreExt
|
69
|
+
|
70
|
+
private
|
71
|
+
def to_msgpack_with_packer(packer)
|
72
|
+
packer.write_array self
|
73
|
+
packer
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Hash
|
78
|
+
include MessagePack::CoreExt
|
79
|
+
|
80
|
+
private
|
81
|
+
def to_msgpack_with_packer(packer)
|
82
|
+
packer.write_hash self
|
83
|
+
packer
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Symbol
|
88
|
+
include MessagePack::CoreExt
|
89
|
+
|
90
|
+
private
|
91
|
+
def to_msgpack_with_packer(packer)
|
92
|
+
packer.write_symbol self
|
93
|
+
packer
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
if 1.class.name == "Integer"
|
98
|
+
class Integer
|
99
|
+
include MessagePack::CoreExt
|
100
|
+
|
101
|
+
private
|
102
|
+
def to_msgpack_with_packer(packer)
|
103
|
+
packer.write_int self
|
104
|
+
packer
|
105
|
+
end
|
106
|
+
end
|
107
|
+
else
|
108
|
+
class Fixnum
|
109
|
+
include MessagePack::CoreExt
|
110
|
+
|
111
|
+
private
|
112
|
+
def to_msgpack_with_packer(packer)
|
113
|
+
packer.write_int self
|
114
|
+
packer
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Bignum
|
119
|
+
include MessagePack::CoreExt
|
120
|
+
|
121
|
+
private
|
122
|
+
def to_msgpack_with_packer(packer)
|
123
|
+
packer.write_int self
|
124
|
+
packer
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
module MessagePack
|
130
|
+
class ExtensionValue
|
131
|
+
include CoreExt
|
132
|
+
|
133
|
+
private
|
134
|
+
def to_msgpack_with_packer(packer)
|
135
|
+
packer.write_extension self
|
136
|
+
packer
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/msgpack/factory.rb
CHANGED
@@ -56,5 +56,26 @@ module MessagePack
|
|
56
56
|
raise ArgumentError, "class or type id"
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
def load(src, param = nil)
|
61
|
+
unpacker = nil
|
62
|
+
|
63
|
+
if src.is_a? String
|
64
|
+
unpacker = unpacker(param)
|
65
|
+
unpacker.feed(src)
|
66
|
+
else
|
67
|
+
unpacker = unpacker(src, param)
|
68
|
+
end
|
69
|
+
|
70
|
+
unpacker.full_unpack
|
71
|
+
end
|
72
|
+
alias :unpack :load
|
73
|
+
|
74
|
+
def dump(v, *rest)
|
75
|
+
packer = packer(*rest)
|
76
|
+
packer.write(v)
|
77
|
+
packer.full_pack
|
78
|
+
end
|
79
|
+
alias :pack :dump
|
59
80
|
end
|
60
81
|
end
|
data/lib/msgpack/time.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# MessagePack extention packer and unpacker for built-in Time class
|
4
|
+
module MessagePack
|
5
|
+
module Time
|
6
|
+
# 3-arg Time.at is available Ruby >= 2.5
|
7
|
+
TIME_AT_3_AVAILABLE = begin
|
8
|
+
!!::Time.at(0, 0, :nanosecond)
|
9
|
+
rescue ArgumentError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
Unpacker = if TIME_AT_3_AVAILABLE
|
14
|
+
lambda do |payload|
|
15
|
+
tv = MessagePack::Timestamp.from_msgpack_ext(payload)
|
16
|
+
::Time.at(tv.sec, tv.nsec, :nanosecond)
|
17
|
+
end
|
18
|
+
else
|
19
|
+
lambda do |payload|
|
20
|
+
tv = MessagePack::Timestamp.from_msgpack_ext(payload)
|
21
|
+
::Time.at(tv.sec, tv.nsec / 1000.0)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Packer = lambda { |time|
|
26
|
+
MessagePack::Timestamp.to_msgpack_ext(time.tv_sec, time.tv_nsec)
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MessagePack
|
4
|
+
class Timestamp # a.k.a. "TimeSpec"
|
5
|
+
# Because the byte-order of MessagePack is big-endian in,
|
6
|
+
# pack() and unpack() specifies ">".
|
7
|
+
# See https://docs.ruby-lang.org/en/trunk/Array.html#method-i-pack for details.
|
8
|
+
|
9
|
+
# The timestamp extension type defined in the MessagePack spec.
|
10
|
+
# See https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type for details.
|
11
|
+
TYPE = -1
|
12
|
+
|
13
|
+
TIMESTAMP32_MAX_SEC = (1 << 32) - 1
|
14
|
+
TIMESTAMP64_MAX_SEC = (1 << 34) - 1
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
attr_reader :sec
|
18
|
+
|
19
|
+
# @return [Integer]
|
20
|
+
attr_reader :nsec
|
21
|
+
|
22
|
+
# @param [Integer] sec
|
23
|
+
# @param [Integer] nsec
|
24
|
+
def initialize(sec, nsec)
|
25
|
+
@sec = sec
|
26
|
+
@nsec = nsec
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.from_msgpack_ext(data)
|
30
|
+
case data.length
|
31
|
+
when 4
|
32
|
+
# timestamp32 (sec: uint32be)
|
33
|
+
sec, = data.unpack('L>')
|
34
|
+
new(sec, 0)
|
35
|
+
when 8
|
36
|
+
# timestamp64 (nsec: uint30be, sec: uint34be)
|
37
|
+
n, s = data.unpack('L>2')
|
38
|
+
sec = ((n & 0b11) << 32) | s
|
39
|
+
nsec = n >> 2
|
40
|
+
new(sec, nsec)
|
41
|
+
when 12
|
42
|
+
# timestam96 (nsec: uint32be, sec: int64be)
|
43
|
+
nsec, sec = data.unpack('L>q>')
|
44
|
+
new(sec, nsec)
|
45
|
+
else
|
46
|
+
raise MalformedFormatError, "Invalid timestamp data size: #{data.length}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.to_msgpack_ext(sec, nsec)
|
51
|
+
if sec >= 0 && nsec >= 0 && sec <= TIMESTAMP64_MAX_SEC
|
52
|
+
if nsec === 0 && sec <= TIMESTAMP32_MAX_SEC
|
53
|
+
# timestamp32 = (sec: uint32be)
|
54
|
+
[sec].pack('L>')
|
55
|
+
else
|
56
|
+
# timestamp64 (nsec: uint30be, sec: uint34be)
|
57
|
+
nsec30 = nsec << 2
|
58
|
+
sec_high2 = sec >> 32 # high 2 bits (`x & 0b11` is redandunt)
|
59
|
+
sec_low32 = sec & 0xffffffff # low 32 bits
|
60
|
+
[nsec30 | sec_high2, sec_low32].pack('L>2')
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# timestamp96 (nsec: uint32be, sec: int64be)
|
64
|
+
[nsec, sec].pack('L>q>')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_msgpack_ext
|
69
|
+
self.class.to_msgpack_ext(sec, nsec)
|
70
|
+
end
|
71
|
+
|
72
|
+
def ==(other)
|
73
|
+
other.class == self.class && sec == other.sec && nsec == other.nsec
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/msgpack/version.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
1
|
module MessagePack
|
2
|
-
VERSION = "
|
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
|
3
10
|
end
|
data/msgpack.gemspec
CHANGED
@@ -10,8 +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
|
-
s.has_rdoc = false
|
15
13
|
s.require_paths = ["lib"]
|
16
14
|
if /java/ =~ RUBY_PLATFORM
|
17
15
|
s.files = Dir['lib/**/*.rb', 'lib/**/*.jar']
|
@@ -22,13 +20,14 @@ Gem::Specification.new do |s|
|
|
22
20
|
end
|
23
21
|
s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
|
24
22
|
|
25
|
-
s.add_development_dependency 'bundler'
|
26
|
-
s.add_development_dependency 'rake'
|
27
|
-
s.add_development_dependency 'rake-compiler', ['~> 0
|
23
|
+
s.add_development_dependency 'bundler'
|
24
|
+
s.add_development_dependency 'rake'
|
25
|
+
s.add_development_dependency 'rake-compiler', ['~> 1.0']
|
28
26
|
if /java/ !~ RUBY_PLATFORM
|
29
|
-
|
27
|
+
# NOTE: rake-compiler-dock SHOULD be updated for new Ruby versions
|
28
|
+
s.add_development_dependency 'rake-compiler-dock', ['~> 1.0']
|
30
29
|
end
|
31
30
|
s.add_development_dependency 'rspec', ['~> 3.3']
|
32
|
-
s.add_development_dependency 'yard'
|
31
|
+
s.add_development_dependency 'yard'
|
33
32
|
s.add_development_dependency 'json'
|
34
33
|
end
|
data/spec/cruby/buffer_spec.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'random_compat'
|
3
3
|
|
4
|
+
require 'stringio'
|
5
|
+
if defined?(Encoding)
|
6
|
+
Encoding.default_external = 'ASCII-8BIT'
|
7
|
+
end
|
8
|
+
|
4
9
|
describe Buffer do
|
5
10
|
STATIC_EXAMPLES = {}
|
6
11
|
STATIC_EXAMPLES[:empty01] = ''
|
@@ -45,7 +50,7 @@ describe Buffer do
|
|
45
50
|
b.read(n)
|
46
51
|
s.slice!(0, n)
|
47
52
|
end
|
48
|
-
key = :"random#{"%02d"%i}"
|
53
|
+
key = :"random#{"%02d" % i}"
|
49
54
|
cases[key] = b
|
50
55
|
examples[key] = s
|
51
56
|
end
|
data/spec/factory_spec.rb
CHANGED
@@ -44,6 +44,32 @@ describe MessagePack::Factory do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
describe '#dump and #load' do
|
48
|
+
it 'can be used like a standard coder' do
|
49
|
+
subject.register_type(0x00, Symbol)
|
50
|
+
expect(subject.load(subject.dump(:symbol))).to be == :symbol
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'is alias as pack and unpack' do
|
54
|
+
subject.register_type(0x00, Symbol)
|
55
|
+
expect(subject.unpack(subject.pack(:symbol))).to be == :symbol
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'accept options' do
|
59
|
+
hash = subject.unpack(MessagePack.pack('k' => 'v'), symbolize_keys: true)
|
60
|
+
expect(hash).to be == { k: 'v' }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#freeze' do
|
65
|
+
it 'can freeze factory instance to deny new registrations anymore' do
|
66
|
+
subject.register_type(0x00, Symbol)
|
67
|
+
subject.freeze
|
68
|
+
expect(subject.frozen?).to be_truthy
|
69
|
+
expect{ subject.register_type(0x01, Array) }.to raise_error(RuntimeError, "can't modify frozen Factory")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
47
73
|
class MyType
|
48
74
|
def initialize(a, b)
|
49
75
|
@a = a
|
@@ -208,6 +234,114 @@ describe MessagePack::Factory do
|
|
208
234
|
my.a.should == 1
|
209
235
|
my.b.should == 2
|
210
236
|
end
|
237
|
+
|
238
|
+
describe "registering an ext type for a module" do
|
239
|
+
before do
|
240
|
+
mod = Module.new do
|
241
|
+
def self.from_msgpack_ext(data)
|
242
|
+
"unpacked #{data}"
|
243
|
+
end
|
244
|
+
|
245
|
+
def to_msgpack_ext
|
246
|
+
'value_msgpacked'
|
247
|
+
end
|
248
|
+
end
|
249
|
+
stub_const('Mod', mod)
|
250
|
+
end
|
251
|
+
let(:factory) { described_class.new }
|
252
|
+
before { factory.register_type(0x01, Mod) }
|
253
|
+
|
254
|
+
describe "packing an object whose class included the module" do
|
255
|
+
subject { factory.packer.pack(value).to_s }
|
256
|
+
before { stub_const('Value', Class.new{ include Mod }) }
|
257
|
+
let(:value) { Value.new }
|
258
|
+
it { is_expected.to eq "\xC7\x0F\x01value_msgpacked" }
|
259
|
+
end
|
260
|
+
|
261
|
+
describe "packing an object which has been extended by the module" do
|
262
|
+
subject { factory.packer.pack(object).to_s }
|
263
|
+
let(:object) { Object.new.extend Mod }
|
264
|
+
it { is_expected.to eq "\xC7\x0F\x01value_msgpacked" }
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "unpacking with the module" do
|
268
|
+
subject { factory.unpacker.feed("\xC7\x06\x01module").unpack }
|
269
|
+
it { is_expected.to eq "unpacked module" }
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
describe 'the special treatment of symbols with ext type' do
|
275
|
+
let(:packer) { subject.packer }
|
276
|
+
let(:unpacker) { subject.unpacker }
|
277
|
+
|
278
|
+
def symbol_after_roundtrip
|
279
|
+
packed_symbol = packer.pack(:symbol).to_s
|
280
|
+
unpacker.feed(packed_symbol).unpack
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'if no ext type is registered for symbols' do
|
284
|
+
it 'converts symbols to string' do
|
285
|
+
expect(symbol_after_roundtrip).to eq 'symbol'
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
context 'if an ext type is registered for symbols' do
|
290
|
+
context 'if using the default serializer' do
|
291
|
+
before { subject.register_type(0x00, ::Symbol) }
|
292
|
+
|
293
|
+
it 'lets symbols survive a roundtrip' do
|
294
|
+
expect(symbol_after_roundtrip).to be :symbol
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context 'if using a custom serializer' do
|
299
|
+
before do
|
300
|
+
class Symbol
|
301
|
+
alias_method :to_msgpack_ext_orig, :to_msgpack_ext
|
302
|
+
def to_msgpack_ext
|
303
|
+
self.to_s.codepoints.to_a.pack('n*')
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class << Symbol
|
308
|
+
alias_method :from_msgpack_ext_orig, :from_msgpack_ext
|
309
|
+
def from_msgpack_ext(data)
|
310
|
+
data.unpack('n*').map(&:chr).join.to_sym
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
before { subject.register_type(0x00, ::Symbol) }
|
316
|
+
|
317
|
+
it 'lets symbols survive a roundtrip' do
|
318
|
+
expect(symbol_after_roundtrip).to be :symbol
|
319
|
+
end
|
320
|
+
|
321
|
+
after do
|
322
|
+
class Symbol
|
323
|
+
alias_method :to_msgpack_ext, :to_msgpack_ext_orig
|
324
|
+
end
|
325
|
+
|
326
|
+
class << Symbol
|
327
|
+
alias_method :from_msgpack_ext, :from_msgpack_ext_orig
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
describe 'under stressful GC' do
|
335
|
+
it 'works well' do
|
336
|
+
begin
|
337
|
+
GC.stress = true
|
338
|
+
|
339
|
+
f = MessagePack::Factory.new
|
340
|
+
f.register_type(0x0a, Symbol)
|
341
|
+
ensure
|
342
|
+
GC.stress = false
|
343
|
+
end
|
344
|
+
end
|
211
345
|
end
|
212
346
|
|
213
347
|
describe 'DefaultFactory' do
|