payshares-xdr 0.0.2
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 +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +14 -0
- data/.yardopts +7 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +202 -0
- data/README.md +106 -0
- data/Rakefile +9 -0
- data/examples/enum.rb +30 -0
- data/examples/struct.rb +24 -0
- data/examples/union.rb +36 -0
- data/lib/xdr.rb +73 -0
- data/lib/xdr/array.rb +28 -0
- data/lib/xdr/bool.rb +24 -0
- data/lib/xdr/concerns/array_converter.rb +5 -0
- data/lib/xdr/concerns/converts_to_xdr.rb +67 -0
- data/lib/xdr/concerns/float_converter.rb +5 -0
- data/lib/xdr/concerns/integer_converter.rb +5 -0
- data/lib/xdr/concerns/reads_bytes.rb +8 -0
- data/lib/xdr/concerns/string_converter.rb +5 -0
- data/lib/xdr/double.rb +14 -0
- data/lib/xdr/dsl.rb +7 -0
- data/lib/xdr/dsl/enum.rb +24 -0
- data/lib/xdr/dsl/struct.rb +13 -0
- data/lib/xdr/dsl/union.rb +32 -0
- data/lib/xdr/enum.rb +48 -0
- data/lib/xdr/float.rb +14 -0
- data/lib/xdr/hyper.rb +14 -0
- data/lib/xdr/int.rb +14 -0
- data/lib/xdr/namespace.rb +26 -0
- data/lib/xdr/opaque.rb +28 -0
- data/lib/xdr/option.rb +30 -0
- data/lib/xdr/quadruple.rb +5 -0
- data/lib/xdr/rpc.rb +6 -0
- data/lib/xdr/rpc/record.rb +7 -0
- data/lib/xdr/rpc/record_reader.rb +16 -0
- data/lib/xdr/string.rb +36 -0
- data/lib/xdr/struct.rb +51 -0
- data/lib/xdr/struct_validator.rb +6 -0
- data/lib/xdr/union.rb +101 -0
- data/lib/xdr/union_validator.rb +7 -0
- data/lib/xdr/unsigned_hyper.rb +14 -0
- data/lib/xdr/unsigned_int.rb +14 -0
- data/lib/xdr/var_array.rb +38 -0
- data/lib/xdr/var_opaque.rb +36 -0
- data/lib/xdr/version.rb +3 -0
- data/lib/xdr/void.rb +14 -0
- data/payshares-xdr.gemspec +29 -0
- data/spec/lib/xdr/array_spec.rb +73 -0
- data/spec/lib/xdr/bool_spec.rb +43 -0
- data/spec/lib/xdr/concerns/converts_to_xdr_spec.rb +55 -0
- data/spec/lib/xdr/concerns/reads_bytes_spec.rb +31 -0
- data/spec/lib/xdr/double_spec.rb +38 -0
- data/spec/lib/xdr/dsl/enum_spec.rb +44 -0
- data/spec/lib/xdr/dsl/struct_spec.rb +29 -0
- data/spec/lib/xdr/dsl/union_spec.rb +22 -0
- data/spec/lib/xdr/enum_spec.rb +70 -0
- data/spec/lib/xdr/float_spec.rb +37 -0
- data/spec/lib/xdr/hyper_spec.rb +40 -0
- data/spec/lib/xdr/int_spec.rb +40 -0
- data/spec/lib/xdr/opaque_spec.rb +36 -0
- data/spec/lib/xdr/option_spec.rb +36 -0
- data/spec/lib/xdr/quadruple_spec.rb +14 -0
- data/spec/lib/xdr/rpc/record_reader_spec.rb +27 -0
- data/spec/lib/xdr/string_spec.rb +41 -0
- data/spec/lib/xdr/struct_spec.rb +101 -0
- data/spec/lib/xdr/union_spec.rb +248 -0
- data/spec/lib/xdr/unsigned_hyper_spec.rb +36 -0
- data/spec/lib/xdr/unsigned_int_spec.rb +36 -0
- data/spec/lib/xdr/var_array_spec.rb +71 -0
- data/spec/lib/xdr/var_opaque_spec.rb +43 -0
- data/spec/lib/xdr/void_spec.rb +46 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/matchers/eq_bytes.rb +6 -0
- metadata +257 -0
data/lib/xdr/opaque.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class XDR::Opaque
|
2
|
+
include XDR::Concerns::ConvertsToXDR
|
3
|
+
include XDR::Concerns::StringConverter
|
4
|
+
|
5
|
+
singleton_class.send(:alias_method, :[], :new)
|
6
|
+
|
7
|
+
def initialize(length)
|
8
|
+
@length = length
|
9
|
+
@padding = padding_for length
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(io)
|
13
|
+
# read and return @length bytes
|
14
|
+
# throw away @padding bytes
|
15
|
+
read_bytes(io, @length).tap{ read_bytes(io, @padding) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def write(val,io)
|
19
|
+
length = val.bytesize
|
20
|
+
|
21
|
+
if val.length != @length
|
22
|
+
raise XDR::WriteError, "Value length is #{length}, must be #{@length}"
|
23
|
+
end
|
24
|
+
|
25
|
+
io.write val
|
26
|
+
io.write "\x00" * @padding
|
27
|
+
end
|
28
|
+
end
|
data/lib/xdr/option.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
class XDR::Option
|
2
|
+
include XDR::Concerns::ConvertsToXDR
|
3
|
+
|
4
|
+
singleton_class.send(:alias_method, :[], :new)
|
5
|
+
|
6
|
+
attr_reader :child_type
|
7
|
+
|
8
|
+
def initialize(child_type)
|
9
|
+
#TODO, raise an error if child_type is not ConvertToXDR
|
10
|
+
@child_type = child_type
|
11
|
+
end
|
12
|
+
|
13
|
+
def write(val, io)
|
14
|
+
if val.present?
|
15
|
+
XDR::Bool.write(true, io)
|
16
|
+
@child_type.write(val, io)
|
17
|
+
else
|
18
|
+
XDR::Bool.write(false, io)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def read(io)
|
23
|
+
present = XDR::Bool.read(io)
|
24
|
+
@child_type.read(io) if present
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?(val)
|
28
|
+
val.nil? || @child_type.valid?(val)
|
29
|
+
end
|
30
|
+
end
|
data/lib/xdr/rpc.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class XDR::RPC::RecordReader
|
2
|
+
include XDR::Concerns::ReadsBytes
|
3
|
+
|
4
|
+
LAST_MASK = 0x80000000
|
5
|
+
LENGTH_MASK = 0x7FFFFFFF
|
6
|
+
|
7
|
+
def read(io)
|
8
|
+
header = read_bytes(io, 4).unpack("L>").first
|
9
|
+
length = header & LENGTH_MASK
|
10
|
+
last = (header & LAST_MASK) > 0
|
11
|
+
raw_content = read_bytes(io, length)
|
12
|
+
content = StringIO.new(raw_content)
|
13
|
+
|
14
|
+
XDR::RPC::Record.new(last, length, content)
|
15
|
+
end
|
16
|
+
end
|
data/lib/xdr/string.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
class XDR::String
|
2
|
+
include XDR::Concerns::ConvertsToXDR
|
3
|
+
include XDR::Concerns::StringConverter
|
4
|
+
|
5
|
+
singleton_class.send(:alias_method, :[], :new)
|
6
|
+
|
7
|
+
def initialize(length=XDR::MAX_SIZE)
|
8
|
+
@length = length
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(val, io)
|
12
|
+
length = val.bytesize
|
13
|
+
|
14
|
+
if length > @length
|
15
|
+
raise XDR::WriteError, "Value length #{length} exceeds max #{@length}"
|
16
|
+
end
|
17
|
+
|
18
|
+
XDR::Int.write(length, io)
|
19
|
+
io.write val
|
20
|
+
io.write "\x00" * padding_for(length)
|
21
|
+
end
|
22
|
+
|
23
|
+
def read(io)
|
24
|
+
length = XDR::Int.read(io)
|
25
|
+
|
26
|
+
if length > @length
|
27
|
+
raise XDR::ReadError, "String length #{length} is greater than max"
|
28
|
+
end
|
29
|
+
|
30
|
+
padding = padding_for length
|
31
|
+
|
32
|
+
# read and return length bytes
|
33
|
+
# throw away padding bytes
|
34
|
+
read_bytes(io, length).tap{ read_bytes(io, padding) }
|
35
|
+
end
|
36
|
+
end
|
data/lib/xdr/struct.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
class XDR::Struct
|
4
|
+
include ActiveModel::Model
|
5
|
+
include ActiveModel::AttributeMethods
|
6
|
+
|
7
|
+
extend XDR::Concerns::ConvertsToXDR
|
8
|
+
extend XDR::DSL::Struct
|
9
|
+
|
10
|
+
class_attribute :fields
|
11
|
+
self.fields = ActiveSupport::OrderedHash.new
|
12
|
+
|
13
|
+
validates_with XDR::StructValidator
|
14
|
+
|
15
|
+
def self.read(io)
|
16
|
+
new.tap do |result|
|
17
|
+
fields.each do |name, type|
|
18
|
+
result.public_send("#{name}=", type.read(io))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.write(val, io)
|
24
|
+
fields.each do |name, type|
|
25
|
+
field_val = val.public_send(name)
|
26
|
+
type.write(field_val, io)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.valid?(val)
|
31
|
+
val.is_a?(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Serializes struct to xdr, return a string of bytes
|
36
|
+
#
|
37
|
+
# @param format=:raw [Symbol] The encoding used for the bytes produces, one of (:raw, :hex, :base64)
|
38
|
+
#
|
39
|
+
# @return [String] The encoded bytes of this struct
|
40
|
+
def to_xdr(format=:raw)
|
41
|
+
raw = self.class.to_xdr(self)
|
42
|
+
|
43
|
+
case format
|
44
|
+
when :raw ; raw
|
45
|
+
when :hex ; raw.unpack("H*").first
|
46
|
+
when :base64 ; Base64.strict_encode64(raw)
|
47
|
+
else ;
|
48
|
+
raise ArgumentError, "Invalid format #{format.inspect}; must be :raw, :hex, or :base64"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/xdr/union.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
class XDR::Union
|
2
|
+
include ActiveModel::Model
|
3
|
+
include ActiveModel::AttributeMethods
|
4
|
+
|
5
|
+
extend XDR::Concerns::ConvertsToXDR
|
6
|
+
extend XDR::DSL::Union
|
7
|
+
|
8
|
+
|
9
|
+
class_attribute :arms
|
10
|
+
class_attribute :switches
|
11
|
+
class_attribute :switch_type
|
12
|
+
class_attribute :switch_name
|
13
|
+
attr_reader :switch
|
14
|
+
attr_reader :arm
|
15
|
+
|
16
|
+
self.arms = ActiveSupport::OrderedHash.new
|
17
|
+
self.switches = ActiveSupport::OrderedHash.new
|
18
|
+
self.switch_type = nil
|
19
|
+
self.switch_name = nil
|
20
|
+
|
21
|
+
attribute_method_suffix '!'
|
22
|
+
|
23
|
+
def self.arm_for_switch(switch)
|
24
|
+
raise XDR::InvalidSwitchError unless switch.is_a?(switch_type)
|
25
|
+
|
26
|
+
result = switches.fetch(switch, :switch_not_found)
|
27
|
+
result = switches.fetch(:default, :switch_not_found) if result == :switch_not_found
|
28
|
+
|
29
|
+
if result == :switch_not_found
|
30
|
+
raise XDR::InvalidSwitchError, "Bad switch: #{switch}"
|
31
|
+
end
|
32
|
+
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.read(io)
|
37
|
+
switch = switch_type.read(io)
|
38
|
+
arm = arm_for_switch(switch)
|
39
|
+
arm_type = arms[arm] || XDR::Void
|
40
|
+
value = arm_type.read(io)
|
41
|
+
new(switch, value)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.write(val, io)
|
45
|
+
switch_type.write(val.switch, io)
|
46
|
+
arm_type = arms[val.arm] || XDR::Void
|
47
|
+
arm_type.write(val.get,io)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.valid?(val)
|
51
|
+
val.is_a?(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize(switch=nil, value=:void)
|
55
|
+
@switch = nil
|
56
|
+
@arm = nil
|
57
|
+
@value = nil
|
58
|
+
set(switch, value) if switch
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_xdr
|
62
|
+
self.class.to_xdr self
|
63
|
+
end
|
64
|
+
|
65
|
+
def set(switch, value=:void)
|
66
|
+
@switch = switch.is_a?(switch_type) ? switch : switch_type.from_name(switch)
|
67
|
+
@arm = self.class.arm_for_switch @switch
|
68
|
+
|
69
|
+
raise XDR::InvalidValueError unless valid_for_arm_type(value, @arm)
|
70
|
+
|
71
|
+
@value = value
|
72
|
+
rescue XDR::EnumNameError
|
73
|
+
raise XDR::InvalidSwitchError, "Bad switch: #{switch}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def value
|
77
|
+
@value unless @value == :void
|
78
|
+
end
|
79
|
+
|
80
|
+
alias get value
|
81
|
+
|
82
|
+
def attribute!(attr)
|
83
|
+
if @arm.to_s != attr
|
84
|
+
raise XDR::ArmNotSetError, "#{attr} is not the set arm"
|
85
|
+
end
|
86
|
+
|
87
|
+
get
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
def valid_for_arm_type(value, arm)
|
92
|
+
arm_type = arms[@arm]
|
93
|
+
|
94
|
+
return value == :void if arm_type.nil?
|
95
|
+
|
96
|
+
arm_type.valid?(value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module XDR::UnsignedHyper
|
2
|
+
extend XDR::Concerns::ConvertsToXDR
|
3
|
+
extend XDR::Concerns::IntegerConverter
|
4
|
+
|
5
|
+
def self.write(val, io)
|
6
|
+
raise XDR::WriteError, "val is not Integer" unless val.is_a?(Integer)
|
7
|
+
# TODO: check bounds
|
8
|
+
io.write [val].pack("Q>")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.read(io)
|
12
|
+
read_bytes(io, 8).unpack("Q>").first
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module XDR::UnsignedInt
|
2
|
+
extend XDR::Concerns::ConvertsToXDR
|
3
|
+
extend XDR::Concerns::IntegerConverter
|
4
|
+
|
5
|
+
def self.write(val, io)
|
6
|
+
raise XDR::WriteError, "val is not Integer" unless val.is_a?(Integer)
|
7
|
+
# TODO: check bounds
|
8
|
+
io.write [val].pack("L>")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.read(io)
|
12
|
+
read_bytes(io, 4).unpack("L>").first
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class XDR::VarArray
|
2
|
+
include XDR::Concerns::ConvertsToXDR
|
3
|
+
include XDR::Concerns::ArrayConverter
|
4
|
+
|
5
|
+
singleton_class.send(:alias_method, :[], :new)
|
6
|
+
|
7
|
+
def initialize(child_type, length=XDR::MAX_SIZE)
|
8
|
+
@child_type = child_type
|
9
|
+
@length = length
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(val, io)
|
13
|
+
length = val.length
|
14
|
+
|
15
|
+
if length > @length
|
16
|
+
raise XDR::WriteError, "Value length #{length} exceeds max #{@length}"
|
17
|
+
end
|
18
|
+
|
19
|
+
XDR::Int.write(length, io)
|
20
|
+
val.each do |member|
|
21
|
+
@child_type.write member, io
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def read(io)
|
26
|
+
length = XDR::Int.read(io)
|
27
|
+
|
28
|
+
if length > @length
|
29
|
+
raise XDR::ReadError, "VarArray length #{length} is greater than max #{@length}"
|
30
|
+
end
|
31
|
+
|
32
|
+
length.times.map{ @child_type.read(io) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?(val)
|
36
|
+
super(val) && val.length <= @length
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class XDR::VarOpaque
|
2
|
+
include XDR::Concerns::ConvertsToXDR
|
3
|
+
include XDR::Concerns::StringConverter
|
4
|
+
|
5
|
+
singleton_class.send(:alias_method, :[], :new)
|
6
|
+
|
7
|
+
def initialize(length=XDR::MAX_SIZE)
|
8
|
+
@length = length
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(val, io)
|
12
|
+
length = val.bytesize
|
13
|
+
|
14
|
+
if length > @length
|
15
|
+
raise XDR::WriteError, "Value length #{length} exceeds max #{@length}"
|
16
|
+
end
|
17
|
+
|
18
|
+
XDR::Int.write(length, io)
|
19
|
+
io.write val
|
20
|
+
io.write "\x00" * padding_for(length)
|
21
|
+
end
|
22
|
+
|
23
|
+
def read(io)
|
24
|
+
length = XDR::Int.read(io)
|
25
|
+
|
26
|
+
if length > @length
|
27
|
+
raise XDR::ReadError, "VarOpaque length #{length}"
|
28
|
+
end
|
29
|
+
|
30
|
+
padding = padding_for length
|
31
|
+
|
32
|
+
# read and return length bytes
|
33
|
+
# throw away padding bytes
|
34
|
+
read_bytes(io, length).tap{ read_bytes(io, padding) }
|
35
|
+
end
|
36
|
+
end
|
data/lib/xdr/version.rb
ADDED
data/lib/xdr/void.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'xdr/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "payshares-xdr"
|
8
|
+
spec.version = XDR::VERSION
|
9
|
+
spec.authors = ["Kedia"]
|
10
|
+
spec.email = ["support@payshares.org"]
|
11
|
+
spec.summary = %q{Payshares XDR Helper Library}
|
12
|
+
spec.homepage = "https://github.com/payshares/ruby-payshares-xdr"
|
13
|
+
spec.license = "Apache 2.0"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "activesupport", "4.1.9"
|
21
|
+
spec.add_dependency "activemodel", "4.1.9"
|
22
|
+
spec.add_dependency "backports", "3.6.4"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "1.17.3"
|
25
|
+
spec.add_development_dependency "rake", "10.4.2"
|
26
|
+
spec.add_development_dependency "rspec", "3.2.0"
|
27
|
+
spec.add_development_dependency "guard-rspec"
|
28
|
+
spec.add_development_dependency "simplecov"
|
29
|
+
end
|