scale.rb 0.1.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.
data/lib/scale.rb ADDED
@@ -0,0 +1,187 @@
1
+ require "scale/version"
2
+
3
+ require "substrate_common"
4
+
5
+ require "scale/base"
6
+ require "scale/types"
7
+
8
+ require "metadata/metadata"
9
+ require "metadata/metadata_v3"
10
+ require "metadata/metadata_v7"
11
+ require "metadata/metadata_v8"
12
+ require "metadata/metadata_v9"
13
+ require "metadata/metadata_v10"
14
+
15
+ module Scale
16
+ class Error < StandardError; end
17
+ # TODO: == implement
18
+
19
+ class Bytes
20
+ attr_reader :data, :bytes
21
+ attr_reader :offset
22
+
23
+ def initialize(data)
24
+ if data.class == Array and data.is_byte_array?
25
+ @bytes = data
26
+ elsif data.class == String and data.start_with?('0x') and data.length % 2 == 0
27
+ arr = data[2..].scan(/../).map(&:hex)
28
+ @bytes = arr
29
+ else
30
+ raise "Provided data is not valid"
31
+ end
32
+
33
+ @data = data
34
+ @offset = 0
35
+ end
36
+
37
+ def reset_offset
38
+ @offset = 0
39
+ end
40
+
41
+ def get_next_bytes(length)
42
+ result = @bytes[@offset ... @offset + length]
43
+ if result.length < length
44
+ str = @data[(2 + @offset * 2)..]
45
+ str = str.length > 40 ? (str[0...40]).to_s + "..." : str
46
+ raise "No enough data: #{str}, expect length: #{length}, but #{result.length}"
47
+ end
48
+ @offset = @offset + length
49
+ result
50
+ end
51
+
52
+ def get_remaining_bytes
53
+ @bytes[offset..]
54
+ @offset = @bytes.length
55
+ result
56
+ end
57
+
58
+ def to_hex_string
59
+ @bytes.bytes_to_hex
60
+ end
61
+
62
+ def to_bin_string
63
+ @bytes.bytes_to_bin
64
+ end
65
+
66
+ def ==(another_object)
67
+ self.bytes == another_object.bytes && self.offset == another_object.offset
68
+ end
69
+ end
70
+
71
+ class TypesLoader
72
+ def self.load(filename)
73
+ path = File.join File.dirname(__FILE__), "types", filename
74
+ content = File.open(path).read
75
+ result = JSON.parse content
76
+
77
+ types = result["default"]
78
+ types.each do |name, body|
79
+ if body.class == String
80
+ target_type = "Scale::Types::#{body}"
81
+ klass = Class.new(target_type.constantize) do
82
+ end
83
+ elsif body.class == Hash
84
+ if body["type"] == "struct"
85
+ struct_params = {}
86
+ body['type_mapping'].each do |mapping|
87
+ struct_params[mapping[0].to_sym] = mapping[1]
88
+ end
89
+ klass = Class.new do
90
+ end
91
+ klass.send(:include, Scale::Types::Struct)
92
+ klass.send(:items, struct_params)
93
+ Scale::Types.const_set name, klass
94
+ elsif body["type"] = "enum"
95
+ klass = Class.new do
96
+ end
97
+ klass.send(:include, Scale::Types::Enum)
98
+ if body["type_mapping"]
99
+ struct_params = {}
100
+ body['type_mapping'].each do |mapping|
101
+ struct_params[mapping[0].to_sym] = mapping[1]
102
+ end
103
+ klass.send(:items, struct_params)
104
+ else
105
+ klass.send(:values, body["value_list"])
106
+ end
107
+ Scale::Types.const_set name, klass
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ end
115
+
116
+ def type_of(type_string, enum_values: nil)
117
+ if type_string.end_with?(">")
118
+ type_strs = type_string.scan(/^([^<]*)<(.+)>$/).first
119
+ type_str = type_strs.first
120
+ inner_type_str = type_strs.last
121
+
122
+ if type_str == "Vec" || type_str == "Option"
123
+ klass = Class.new do
124
+ include type_of(type_str)
125
+ inner_type inner_type_str
126
+ end
127
+ name = "#{type_str}#{klass.object_id}"
128
+ Object.const_set name, klass
129
+ return name.constantize
130
+ else
131
+ raise "#{type_str} not support inner type"
132
+ end
133
+ elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
134
+ # TODO: add nested tuple support
135
+ types_with_inner_type = type_string[1...-1].scan(/([A-Za-z]+<[^>]*>)/).first
136
+
137
+ if not types_with_inner_type.nil?
138
+ types_with_inner_type.each do |type_str|
139
+ new_type_str = type_str.gsub(",", ";")
140
+ type_string = type_string.gsub(type_str, new_type_str)
141
+ end
142
+ end
143
+
144
+ type_strs = type_string[1...-1].split(",").map do |type_str|
145
+ type_str.strip.gsub(";", ",")
146
+ end
147
+
148
+ klass = Class.new do
149
+ include Scale::Types::Tuple
150
+ inner_types *type_strs
151
+ end
152
+ name = "Tuple#{klass.object_id}"
153
+ Object.const_set name, klass
154
+ return name.constantize
155
+ else
156
+ if type_string == 'Enum'
157
+ klass = Class.new do
158
+ include Scale::Types::Enum
159
+ values *enum_values
160
+ end
161
+ name = "Enum#{klass.object_id}"
162
+ Object.const_set name, klass
163
+ return name.constantize
164
+ else
165
+ type_string = (type_string.start_with?("Scale::Types::") ? type_string : "Scale::Types::#{type_string}")
166
+ type_string.constantize
167
+ end
168
+ end
169
+ end
170
+
171
+ def adjust(type)
172
+ type = type.gsub("T::", "")
173
+ .gsub("<T>", "")
174
+ .gsub("<T as Trait>::", "")
175
+ .gsub("\n", "")
176
+ .gsub("EventRecord<Event, Hash>", "EventRecord")
177
+ return "Null" if type == "()"
178
+ return "String" if type == "Vec<u8>"
179
+ return "Address" if type == '<Lookup as StaticLookup>::Source'
180
+ return "Vec<Address>" if type == 'Vec<<Lookup as StaticLookup>::Source>'
181
+ return "CompactBalance" if type == '<Balance as HasCompact>::Type'
182
+ return 'CompactBlockNumber' if type == '<BlockNumber as HasCompact>::Type'
183
+ return 'CompactBalance' if type == '<Balance as HasCompact>::Type'
184
+ return 'CompactMoment' if type == '<Moment as HasCompact>::Type'
185
+ return 'InherentOfflineReport' if type == '<InherentOfflineReport as InherentOfflineReport>::Inherent'
186
+ return type
187
+ end
data/scale.gemspec ADDED
@@ -0,0 +1,43 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "scale/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "scale.rb"
8
+ spec.version = Scale::VERSION
9
+ spec.authors = ["Wu Minzhe"]
10
+ spec.email = ["wuminzhe@gmail.com"]
11
+
12
+ spec.summary = %q{Ruby implementation of the parity SCALE data format}
13
+ spec.description = %q{SCALE - Simple Concatenating Aggregated Little Endians}
14
+ spec.homepage = "https://github.com/itering/scale.rb"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = "exe"
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ["lib"]
36
+
37
+ spec.add_dependency "substrate_common.rb", "~> 0.1.3"
38
+
39
+ spec.add_development_dependency "bundler", "~> 1.17"
40
+ spec.add_development_dependency "rake", "~> 13.0"
41
+ spec.add_development_dependency "rspec", "~> 3.2"
42
+ spec.add_development_dependency "pry"
43
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scale.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Wu Minzhe
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: substrate_common.rb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.17'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.17'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: SCALE - Simple Concatenating Aggregated Little Endians
84
+ email:
85
+ - wuminzhe@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".DS_Store"
91
+ - ".gitignore"
92
+ - Dockerfile
93
+ - Gemfile
94
+ - Gemfile.lock
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - grants_badge.png
101
+ - lib/metadata/metadata.rb
102
+ - lib/metadata/metadata_v10.rb
103
+ - lib/metadata/metadata_v3.rb
104
+ - lib/metadata/metadata_v7.rb
105
+ - lib/metadata/metadata_v8.rb
106
+ - lib/metadata/metadata_v9.rb
107
+ - lib/scale.rb
108
+ - lib/scale/base.rb
109
+ - lib/scale/types.rb
110
+ - lib/scale/version.rb
111
+ - scale.gemspec
112
+ homepage: https://github.com/itering/scale.rb
113
+ licenses:
114
+ - MIT
115
+ metadata:
116
+ allowed_push_host: https://rubygems.org
117
+ homepage_uri: https://github.com/itering/scale.rb
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubygems_version: 3.0.6
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Ruby implementation of the parity SCALE data format
137
+ test_files: []