hessian2 1.1.1 → 2.0.1

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -2
  3. data/LICENSE.txt +22 -0
  4. data/README.md +161 -0
  5. data/hessian2.gemspec +3 -2
  6. data/lib/hessian2.rb +12 -4
  7. data/lib/hessian2/class_wrapper.rb +89 -0
  8. data/lib/hessian2/client.rb +38 -0
  9. data/lib/hessian2/constants.rb +164 -0
  10. data/lib/hessian2/em_client.rb +52 -0
  11. data/lib/hessian2/fault.rb +3 -0
  12. data/lib/hessian2/handler.rb +15 -0
  13. data/lib/hessian2/hessian_client.rb +3 -38
  14. data/lib/hessian2/parser.rb +619 -0
  15. data/lib/hessian2/struct_wrapper.rb +55 -0
  16. data/lib/hessian2/type_wrapper.rb +49 -8
  17. data/lib/hessian2/version.rb +1 -1
  18. data/lib/hessian2/writer.rb +498 -0
  19. data/spec/binary_spec.rb +51 -0
  20. data/spec/boolean_spec.rb +26 -0
  21. data/spec/class_wrapper_spec.rb +52 -0
  22. data/spec/create_monkeys.rb +14 -0
  23. data/spec/date_spec.rb +45 -0
  24. data/spec/double_spec.rb +78 -0
  25. data/spec/int_spec.rb +54 -0
  26. data/spec/list_spec.rb +66 -0
  27. data/spec/long_spec.rb +68 -0
  28. data/spec/map_spec.rb +36 -0
  29. data/spec/null_spec.rb +17 -0
  30. data/spec/object_spec.rb +65 -0
  31. data/spec/ref_spec.rb +43 -0
  32. data/spec/spec_helper.rb +23 -0
  33. data/spec/string_spec.rb +61 -0
  34. data/spec/struct_wrapper_spec.rb +47 -0
  35. data/spec/type_wrapper_spec.rb +102 -0
  36. data/test/app.rb +15 -0
  37. data/test/client.rb +9 -0
  38. data/test/config.ru +2 -0
  39. data/test/monkey_service.rb +12 -0
  40. metadata +79 -19
  41. data/README.rdoc +0 -21
  42. data/lib/hessian2/hessian_exception.rb +0 -3
  43. data/lib/hessian2/hessian_parser.rb +0 -75
  44. data/lib/hessian2/hessian_writer.rb +0 -130
  45. data/test/test_hessian_parser.rb +0 -56
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when binary" do
6
+
7
+ it "should write binary data length 0-15 ::= [x20-x2f] <binary-data>" do
8
+ (0..15).to_a.each do |len|
9
+ val = ['b' * len].pack('a*')
10
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:bin, val))
11
+
12
+ expect(bin[0].unpack('C').first - 0x20).to eq(val.size)
13
+ expect(bin.size).to eq(1 + val.size)
14
+ expect(Hessian2.parse(bin)).to eq(val)
15
+ end
16
+ end
17
+
18
+
19
+ it "should write binary data length 0-1023 ::= [x34-x37] <binary-data>" do
20
+ [ 16, 256, 512, 1023 ].each do |len|
21
+ val = ['b' * len].pack('a*')
22
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:bin, val))
23
+
24
+ b1, b0 = bin[0, 2].unpack('CC')
25
+ expect(256 * (b1 - 0x34) + b0).to eq(val.size)
26
+ expect(bin.size).to eq(2 + val.size)
27
+ expect(Hessian2.parse(bin)).to eq(val)
28
+ end
29
+ end
30
+
31
+
32
+ it "should write 8-bit binary data non-final chunk ('A') ::= x41 b1 b0 <binary-data> and 8-bit binary data final chunk ('B') ::= 'B' b1 b0 <binary-data>" do
33
+ val = IO.binread(File.expand_path("../Lighthouse.jpg", __FILE__))
34
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:bin, val))
35
+ chunks = val.size / 0x8000
36
+
37
+ chunks.times do |c|
38
+ i = c * 0x8003
39
+ expect(bin[i]).to eq('A')
40
+ expect(bin[i + 1, 2].unpack('n').first).to eq(0x8000)
41
+ end
42
+
43
+ i = chunks * 0x8003
44
+ expect(bin[i]).to eq('B')
45
+ expect(bin[i + 1, 2].unpack('n').first).to eq(val.size - 0x8000 * chunks)
46
+ expect(Hessian2.parse(bin)).to eq(val)
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when boolean" do
6
+
7
+ it "should write true ::= 'T'" do
8
+ val = true
9
+ bin = Hessian2.write(val)
10
+
11
+ expect(bin).to eq('T')
12
+ expect(Hessian2.parse(bin)).to eq(val)
13
+ end
14
+
15
+
16
+ it "should write false ::= 'F'" do
17
+ val = false
18
+ bin = Hessian2.write(val)
19
+
20
+ expect(bin).to eq('F')
21
+ expect(Hessian2.parse(bin)).to eq(val)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe ClassWrapper do
5
+ hash = { id: nil, born_at: Time.new(2009, 5, 8), name: '大鸡', price: 99.99 }
6
+
7
+ it "should raise error" do
8
+ expect(lambda{ Hessian2::ClassWrapper.new('com.sun.java.Monkey') }).to raise_error
9
+ expect(lambda{ Hessian2::ClassWrapper.new('com.sun.java.Monkey', 59) }).to raise_error
10
+ end
11
+
12
+
13
+ it "should wrap nil" do
14
+ bin = Hessian2.write(Hessian2::ClassWrapper.new('com.sun.java.Monkey', nil))
15
+
16
+ expect(bin).to eq('N')
17
+ expect(Hessian2.parse(bin)).to eq(nil)
18
+ end
19
+
20
+
21
+ it "should wrap hash, monkey, another monkey" do
22
+ bin = Hessian2.write(Hessian2::ClassWrapper.new('com.sun.java.Monkey', hash))
23
+
24
+ [ hash, Monkey.new(hash), AnotherMonkey.new(hash) ].each do |val|
25
+ bin = Hessian2.write(Hessian2::ClassWrapper.new('com.sun.java.Monkey', val))
26
+
27
+ bytes = bin.each_byte
28
+ expect([ bytes.next ].pack('C')).to eq('C')
29
+ expect(Hessian2.parse_string(bytes)).to eq('com.sun.java.Monkey')
30
+ expect(Hessian2.parse_int(bytes)).to eq(4)
31
+ 4.times{ Hessian2.parse_string(bytes) }
32
+ expect(bytes.next - 0x60).to eq(0)
33
+ _monkey = Hessian2.parse(bin)
34
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
35
+ end
36
+ end
37
+
38
+
39
+ it "should wrap array" do
40
+ arr = [nil, hash, Monkey.new(hash), AnotherMonkey.new(hash)]
41
+ bin = Hessian2.write(Hessian2::ClassWrapper.new('[com.sun.java.Monkey', arr))
42
+
43
+ _monkey1, _monkey2, _monkey3, _monkey4 = Hessian2.parse(bin)
44
+ expect(_monkey1).to eq(nil)
45
+ [ _monkey2, _monkey3, _monkey4 ].each do |_monkey|
46
+ expect([ _monkey.born_at, _monkey.name, _monkey.price ]).to eq([ hash[:born_at], hash[:name], hash[:price] ])
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ ActiveRecord::Base.connection.execute("drop table if exists monkeys")
4
+ ActiveRecord::Base.connection.execute("create table monkeys(id integer(11) not null auto_increment, born_at datetime, name varchar(255), price decimal(10, 2), primary key(id)) charset=utf8")
5
+
6
+ now = Time.new
7
+ 1.upto(1000).each do |i|
8
+ Monkey.create(
9
+ id: i,
10
+ name: "#{i}号猴",
11
+ price: 0.25 * i,
12
+ born_at: now - 3600 * (1000 - i)
13
+ )
14
+ end
data/spec/date_spec.rb ADDED
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when date" do
6
+
7
+ it "should write 32-bit UTC minute date ::= x4b b3 b2 b1 b0" do
8
+ val = Time.new(2008, 8, 8, 8, 8)
9
+ bin = Hessian2.write(val)
10
+
11
+ expect(bin[0].unpack('C').first).to eq(0x4b)
12
+ expect(Time.at(bin[1, 4].unpack('l>').first * 60)).to eq(val)
13
+ expect(Hessian2.parse(bin)).to eq(val)
14
+ end
15
+
16
+
17
+ it "should write 64-bit UTC millisecond date ::= x4a b7 b6 b5 b4 b3 b2 b1 b0" do
18
+ val = Time.new(2008, 8, 8, 8, 8, 8)
19
+ bin = Hessian2.write(val)
20
+
21
+ expect(bin[0].unpack('C').first).to eq(0x4a)
22
+ _val = bin[1, 8].unpack('q>').first
23
+ expect(Time.at(_val / 1000, _val % 1000 * 1000)).to eq(val)
24
+ expect(Hessian2.parse(bin)).to eq(val)
25
+
26
+ val2 = Time.at(946684800, 123456.789)
27
+ bin2 = Hessian2.write(val2)
28
+
29
+ expect(bin2[0].unpack('C').first).to eq(0x4a)
30
+ _val2 = bin2[1, 8].unpack('Q>').first
31
+ expect(Time.at(_val2 / 1000, _val2 % 1000 * 1000)).to eq(Time.at(val2.to_i, val2.usec / 1000 * 1000))
32
+ expect(Hessian2.parse(bin2)).to eq(Time.at(val2.to_i, val2.usec / 1000 * 1000))
33
+
34
+ val3 = Time.at(946684800.2)
35
+ bin3 = Hessian2.write(val3)
36
+
37
+ expect(bin3[0].unpack('C').first).to eq(0x4a)
38
+ _val3 = bin3[1, 8].unpack('Q>').first
39
+ expect(Time.at(_val3 / 1000, _val3 % 1000 * 1000)).to eq(Time.at(val3.to_i, val3.usec / 1000 * 1000))
40
+ expect(Hessian2.parse(bin3)).to eq(Time.at(val3.to_i, val3.usec / 1000 * 1000))
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,78 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when double" do
6
+
7
+ it "should write double 0.0 ::= x5b" do
8
+ bin = Hessian2.write(0.0)
9
+
10
+ expect(bin.unpack('C').first).to eq(0x5b)
11
+ expect(Hessian2.parse(bin)).to eq(0)
12
+ end
13
+
14
+
15
+ it "should write double 1.0 ::= x5c" do
16
+ bin = Hessian2.write(1.0)
17
+
18
+ expect(bin.unpack('C').first).to eq(0x5c)
19
+ expect(Hessian2.parse(bin)).to eq(1)
20
+ end
21
+
22
+
23
+ it "should write double represented as byte (-128.0 to 127.0) ::= x5d b0" do
24
+ [ -128.0, 127.0 ].each do |val|
25
+ bin = Hessian2.write(val)
26
+
27
+ expect(bin[0].unpack('C').first).to eq(0x5d)
28
+ expect(bin.bytesize).to eq(2)
29
+ expect(Hessian2.parse(bin)).to eq(val)
30
+ end
31
+ end
32
+
33
+
34
+ it "should write double represented as short (-32768.0 to 327676.0) ::= x5e b1 b0" do
35
+ [ -32768.0, 32767.0, -129.0, 128.0 ].each do |val|
36
+ bin = Hessian2.write(val)
37
+
38
+ expect(bin[0].unpack('C').first).to eq(0x5e)
39
+ expect(bin.bytesize).to eq(3)
40
+ expect(Hessian2.parse(bin)).to eq(val)
41
+ end
42
+ end
43
+
44
+
45
+ it "should write double represented as float ::= x5f b3 b2 b1 b0" do
46
+ [ -123.456, 123.456 ].each do |val|
47
+ bin = Hessian2.write(val)
48
+
49
+ expect(bin[0].unpack('C').first).to eq(0x5f)
50
+ expect(bin.bytesize).to eq(5)
51
+ expect(Hessian2.parse(bin)).to eq(val)
52
+ end
53
+ end
54
+
55
+
56
+ it "should write 64-bit IEEE encoded double ('D') ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0" do
57
+ [ 4.9E-324, 1.7976931348623157E308, Float::INFINITY, -Float::INFINITY ].each do |val|
58
+ bin = Hessian2.write(val)
59
+
60
+ expect(bin[0]).to eq('D')
61
+ expect(bin.bytesize).to eq(9)
62
+ expect(Hessian2.parse(bin)).to eq(val)
63
+ end
64
+ end
65
+
66
+
67
+ it "should write NAN" do
68
+ val = Float::NAN
69
+ bin = Hessian2.write(val)
70
+
71
+ expect(bin[0]).to eq('D')
72
+ expect(bin.bytesize).to eq(9)
73
+ expect(Hessian2.parse(bin).nan?).to eq(true)
74
+ end
75
+
76
+ end
77
+ end
78
+ end
data/spec/int_spec.rb ADDED
@@ -0,0 +1,54 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when int" do
6
+
7
+ it "should write one-octet compact int (-x10 to x2f, x90 is 0) ::= [x80-xbf]" do
8
+ (-0x10..0x2f).each do |val|
9
+ bin = Hessian2.write(val)
10
+
11
+ expect(bin.unpack('C').first - 0x90).to eq(val)
12
+ expect(Hessian2.parse(bin)).to eq(val)
13
+ end
14
+ end
15
+
16
+
17
+ it "should write two-octet compact int (-x800 to x7ff) ::= [xc0-xcf] b0" do
18
+ -0x800.step(0x7ff, 0x100).select{|x| !(-0x10..0x2f).include?(x)}.each do |val|
19
+ bin = Hessian2.write(val)
20
+
21
+ b1, b0 = bin[0, 2].unpack('CC')
22
+ expect(((b1 - 0xc8) << 8) + b0).to eq(val)
23
+ expect(Hessian2.parse(bin)).to eq(val)
24
+ end
25
+ end
26
+
27
+
28
+ it "should write three-octet compact int (-x40000 to x3ffff) ::= [xd0-xd7] b1 b0" do
29
+ -0x40000.step(0x3ffff, 0x10000).select{|x| !(-0x800..0x7ff).include?(x)}.each do |val|
30
+ bin = Hessian2.write(val)
31
+
32
+ b2, b1, b0 = bin[0, 3].unpack('CCC')
33
+ expect(((b2 - 0xd4) << 16) + (b1 << 8) + b0).to eq(val)
34
+ expect(Hessian2.parse(bin)).to eq(val)
35
+ end
36
+ end
37
+
38
+
39
+ it "should write 32-bit signed integer ('I') ::= 'I' b3 b2 b1 b0" do
40
+ fixnum_max = 2 ** (0.size * 8 - 2) - 1
41
+ fixnum_min = -(2 ** (0.size * 8 - 2))
42
+
43
+ [ -0x80_000_000, 0x7f_fff_fff, -0x40001, 0x40000 ].each do |val|
44
+ bin = Hessian2.write(val > fixnum_max || val < fixnum_min ? Hessian2::TypeWrapper.new(:int, val) : val)
45
+
46
+ expect(bin[0]).to eq('I')
47
+ expect(bin[1, 4].unpack('l>').first).to eq(val)
48
+ expect(Hessian2.parse(bin)).to eq(val)
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
data/spec/list_spec.rb ADDED
@@ -0,0 +1,66 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when list" do
6
+
7
+ it "should write variable-length list/vector ('U') ::= x55 type value* 'Z'" do
8
+ # not implemented
9
+ end
10
+
11
+
12
+ it "should write fixed-length list/vector ('V') ::= 'V' type int value*" do
13
+ val = (1..9).to_a
14
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[int', val))
15
+
16
+ bytes = bin.each_byte
17
+ expect([ bytes.next ].pack('C')).to eq('V')
18
+ expect(Hessian2.parse_string(bytes)).to eq('[I')
19
+ expect(Hessian2.parse_int(bytes)).to eq(val.size)
20
+ expect(Hessian2.parse(bin)).to eq(val)
21
+ end
22
+
23
+
24
+ it "should write variable-length untyped list/vector ('W') ::= x57 value* 'Z'" do
25
+ # not implemented
26
+ end
27
+
28
+
29
+ it "should write fixed-length untyped list/vector ('X') ::= x58 int value*" do
30
+ val = [ Time.new(2005, 3, 4), '阿门', 59.59 ] * 3
31
+ bin = Hessian2.write(val)
32
+
33
+ bytes = bin.each_byte
34
+ expect([ bytes.next ].pack('C')).to eq('X')
35
+ expect(Hessian2.parse_int(bytes)).to eq(val.size)
36
+ expect(Hessian2.parse(bin)).to eq(val)
37
+ end
38
+
39
+
40
+ it "should write fixed list with direct length ::= [x70-77] type value*" do
41
+ 8.times do |i|
42
+ val = (0...i).to_a
43
+ bin = Hessian2.write(Hessian2::TypeWrapper.new('[int', val))
44
+
45
+ bytes = bin.each_byte
46
+ expect(bytes.next - 0x70).to eq(val.size)
47
+ expect(Hessian2.parse_string(bytes)).to eq('[I')
48
+ expect(Hessian2.parse(bin)).to eq(val)
49
+ end
50
+ end
51
+
52
+
53
+ it "should write fixed untyped list with direct length ::= [x78-7f] value*" do
54
+ 8.times do |i|
55
+ val = (0...i).to_a
56
+ bin = Hessian2.write(val)
57
+
58
+ bytes = bin.each_byte
59
+ expect(bytes.next - 0x78).to eq(val.size)
60
+ expect(Hessian2.parse(bin)).to eq(val)
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
data/spec/long_spec.rb ADDED
@@ -0,0 +1,68 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ module Hessian2
4
+ describe Writer do
5
+ context "when long" do
6
+
7
+ it "should write one-octet compact long (-x8 to xf, xe0 is 0) ::= [xd8-xef]" do
8
+ (-0x08..0x0f).each do |val|
9
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:long, val))
10
+
11
+ expect(bin.unpack('C').first - 0xe0).to eq(val)
12
+ expect(Hessian2.parse(bin)).to eq(val)
13
+ end
14
+ end
15
+
16
+
17
+ it "should write two-octet compact long (-x800 to x7ff, xf8 is 0) ::= [xf0-xff] b0" do
18
+ -0x800.step(0x7ff, 0x100).select{|x| !(-0x08..0x0f).include?(x)}.each do |val|
19
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:long, val))
20
+
21
+ b1, b0 = bin[0, 2].unpack('CC')
22
+ expect(((b1 - 0xf8) << 8) + b0).to eq(val)
23
+ expect(Hessian2.parse(bin)).to eq(val)
24
+ end
25
+ end
26
+
27
+
28
+ it "should write three-octet compact long (-x40000 to x3ffff) ::= [x38-x3f] b1 b0" do
29
+ -0x40000.step(0x3ffff, 0x10000).select{|x| !(-0x800..0x7ff).include?(x)}.each do |val|
30
+ bin = Hessian2.write(Hessian2::TypeWrapper.new(:long, val))
31
+
32
+ b2, b1, b0 = bin[0, 3].unpack('CCC')
33
+ expect(((b2 - 0x3c) << 16) + (b1 << 8) + b0).to eq(val)
34
+ expect(Hessian2.parse(bin)).to eq(val)
35
+ end
36
+ end
37
+
38
+
39
+ it "should write long encoded as 32-bit int ('Y') ::= x59 b3 b2 b1 b0" do
40
+ fixnum_max = 2 ** (0.size * 8 - 2) - 1
41
+ fixnum_min = -(2 ** (0.size * 8 - 2))
42
+
43
+ [ -0x80_000_000, 0x7f_fff_fff, -0x40001, 0x40000 ].each do |val|
44
+ bin = Hessian2.write(val <= fixnum_max && val >= fixnum_min ? Hessian2::TypeWrapper.new(:long, val) : val)
45
+
46
+ expect(bin[0]).to eq('Y')
47
+ expect(bin[1, 4].unpack('l>').first).to eq(val)
48
+ expect(Hessian2.parse(bin)).to eq(val)
49
+ end
50
+ end
51
+
52
+
53
+ it "should write 64-bit signed long integer ('L') ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0" do
54
+ fixnum_max = 2 ** (0.size * 8 - 2) - 1
55
+ fixnum_min = -(2 ** (0.size * 8 - 2))
56
+
57
+ [ -0x8_000_000_000_000_000, 0x7_fff_fff_fff_fff_fff, -0x80_000_001, 0x80_000_000 ].each do |val|
58
+ bin = Hessian2.write(val <= fixnum_max && val >= fixnum_min ? Hessian2::TypeWrapper.new(:long, val) : val)
59
+
60
+ expect(bin[0]).to eq('L')
61
+ expect(bin[1, 8].unpack('q>').first).to eq(val)
62
+ expect(Hessian2.parse(bin)).to eq(val)
63
+ end
64
+ end
65
+
66
+ end
67
+ end
68
+ end