xdr 0.0.4 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bc2054a14c8b40897a81b9758fe8f7d48fa5be07
4
- data.tar.gz: 3bddeb7f3628cb88feae1800467e060080b8b942
2
+ SHA256:
3
+ metadata.gz: cf995b29e360c1ebdc82ee5c94ea470d7d8e87a577263f2faeb8fd3d7fce4a62
4
+ data.tar.gz: ad232ebcb97bef9e00e9fd1103a37cf87941171e5d6fdb89a38addef8ea1afa6
5
5
  SHA512:
6
- metadata.gz: b22b70f5094869e0f09d9819b63746eab3416416eb4a7c2128043888e587dc4e7a5e7a7452e9df925d302d9f771883ca72b76615c9588059c15d9fec793ff59d
7
- data.tar.gz: 6d8bdbafec1e37e2a6a9ade6d139ebd94cf297277e9ff25b676560d6f1d85f70fd8e7e71123d01170e5fcc09a285253a9ce56c303b1fb4f2d84f08e52082c329
6
+ metadata.gz: 7026fd132281c4955332ae9acbd4757c1e0d61e29b900139cc24475e8e347381da3c77f04896ea3841a81b790972fc8bc4fa0c79c36922315283921b6c456836
7
+ data.tar.gz: 9db16c2e581691273a475f6044fcff536accc8a9531c195571b784aaee2534f47409593b54d2c9102072ba9eea8a7871348dbafb789a99eee34e17b3b958d28b
@@ -1,14 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.0
4
- - 2.1.5
5
- - 2.0.0
6
- - 1.9.3
7
- - jruby-1.7.9
8
- - jruby-head
3
+ - 2.2.6
4
+ - 2.3.3
5
+ - 2.4.0
6
+ - jruby
9
7
  notifications:
10
8
  slack:
11
9
  secure: fXYggrDRoLB/4yvyW0kWwyrV5yWa/GC0btPyGu7Hx6ZOaXDC+ejiXSfx7nRyY+uZBs5UF12O4gkUXwBbnWDT5JtQRxzZd5s0cyeGQfAakALexI+FuR2jDcV1prCCaYI4IYoUt61MlfDmuCYVm8hGZ3qsgk/GPHHPnZ8a1FBd2ls=
12
- matrix:
13
- allow_failures:
14
- - rvm: jruby-head
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this
4
+ file. This project adheres to [Semantic Versioning](http://semver.org/).
5
+
6
+ As this project is pre 1.0, breaking changes may happen for minor version
7
+ bumps. A breaking change will get clearly notified in this log.
8
+
9
+ ## [Unreleased](https://github.com/stellar/ruby-xdr/compare/v3.0.1...master)
10
+
11
+ ## [3.0.1](https://github.com/stellar/ruby-xdr/compare/v3.0.0...v3.0.1)
12
+
13
+
14
+ ### Added
15
+ - Add encoding parameter to Union#to_xdr ((#7)[https://github.com/stellar/ruby-xdr/pull/7]).
16
+
17
+ ### Fixed
18
+ - Padding bytes are now properly validated when reading xdr values. According to the XDR spec, padding must be zeros.
19
+
20
+ ## [1.0.0](https://github.com/stellar/ruby-xdr/compare/v0.1.0...v1.0.0)
21
+
22
+ ### Added
23
+ - the `to_xdr` helpers can take a second parameter that will encode the resulting output to hex or base64 when requested.
24
+ - the `from_xdr` helpers can take a second parameter that will trigger a decode from hex or base64 of the provided string before decoding from xdr.
25
+
26
+ ### Changed
27
+
28
+ - `from_xdr` raises an ArgumentError when the input data is not fully consumed
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # XDR, for Ruby
2
2
 
3
+ [![Build Status](https://travis-ci.org/stellar/ruby-xdr.svg?branch=master)](https://travis-ci.org/stellar/ruby-xdr)
4
+ [![Code Climate](https://codeclimate.com/github/stellar/ruby-xdr/badges/gpa.svg)](https://codeclimate.com/github/stellar/ruby-xdr)
5
+
3
6
  XDR is an open data format, specified in [RFC 4506](http://tools.ietf.org/html/rfc4506.html). This library provides a way to read and write XDR data from ruby. It can read/write all of the primitive XDR types and also provides facilities to define readers for the compound XDR types (enums, structs and unions)
4
7
 
5
8
  ## Installation
data/lib/xdr.rb CHANGED
@@ -10,7 +10,6 @@ require "active_support/core_ext/hash/indifferent_access"
10
10
  require "active_support/core_ext/string/inflections"
11
11
  require "active_support/logger"
12
12
  require "active_support/ordered_hash"
13
- require "backports/2.1.0"
14
13
 
15
14
  module XDR
16
15
  extend ActiveSupport::Autoload
@@ -1,3 +1,5 @@
1
+ require 'base64'
2
+
1
3
  module XDR::Concerns::ConvertsToXDR
2
4
  include XDR::Concerns::ReadsBytes
3
5
 
@@ -37,11 +39,19 @@ module XDR::Concerns::ConvertsToXDR
37
39
  # @param val [Object] the value to serialize
38
40
  #
39
41
  # @return [String] the produced bytes
40
- def to_xdr(val)
41
- StringIO.
42
+ def to_xdr(val, encoding='raw')
43
+ raw = StringIO.
42
44
  new.
43
45
  tap{|io| write(val, io)}.
44
46
  string.force_encoding("ASCII-8BIT")
47
+
48
+ case encoding.to_s
49
+ when 'raw' ; raw
50
+ when 'base64' ; Base64.strict_encode64(raw)
51
+ when 'hex' ; raw.unpack("H*").first
52
+ else
53
+ raise ArgumentError, "Invalid encoding #{encoding.inspect}: must be 'raw', 'base64', or 'hex'"
54
+ end
45
55
  end
46
56
 
47
57
  #
@@ -50,9 +60,23 @@ module XDR::Concerns::ConvertsToXDR
50
60
  # @param string [String] the bytes to read from
51
61
  #
52
62
  # @return [Object] the deserialized value
53
- def from_xdr(string)
54
- io = StringIO.new(string)
55
- read(io)
63
+ def from_xdr(string, encoding='raw')
64
+ raw = case encoding
65
+ when 'raw' ; string
66
+ when 'base64' ; Base64.strict_decode64(string)
67
+ when 'hex' ; [string].pack("H*")
68
+ else
69
+ raise ArgumentError, "Invalid encoding #{encoding.inspect}: must be 'raw', 'base64', or 'hex'"
70
+ end
71
+
72
+ io = StringIO.new(raw)
73
+ result = read(io)
74
+
75
+ if io.pos != io.length
76
+ raise ArgumentError, "Input string not fully consumed! are you decoding the right xdr type?"
77
+ end
78
+
79
+ result
56
80
  end
57
81
 
58
82
  private
@@ -64,4 +88,4 @@ module XDR::Concerns::ConvertsToXDR
64
88
  when 3 ; 1
65
89
  end
66
90
  end
67
- end
91
+ end
@@ -5,4 +5,12 @@ module XDR::Concerns::ReadsBytes
5
5
  raise EOFError if bytes.nil? || bytes.length != length
6
6
  end
7
7
  end
8
+
9
+ def read_zeros(io, length)
10
+ read_bytes(io, length).each_byte do |byte|
11
+ raise XDR::ReadError unless byte == 0
12
+ end
13
+
14
+ nil
15
+ end
8
16
  end
@@ -2,7 +2,7 @@ module XDR::DSL::Enum
2
2
 
3
3
  def member(name, value)
4
4
  raise ArgumentError, "#{self} is sealed" if self.sealed
5
- raise ArgumentError, "#{value} is not Fixnum" unless value.is_a?(Fixnum)
5
+ raise ArgumentError, "#{value} is not Integer" unless value.is_a?(Integer)
6
6
  raise ArgumentError, "#{value} is already used" unless
7
7
 
8
8
  name = name.to_s.underscore
@@ -12,7 +12,7 @@ class XDR::Opaque
12
12
  def read(io)
13
13
  # read and return @length bytes
14
14
  # throw away @padding bytes
15
- read_bytes(io, @length).tap{ read_bytes(io, @padding) }
15
+ read_bytes(io, @length).tap{ read_zeros(io, @padding) }
16
16
  end
17
17
 
18
18
  def write(val,io)
@@ -31,6 +31,6 @@ class XDR::String
31
31
 
32
32
  # read and return length bytes
33
33
  # throw away padding bytes
34
- read_bytes(io, length).tap{ read_bytes(io, padding) }
34
+ read_bytes(io, length).tap{ read_zeros(io, padding) }
35
35
  end
36
36
  end
@@ -9,7 +9,7 @@ class XDR::Struct
9
9
 
10
10
  attribute_method_prefix 'read_'
11
11
  attribute_method_suffix 'write_'
12
-
12
+
13
13
  class_attribute :fields
14
14
  self.fields = ActiveSupport::OrderedHash.new
15
15
 
@@ -68,6 +68,14 @@ class XDR::Struct
68
68
  other.attributes == self.attributes
69
69
  end
70
70
 
71
+ def eql? (other)
72
+ return false unless other.is_a?(self.class)
73
+ other.attributes.eql? self.attributes
74
+ end
75
+
76
+ def hash
77
+ [self.class, self.attributes].hash
78
+ end
71
79
 
72
80
  def read_attribute(attr)
73
81
  @attributes[attr]
@@ -75,8 +75,14 @@ class XDR::Union
75
75
  set(switch, value) unless switch == :__unset__
76
76
  end
77
77
 
78
- def to_xdr
79
- self.class.to_xdr self
78
+ #
79
+ # Serializes struct to xdr, return a string of bytes
80
+ #
81
+ # @param format=:raw [Symbol] The encoding used for the bytes produces, one of (:raw, :hex, :base64)
82
+ #
83
+ # @return [String] The encoded bytes of this struct
84
+ def to_xdr(format=:raw)
85
+ self.class.to_xdr(self, format)
80
86
  end
81
87
 
82
88
  def set(switch, value=:void)
@@ -114,6 +120,16 @@ class XDR::Union
114
120
  other.value == self.value
115
121
  end
116
122
 
123
+ def eql?(other)
124
+ return false unless other.is_a?(self.class)
125
+ return false unless other.switch.eql? self.switch
126
+ other.value.eql? self.value
127
+ end
128
+
129
+ def hash
130
+ [self.class, self.switch, self.value].hash
131
+ end
132
+
117
133
  private
118
134
  def valid_for_arm_type(value, arm)
119
135
  arm_type = arms[@arm]
@@ -31,6 +31,6 @@ class XDR::VarOpaque
31
31
 
32
32
  # read and return length bytes
33
33
  # throw away padding bytes
34
- read_bytes(io, length).tap{ read_bytes(io, padding) }
34
+ read_bytes(io, length).tap{ read_zeros(io, padding) }
35
35
  end
36
36
  end
@@ -1,3 +1,3 @@
1
1
  module XDR
2
- VERSION = "0.0.4"
2
+ VERSION = "3.0.1"
3
3
  end
@@ -23,14 +23,47 @@ describe XDR::Concerns::ConvertsToXDR, "#to_xdr" do
23
23
  expect(subject).to receive(:write).with("hiya", kind_of(StringIO))
24
24
  subject.to_xdr("hiya")
25
25
  end
26
+
27
+ context "using an actual xdr type" do
28
+ subject{ XDR::Opaque.new(4) }
29
+
30
+ it "encodes to hex" do
31
+ r = subject.to_xdr("\x00\x01\x02\x03", "hex")
32
+ expect(r).to eql("00010203")
33
+ end
34
+
35
+ it "encodes to base64" do
36
+ r = subject.to_xdr("\x00\x01\x02\x03", "base64")
37
+ expect(r).to eql("AAECAw==")
38
+ end
39
+ end
26
40
  end
27
41
 
28
42
  describe XDR::Concerns::ConvertsToXDR, "#from_xdr" do
29
43
  subject{ ImplementedConvertible.new }
30
44
 
31
- it "calls through to write" do
32
- expect(subject).to receive(:read).with(kind_of(StringIO))
45
+ it "calls through to read" do
46
+ allow(subject).to receive(:read).and_call_original
33
47
  subject.from_xdr("hiya")
48
+ expect(subject).to have_received(:read).with(kind_of(StringIO))
49
+ end
50
+
51
+ context "using an actual xdr type" do
52
+ subject{ XDR::Opaque.new(4) }
53
+
54
+ it "decodes from hex" do
55
+ r = subject.from_xdr("00010203", "hex")
56
+ expect(r).to eql("\x00\x01\x02\x03")
57
+ end
58
+
59
+ it "decodes from base64" do
60
+ r = subject.from_xdr("AAECAw==", "base64")
61
+ expect(r).to eql("\x00\x01\x02\x03")
62
+ end
63
+
64
+ it "raises an ArgumentError if the input is not fully consumed" do
65
+ expect{ subject.from_xdr("\x00\x00\x00\x00\x00") }.to raise_error(ArgumentError)
66
+ end
34
67
  end
35
68
  end
36
69
 
@@ -42,7 +75,7 @@ class ImplementedConvertible
42
75
  include XDR::Concerns::ConvertsToXDR
43
76
 
44
77
  def read(io)
45
- read_bytes(4)
78
+ read_bytes(io, 4)
46
79
  end
47
80
 
48
81
  def write(val, io)
@@ -52,4 +85,4 @@ class ImplementedConvertible
52
85
  def valid?(val)
53
86
  true
54
87
  end
55
- end
88
+ end
@@ -3,6 +3,7 @@ require 'spec_helper'
3
3
  class TestReader
4
4
  include XDR::Concerns::ReadsBytes
5
5
  public :read_bytes
6
+ public :read_zeros
6
7
  end
7
8
 
8
9
 
@@ -28,4 +29,29 @@ describe XDR::Concerns::ReadsBytes, "#read_bytes" do
28
29
  io = StringIO.new(str)
29
30
  subject.read_bytes(io, length)
30
31
  end
32
+ end
33
+
34
+
35
+ describe XDR::Concerns::ReadsBytes, "#read_zeros" do
36
+ subject{ TestReader.new }
37
+
38
+ it "raises XDR::ReadError when the bytes read do not equal zero" do
39
+ expect{ read("\x01", 1) }.to raise_error(XDR::ReadError)
40
+ end
41
+
42
+ it "succeeds when all the bytes read are zero" do
43
+ expect{ read("\x00\x00\x00\x00", 1) }.to_not raise_error
44
+ expect{ read("\x00\x00\x00\x00", 2) }.to_not raise_error
45
+ expect{ read("\x00\x00\x00\x00", 3) }.to_not raise_error
46
+ expect{ read("\x00\x00\x00\x00", 4) }.to_not raise_error
47
+ end
48
+
49
+ it "raises EOFError when the requested length goes beyond the length of the stream" do
50
+ expect{ read("\x00\x00\x00\x00", 5) }.to raise_error(EOFError)
51
+ end
52
+
53
+ def read(str, length)
54
+ io = StringIO.new(str)
55
+ subject.read_zeros(io, length)
56
+ end
31
57
  end
@@ -15,7 +15,7 @@ describe XDR::DSL::Enum, "#member" do
15
15
  expect(subject.members[:two]).to eq(subject.two)
16
16
  end
17
17
 
18
- it "raises ArgumentError if a non-fixnum value is used" do
18
+ it "raises ArgumentError if a non-integer value is used" do
19
19
  expect {
20
20
  Class.new(XDR::Enum) do
21
21
  member :one, "hi!"
@@ -9,6 +9,10 @@ describe XDR::Opaque, "#read" do
9
9
  expect(read("\x00\x01\x00\x00")).to eq("\x00\x01\x00")
10
10
  end
11
11
 
12
+ it "raises a ReadError when the padding isn't zeros" do
13
+ expect{ read "\x00\x00\x01\x01" }.to raise_error(XDR::ReadError)
14
+ end
15
+
12
16
  def read(str)
13
17
  io = StringIO.new(str)
14
18
  subject.read(io)
@@ -14,6 +14,12 @@ describe XDR::String, "#read" do
14
14
  expect{ read "\x00\x00\x00\x04hiya" }.to raise_error(XDR::ReadError)
15
15
  end
16
16
 
17
+ it "raises a ReadError when the padding isn't zeros" do
18
+ expect{ read "\x00\x00\x00\x01h\x00\x00\x01" }.to raise_error(XDR::ReadError)
19
+ expect{ read "\x00\x00\x00\x01h\x00\x01\x00" }.to raise_error(XDR::ReadError)
20
+ expect{ read "\x00\x00\x00\x01h\x01\x00\x00" }.to raise_error(XDR::ReadError)
21
+ end
22
+
17
23
  def read(str)
18
24
  io = StringIO.new(str)
19
25
  subject.read(io)
@@ -186,6 +186,16 @@ describe XDR::Union, "#switch" do
186
186
  end
187
187
  end
188
188
 
189
+ describe XDR::Union, "#to_xdr" do
190
+ subject { UnionSpec::Result.new(:error, "spec error") }
191
+
192
+ context "with base64 encoding" do
193
+ it "returns base64 encoding of union's XDR" do
194
+ expect(subject.to_xdr(:base64)).to eq("AAAAAQAAAApzcGVjIGVycm9yAAA=")
195
+ end
196
+ end
197
+ end
198
+
189
199
  module UnionSpec
190
200
  class ResultType < XDR::Enum
191
201
  member :ok, 0
@@ -15,6 +15,13 @@ describe XDR::VarOpaque, "#read" do
15
15
  expect{ read "\x00\x00\x00\x03\x00\x00\x00\x00" }.to raise_error(XDR::ReadError)
16
16
  end
17
17
 
18
+
19
+ it "raises a ReadError when the padding isn't zeros" do
20
+ expect{ read "\x00\x00\x00\x01\x01\x00\x00\x01" }.to raise_error(XDR::ReadError)
21
+ expect{ read "\x00\x00\x00\x01\x01\x00\x01\x00" }.to raise_error(XDR::ReadError)
22
+ expect{ read "\x00\x00\x00\x01\x01\x01\x00\x00" }.to raise_error(XDR::ReadError)
23
+ end
24
+
18
25
  def read(str)
19
26
  io = StringIO.new(str)
20
27
  subject.read(io)
@@ -11,17 +11,16 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = %q{XDR Helper Library}
12
12
  spec.homepage = "https://github.com/stellar/ruby-xdr"
13
13
  spec.license = "Apache 2.0"
14
+ spec.required_ruby_version = '>= 2.2.0'
14
15
 
15
16
  spec.files = `git ls-files -z`.split("\x0")
16
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
19
  spec.require_paths = ["lib"]
20
+ spec.add_dependency "activesupport", ">= 5.2.0"
21
+ spec.add_dependency "activemodel", ">= 5.2.0"
19
22
 
20
- spec.add_dependency "activesupport", "~> 4"
21
- spec.add_dependency "activemodel", "~> 4"
22
- spec.add_dependency "backports", "~> 3.6"
23
-
24
- spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "bundler", "~> 2.1.4"
25
24
  spec.add_development_dependency "rake", "~> 10.0"
26
25
  spec.add_development_dependency "rspec", "~> 3.1"
27
26
  spec.add_development_dependency "guard-rspec"
metadata CHANGED
@@ -1,71 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xdr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Fleckenstein
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-09 00:00:00.000000000 Z
11
+ date: 2020-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4'
19
+ version: 5.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '4'
26
+ version: 5.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '4'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '4'
41
- - !ruby/object:Gem::Dependency
42
- name: backports
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
31
+ - - ">="
46
32
  - !ruby/object:Gem::Version
47
- version: '3.6'
33
+ version: 5.2.0
48
34
  type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - "~>"
38
+ - - ">="
53
39
  - !ruby/object:Gem::Version
54
- version: '3.6'
40
+ version: 5.2.0
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '1.7'
47
+ version: 2.1.4
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '1.7'
54
+ version: 2.1.4
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rake
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -132,6 +118,7 @@ files:
132
118
  - ".gitignore"
133
119
  - ".travis.yml"
134
120
  - ".yardopts"
121
+ - CHANGELOG.md
135
122
  - Gemfile
136
123
  - Guardfile
137
124
  - LICENSE.txt
@@ -215,15 +202,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
202
  requirements:
216
203
  - - ">="
217
204
  - !ruby/object:Gem::Version
218
- version: '0'
205
+ version: 2.2.0
219
206
  required_rubygems_version: !ruby/object:Gem::Requirement
220
207
  requirements:
221
208
  - - ">="
222
209
  - !ruby/object:Gem::Version
223
210
  version: '0'
224
211
  requirements: []
225
- rubyforge_project:
226
- rubygems_version: 2.2.2
212
+ rubygems_version: 3.0.3
227
213
  signing_key:
228
214
  specification_version: 4
229
215
  summary: XDR Helper Library
@@ -254,4 +240,3 @@ test_files:
254
240
  - spec/lib/xdr/void_spec.rb
255
241
  - spec/spec_helper.rb
256
242
  - spec/support/matchers/eq_bytes.rb
257
- has_rdoc: