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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +10 -0
- data/Dockerfile +18 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +49 -0
- data/LICENSE.txt +21 -0
- data/README.md +149 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/grants_badge.png +0 -0
- data/lib/metadata/metadata.rb +127 -0
- data/lib/metadata/metadata_v10.rb +22 -0
- data/lib/metadata/metadata_v3.rb +22 -0
- data/lib/metadata/metadata_v7.rb +123 -0
- data/lib/metadata/metadata_v8.rb +69 -0
- data/lib/metadata/metadata_v9.rb +22 -0
- data/lib/scale/base.rb +322 -0
- data/lib/scale/types.rb +561 -0
- data/lib/scale/version.rb +3 -0
- data/lib/scale.rb +187 -0
- data/scale.gemspec +43 -0
- metadata +137 -0
data/lib/scale/base.rb
ADDED
@@ -0,0 +1,322 @@
|
|
1
|
+
module Scale
|
2
|
+
module Types
|
3
|
+
|
4
|
+
module SingleValue
|
5
|
+
attr_reader :value
|
6
|
+
|
7
|
+
def initialize(value)
|
8
|
+
@value = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(another)
|
12
|
+
self.value == another.value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# value: one of nil, false, true, scale object
|
17
|
+
module Option
|
18
|
+
include SingleValue
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def decode(scale_bytes)
|
22
|
+
byte = scale_bytes.get_next_bytes(1)
|
23
|
+
if byte == [0]
|
24
|
+
return self.new(nil)
|
25
|
+
elsif byte == [1]
|
26
|
+
if self::INNER_TYPE_STR == 'boolean'
|
27
|
+
return self.new(false)
|
28
|
+
else
|
29
|
+
# big process
|
30
|
+
value = type_of(self::INNER_TYPE_STR).decode(scale_bytes)
|
31
|
+
return self.new(value)
|
32
|
+
end
|
33
|
+
elsif byte == [2]
|
34
|
+
if self::INNER_TYPE_STR == 'boolean'
|
35
|
+
return self.new(true)
|
36
|
+
else
|
37
|
+
raise "bad data"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
raise "bad data"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def inner_type(type_str)
|
45
|
+
self.const_set(:INNER_TYPE_STR, type_str)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.included(base)
|
50
|
+
base.extend(ClassMethods)
|
51
|
+
end
|
52
|
+
|
53
|
+
def encode
|
54
|
+
# TODO: add Null type
|
55
|
+
if self.value.nil?
|
56
|
+
"00"
|
57
|
+
else
|
58
|
+
return "02" if self.value.class == TrueClass && self.value === true
|
59
|
+
return "01" if self.value.class == FalseClass && self.value === false
|
60
|
+
"01" + self.value.encode
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module FixedWidthUInt
|
66
|
+
include SingleValue
|
67
|
+
|
68
|
+
module ClassMethods
|
69
|
+
def decode(scale_bytes)
|
70
|
+
class_name = self.to_s
|
71
|
+
bytes = scale_bytes.get_next_bytes self::BYTES_LENGTH
|
72
|
+
bytes_reversed = bytes.reverse
|
73
|
+
hex = bytes_reversed.reduce('0x') { |hex, byte| hex + byte.to_s(16).rjust(2, '0') }
|
74
|
+
self.new(hex.to_i(16))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.included(base)
|
79
|
+
base.extend(ClassMethods)
|
80
|
+
end
|
81
|
+
|
82
|
+
def encode
|
83
|
+
bytes = self.value.to_s(16).rjust(self.class::BYTES_LENGTH*2, '0').scan(/.{2}/).reverse.map {|hex| hex.to_i(16) }
|
84
|
+
bytes.bytes_to_hex[2..]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
module Struct
|
90
|
+
include SingleValue
|
91
|
+
# new(1.to_u32, U32(69))
|
92
|
+
module ClassMethods
|
93
|
+
def decode(scale_bytes)
|
94
|
+
item_values = self::ITEM_TYPE_STRS.map do |item_type_str|
|
95
|
+
type_of(item_type_str).decode(scale_bytes)
|
96
|
+
end
|
97
|
+
|
98
|
+
value = {}
|
99
|
+
self::ITEM_NAMES.zip(item_values) do |attr, val|
|
100
|
+
value[attr] = val
|
101
|
+
end
|
102
|
+
|
103
|
+
result = self.new(value)
|
104
|
+
value.each_pair do |attr, val|
|
105
|
+
result.send "#{attr}=", val
|
106
|
+
end
|
107
|
+
return result
|
108
|
+
end
|
109
|
+
|
110
|
+
def items(**items)
|
111
|
+
attr_names = []
|
112
|
+
attr_type_strs = []
|
113
|
+
|
114
|
+
items.each_pair do |attr_name, attr_type_str|
|
115
|
+
attr_names << attr_name
|
116
|
+
attr_type_strs << attr_type_str
|
117
|
+
end
|
118
|
+
|
119
|
+
self.const_set(:ITEM_NAMES, attr_names)
|
120
|
+
self.const_set(:ITEM_TYPE_STRS, attr_type_strs)
|
121
|
+
self.attr_accessor *attr_names
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.included(base)
|
126
|
+
base.extend ClassMethods
|
127
|
+
end
|
128
|
+
|
129
|
+
def encode
|
130
|
+
[].tap do |result|
|
131
|
+
self.value.each_pair do |attr_name, attr_value|
|
132
|
+
result << attr_value.encode
|
133
|
+
end
|
134
|
+
end.join
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
module Tuple
|
139
|
+
include SingleValue
|
140
|
+
|
141
|
+
module ClassMethods
|
142
|
+
def decode(scale_bytes)
|
143
|
+
values = self::TYPE_STRS.map do |type_str|
|
144
|
+
type_of(type_str).decode(scale_bytes)
|
145
|
+
end
|
146
|
+
return self.new(values)
|
147
|
+
end
|
148
|
+
|
149
|
+
def inner_types(*type_strs)
|
150
|
+
self.const_set(:TYPE_STRS, type_strs)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.included(base)
|
155
|
+
base.extend(ClassMethods)
|
156
|
+
end
|
157
|
+
|
158
|
+
def encode
|
159
|
+
self.value.map(&:encode).join
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
module Enum
|
164
|
+
include SingleValue
|
165
|
+
|
166
|
+
module ClassMethods
|
167
|
+
def decode(scale_bytes)
|
168
|
+
index = scale_bytes.get_next_bytes(1)[0]
|
169
|
+
if self.const_defined? "ITEM_NAMES"
|
170
|
+
item_type_str = self::ITEM_TYPE_STRS[index]
|
171
|
+
raise "There is no such member with index #{index} for enum #{self}" if item_type_str.nil?
|
172
|
+
value = type_of(item_type_str).decode(scale_bytes)
|
173
|
+
return self.new(value)
|
174
|
+
else
|
175
|
+
value = self::VALUES[index]
|
176
|
+
return self.new(value)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def items(**items)
|
181
|
+
attr_names = []
|
182
|
+
attr_type_strs = []
|
183
|
+
|
184
|
+
items.each_pair do |attr_name, attr_type_str|
|
185
|
+
attr_names << attr_name
|
186
|
+
attr_type_strs << attr_type_str
|
187
|
+
end
|
188
|
+
|
189
|
+
self.const_set(:ITEM_NAMES, attr_names)
|
190
|
+
self.const_set(:ITEM_TYPE_STRS, attr_type_strs)
|
191
|
+
end
|
192
|
+
|
193
|
+
def values(*values)
|
194
|
+
self.const_set(:VALUES, values)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.included(base)
|
199
|
+
base.extend(ClassMethods)
|
200
|
+
end
|
201
|
+
|
202
|
+
def encode
|
203
|
+
if self.class.const_defined? "ITEM_NAMES"
|
204
|
+
value_type_str = self.value.class.to_s.split("::").last.to_s
|
205
|
+
index = self::class::ITEM_TYPE_STRS.index(value_type_str).to_s(16).rjust(2, '0')
|
206
|
+
index + self.value.encode
|
207
|
+
else
|
208
|
+
self::class::VALUES.index(self.value).to_s(16).rjust(2, '0')
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
module Vec
|
214
|
+
include SingleValue # value is an array
|
215
|
+
|
216
|
+
module ClassMethods
|
217
|
+
def decode(scale_bytes, raw=false)
|
218
|
+
number = Scale::Types::Compact.decode(scale_bytes).value
|
219
|
+
items = []
|
220
|
+
number.times do
|
221
|
+
item = type_of(self::INNER_TYPE_STR).decode(scale_bytes)
|
222
|
+
items << item
|
223
|
+
end
|
224
|
+
raw ? items : self.new(items)
|
225
|
+
end
|
226
|
+
|
227
|
+
def inner_type(type_str)
|
228
|
+
self.const_set(:INNER_TYPE_STR, type_str)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def self.included(base)
|
233
|
+
base.extend ClassMethods
|
234
|
+
end
|
235
|
+
|
236
|
+
def encode
|
237
|
+
number = Scale::Types::Compact.new(self.value.length).encode
|
238
|
+
[number].tap do |result|
|
239
|
+
self.value.each do |element|
|
240
|
+
result << element.encode
|
241
|
+
end
|
242
|
+
end.join
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
module Set
|
247
|
+
include SingleValue
|
248
|
+
|
249
|
+
module ClassMethods
|
250
|
+
def decode(scale_bytes)
|
251
|
+
value = "Scale::Types::U#{self::BYTES_LENGTH*8}".constantize.decode(scale_bytes).value
|
252
|
+
return self.new [] if not value || value <= 0
|
253
|
+
|
254
|
+
result = self::VALUES.select{ |_, mask| value & mask > 0 }.keys
|
255
|
+
return self.new result
|
256
|
+
end
|
257
|
+
|
258
|
+
# values is a hash:
|
259
|
+
# {
|
260
|
+
# "TransactionPayment" => 0b00000001,
|
261
|
+
# "Transfer" => 0b00000010,
|
262
|
+
# "Reserve" => 0b00000100,
|
263
|
+
# ...
|
264
|
+
# }
|
265
|
+
def values(values, bytes_length=1)
|
266
|
+
raise "byte length is wrong: #{bytes_length}" if not [1, 2, 4, 8, 16].include?(bytes_length)
|
267
|
+
self.const_set(:VALUES, values)
|
268
|
+
self.const_set(:BYTES_LENGTH, bytes_length)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.included(base)
|
273
|
+
base.extend ClassMethods
|
274
|
+
end
|
275
|
+
|
276
|
+
def encode
|
277
|
+
value = self.class::VALUES.select{ |str, _| self.value.include?(str) }.values.sum
|
278
|
+
"Scale::Types::U#{self.class::BYTES_LENGTH*8}".constantize.new(value).encode
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
module VecU8FixedLength
|
283
|
+
include SingleValue
|
284
|
+
|
285
|
+
module ClassMethods
|
286
|
+
def decode(scale_bytes)
|
287
|
+
class_name = self.to_s
|
288
|
+
length = class_name[class_name.length-1]
|
289
|
+
raise "length is wrong: #{length}" if not ["2", "3", "4", "8", "16", "20", "32", "64"].include?(length)
|
290
|
+
length = length.to_i
|
291
|
+
|
292
|
+
bytes = scale_bytes.get_next_bytes(length)
|
293
|
+
str = bytes.pack("C*").force_encoding("utf-8")
|
294
|
+
if str.valid_encoding?
|
295
|
+
self.new str
|
296
|
+
else
|
297
|
+
self.new bytes.bytes_to_hex
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.included(base)
|
303
|
+
base.extend ClassMethods
|
304
|
+
end
|
305
|
+
|
306
|
+
def encode
|
307
|
+
class_name = self.class.to_s
|
308
|
+
length = class_name[class_name.length-1]
|
309
|
+
raise "length is wrong: #{length}" if not ["2", "3", "4", "8", "16", "20", "32", "64"].include?(length)
|
310
|
+
length = length.to_i
|
311
|
+
|
312
|
+
if self.value.start_with?("0x") && self.value.length == (length*2+2)
|
313
|
+
self.value[2..]
|
314
|
+
else
|
315
|
+
bytes = self.value.unpack("C*")
|
316
|
+
bytes.bytes_to_hex[2..]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
end
|
322
|
+
end
|