scale_rb 0.4.1 → 0.5.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 +4 -4
- data/.devcontainer/devcontainer.json +21 -0
- data/Dockerfile +16 -0
- data/Gemfile +4 -4
- data/README.md +19 -6
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/examples/http_client_1.rb +0 -2
- data/examples/http_client_2.rb +0 -2
- data/examples/ws_client_1.rb +0 -2
- data/examples/ws_client_3.rb +1 -3
- data/examples/ws_client_4.rb +0 -2
- data/exe/metadata +9 -11
- data/lib/address.rb +1 -1
- data/lib/custom_assign.rb +92 -0
- data/lib/scale_rb/call_helper.rb +42 -0
- data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
- data/lib/{client → scale_rb/client}/http_client.rb +3 -5
- data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
- data/lib/scale_rb/codec.rb +25 -0
- data/lib/scale_rb/codec_utils.rb +128 -0
- data/lib/scale_rb/decode.rb +164 -0
- data/lib/scale_rb/encode.rb +150 -0
- data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
- data/lib/scale_rb/metadata/metadata.rb +114 -0
- data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
- data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
- data/lib/scale_rb/metadata/registry.rb +263 -0
- data/lib/scale_rb/metadata/type_exp.rb +286 -0
- data/lib/scale_rb/portable_registry.rb +133 -0
- data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
- data/lib/scale_rb/types.rb +233 -0
- data/lib/scale_rb/utils.rb +125 -0
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +22 -30
- data/lib/type_enforcer.rb +170 -0
- data/scale_rb.gemspec +5 -0
- metadata +71 -19
- data/lib/codec.rb +0 -450
- data/lib/metadata/metadata.rb +0 -137
- data/lib/monkey_patching.rb +0 -115
- data/lib/portable_codec.rb +0 -285
- data/lib/registry.rb +0 -13
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable all
|
4
|
+
module ScaleRb
|
5
|
+
class PortableRegistry
|
6
|
+
extend TypeEnforcer
|
7
|
+
include Types
|
8
|
+
|
9
|
+
attr_reader :data, :types
|
10
|
+
|
11
|
+
__ :initialize, { data: TypedArray[HashMap[String, Any]] }
|
12
|
+
def initialize(data)
|
13
|
+
@data = data
|
14
|
+
@types = ::Array.new(@data.size)
|
15
|
+
build_types
|
16
|
+
end
|
17
|
+
|
18
|
+
__ :[], { index: Ti }, PortableType
|
19
|
+
def [](index)
|
20
|
+
@types[index]
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"a_portable_registry"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
__ :build_types, {}
|
30
|
+
def build_types
|
31
|
+
@data.each.with_index do |type, i|
|
32
|
+
id = type._get(:id)
|
33
|
+
raise "Invalid type id: #{id}" if id.nil? || id != i
|
34
|
+
|
35
|
+
def_ = type._get(:type, :def)
|
36
|
+
raise "No 'def' found: #{type}" if def_.nil?
|
37
|
+
|
38
|
+
path = type._get(:type, :path)
|
39
|
+
|
40
|
+
type_name = def_.keys.first.to_sym
|
41
|
+
type_def = def_._get(type_name)
|
42
|
+
@types[id] = _build_type(id, type_name, type_def, path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# TODO: type_def better type definition
|
47
|
+
__ :_build_type, { id: Ti, type_name: Symbol, type_def: Hash | String | Array, path: TypedArray[String] }, PortableType
|
48
|
+
def _build_type(id, type_name, type_def, path)
|
49
|
+
case type_name
|
50
|
+
when :primitive
|
51
|
+
# type_def: 'I32'
|
52
|
+
PrimitiveType.new(primitive: type_def.to_sym, path: path)
|
53
|
+
when :compact
|
54
|
+
# type_def: { type: 1 }
|
55
|
+
CompactType.new(type: type_def._get(:type), registry: self, path: path)
|
56
|
+
when :sequence
|
57
|
+
# type_def: { type: 9 }
|
58
|
+
SequenceType.new(type: type_def._get(:type), registry: self, path: path)
|
59
|
+
when :bitSequence
|
60
|
+
# type_def: {"bitStoreType"=>2, "bitOrderType"=>502}
|
61
|
+
BitSequenceType.new(
|
62
|
+
bit_store_type: type_def._get(:bitStoreType),
|
63
|
+
bit_order_type: type_def._get(:bitOrderType),
|
64
|
+
registry: self,
|
65
|
+
path: path
|
66
|
+
)
|
67
|
+
when :array
|
68
|
+
# type_def: { len: 3, type: 1 }
|
69
|
+
ArrayType.new(
|
70
|
+
len: type_def._get(:len),
|
71
|
+
type: type_def._get(:type),
|
72
|
+
registry: self,
|
73
|
+
path: path
|
74
|
+
)
|
75
|
+
when :tuple
|
76
|
+
# type_def: [1, 2, 3]
|
77
|
+
TupleType.new(tuple: type_def, registry: self, path: path)
|
78
|
+
when :composite
|
79
|
+
fields = type_def._get(:fields)
|
80
|
+
first_field = fields.first
|
81
|
+
|
82
|
+
# type_def: {"fields"=>[]}
|
83
|
+
return UnitType.new(path: path) if first_field.nil?
|
84
|
+
|
85
|
+
# type_def: {"fields"=>[{"name"=>nil, "type"=>1}, {"name"=>nil, "type"=>2}]}
|
86
|
+
return TupleType.new(tuple: fields.map { |f| f._get(:type) }, registry: self, path: path) unless first_field._get(:name)
|
87
|
+
|
88
|
+
# type_def: { fields: [{ name: 'name', type: 1 }, { name: 'age', type: 2 }] }
|
89
|
+
StructType.new(
|
90
|
+
fields: fields.map do |field|
|
91
|
+
Field.new(name: field._get(:name), type: field._get(:type))
|
92
|
+
end,
|
93
|
+
registry: self,
|
94
|
+
path: path
|
95
|
+
)
|
96
|
+
when :variant
|
97
|
+
variants = type_def._get(:variants)
|
98
|
+
|
99
|
+
# type_def: {"variants"=>[]}
|
100
|
+
return VariantType.new(variants: [], path: path) if variants.empty?
|
101
|
+
|
102
|
+
variant_list = variants.map do |v|
|
103
|
+
fields = v._get(:fields)
|
104
|
+
if fields.empty?
|
105
|
+
# variant: {"name"=>"Vouching", "fields"=>[], "index"=>0, "docs"=>[]}
|
106
|
+
SimpleVariant.new(name: v._get(:name).to_sym, index: v._get(:index))
|
107
|
+
elsif fields.first._get(:name).nil?
|
108
|
+
# variant: {"name"=>"Seal", "fields"=>[{"name"=>nil, "type"=>15, "typeName"=>"ConsensusEngineId", "docs"=>[]}, {"name"=>nil, "type"=>11, "typeName"=>"Vec<u8>", "docs"=>[]}], "index"=>5, "docs"=>[]},
|
109
|
+
TupleVariant.new(
|
110
|
+
name: v._get(:name).to_sym,
|
111
|
+
index: v._get(:index),
|
112
|
+
tuple: TupleType.new(
|
113
|
+
tuple: fields.map { |field| field._get(:type) },
|
114
|
+
registry: self
|
115
|
+
)
|
116
|
+
)
|
117
|
+
else
|
118
|
+
# variant: {"name"=>"ExtrinsicSuccess", "fields"=>[{"name"=>"dispatch_info", "type"=>20, "typeName"=>"DispatchInfo", "docs"=>[]}], "index"=>0, "docs"=>["An extrinsic completed successfully."]},
|
119
|
+
StructVariant.new(
|
120
|
+
name: v._get(:name).to_sym,
|
121
|
+
index: v._get(:index),
|
122
|
+
struct: StructType.new(
|
123
|
+
fields: fields.map { |field| Field.new(name: field._get(:name), type: field._get(:type)) },
|
124
|
+
registry: self
|
125
|
+
)
|
126
|
+
)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
VariantType.new(variants: variant_list, path: path)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -20,7 +20,7 @@ module ScaleRb
|
|
20
20
|
]
|
21
21
|
else
|
22
22
|
[
|
23
|
-
registry[key[:type]].
|
23
|
+
registry[key[:type]].tuple.first(key[:value].length),
|
24
24
|
key[:value],
|
25
25
|
key[:hashers].first(key[:value].length)
|
26
26
|
]
|
@@ -32,12 +32,24 @@ module ScaleRb
|
|
32
32
|
raise "Key's value doesn't match key's type, key's value: #{key_values.inspect}, but key's type: #{key_types.inspect}. Please check your key's value."
|
33
33
|
end
|
34
34
|
|
35
|
-
storage_key +
|
35
|
+
storage_key + _encode_types_with_hashers(key_types, key_values, registry, key_hashers)
|
36
36
|
else
|
37
37
|
storage_key
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def _encode_types_with_hashers(type_ids, values, registry, hashers)
|
42
|
+
if !hashers.nil? && hashers.length != type_ids.length
|
43
|
+
raise "type_ids length: #{type_ids.length}, hashers length: #{hashers.length}"
|
44
|
+
end
|
45
|
+
|
46
|
+
type_ids
|
47
|
+
.map.with_index { |type_id, i| ScaleRb::Codec.encode(type_id, values[i], registry) }
|
48
|
+
.each_with_index.reduce([]) do |memo, (bytes, i)|
|
49
|
+
memo + Hasher.apply_hasher(hashers[i], bytes)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
41
53
|
# data: hex string
|
42
54
|
# type: portable type id
|
43
55
|
# optional: boolean
|
@@ -45,14 +57,14 @@ module ScaleRb
|
|
45
57
|
# returns nil or data
|
46
58
|
def decode_storage(data, type, optional, fallback, registry)
|
47
59
|
data ||= (optional ? nil : fallback)
|
48
|
-
|
60
|
+
ScaleRb::Codec.decode(type, Utils.hex_to_u8a(data), registry)[0] if data
|
49
61
|
end
|
50
62
|
|
51
63
|
# storage_item: the storage item from metadata
|
52
64
|
def decode_storage2(data, storage_item, registry)
|
53
65
|
modifier = storage_item._get(:modifier) # Default | Optional
|
54
66
|
fallback = storage_item._get(:fallback)
|
55
|
-
type = storage_item._get(:type
|
67
|
+
type = storage_item._get(:type, :plain) || storage_item._get(:type, :map, :value)
|
56
68
|
decode_storage(data, type, modifier == 'Optional', fallback, registry)
|
57
69
|
end
|
58
70
|
|
@@ -0,0 +1,233 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry-struct'
|
4
|
+
require 'dry-types'
|
5
|
+
|
6
|
+
module ScaleRb
|
7
|
+
module Types
|
8
|
+
include Dry.Types()
|
9
|
+
|
10
|
+
Primitive = Types::Strict::Symbol.enum(
|
11
|
+
:I8, :U8, :I16, :U16, :I32, :U32, :I64, :U64, :I128, :U128, :I256, :U256, :Bool, :Str, :Char
|
12
|
+
)
|
13
|
+
Ti = Types::Strict::Integer.constrained(gteq: 0)
|
14
|
+
U8 = Types::Strict::Integer.constrained(gteq: 0, lt: 256)
|
15
|
+
U8Array = Types::Strict::Array.of(U8)
|
16
|
+
Hex = Types::Strict::String.constrained(format: /\A0x[0-9a-fA-F]+\z/)
|
17
|
+
|
18
|
+
Registry = Types.Interface(:[])
|
19
|
+
|
20
|
+
HashMap = lambda do |key_type, value_type|
|
21
|
+
Types::Hash.map(key_type, value_type)
|
22
|
+
end
|
23
|
+
UnsignedInteger = Types::Strict::Integer.constrained(gteq: 0)
|
24
|
+
TypedArray = ->(type) { Types::Array.of(type) }
|
25
|
+
|
26
|
+
class Base < Dry::Struct
|
27
|
+
attribute? :registry, Registry
|
28
|
+
attribute? :path, Types::Strict::Array.of(Types::Strict::String)
|
29
|
+
|
30
|
+
def t(type_id)
|
31
|
+
raise 'No registry' unless registry
|
32
|
+
|
33
|
+
pt = registry[type_id]
|
34
|
+
raise "Unknown type: #{type_id}" unless pt
|
35
|
+
|
36
|
+
pt
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
to_string
|
41
|
+
end
|
42
|
+
|
43
|
+
MAX_DEPTH = 2
|
44
|
+
def to_string(_depth = 0)
|
45
|
+
raise NotImplementedError, "#{self.class} must implement to_string"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class PrimitiveType < Base
|
50
|
+
attribute :primitive, Primitive
|
51
|
+
|
52
|
+
def to_string(_depth = 0)
|
53
|
+
primitive.to_s
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class CompactType < Base
|
58
|
+
attribute? :type, Ti
|
59
|
+
|
60
|
+
def to_string(depth = 0)
|
61
|
+
if type
|
62
|
+
if depth > MAX_DEPTH
|
63
|
+
'Compact<...>'
|
64
|
+
else
|
65
|
+
"Compact<#{t(type).to_string(depth + 1)}>"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
'Compact'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class SequenceType < Base
|
74
|
+
attribute :type, Ti
|
75
|
+
|
76
|
+
def to_string(depth = 0)
|
77
|
+
if depth > MAX_DEPTH
|
78
|
+
'[...]'
|
79
|
+
else
|
80
|
+
"[#{t(type).to_string(depth + 1)}]"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class BitSequenceType < Base
|
86
|
+
attribute :bit_store_type, Ti
|
87
|
+
attribute :bit_order_type, Ti
|
88
|
+
|
89
|
+
def to_string(depth = 0)
|
90
|
+
if depth > MAX_DEPTH
|
91
|
+
'BitSequence<...>'
|
92
|
+
else
|
93
|
+
"BitSequence<#{t(bit_store_type).to_string(depth + 1)}, #{t(bit_order_type).to_string(depth + 1)}>"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class ArrayType < Base
|
99
|
+
attribute :len, Types::Strict::Integer
|
100
|
+
attribute :type, Ti
|
101
|
+
|
102
|
+
def to_string(depth = 0)
|
103
|
+
if depth > MAX_DEPTH
|
104
|
+
'[...]'
|
105
|
+
else
|
106
|
+
"[#{t(type).to_string(depth + 1)}; #{len}]"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class TupleType < Base
|
112
|
+
attribute :tuple, Types::Strict::Array.of(Ti)
|
113
|
+
|
114
|
+
def to_string(depth = 0)
|
115
|
+
if depth > MAX_DEPTH
|
116
|
+
'(...)'
|
117
|
+
else
|
118
|
+
"(#{tuple.map { |t| t(t).to_string(depth + 1) }.join(', ')})"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class Field < Dry::Struct
|
124
|
+
attribute :name, Types::Strict::String
|
125
|
+
attribute :type, Ti
|
126
|
+
end
|
127
|
+
|
128
|
+
class StructType < Base
|
129
|
+
attribute :fields, Types::Strict::Array.of(Field)
|
130
|
+
|
131
|
+
def to_string(depth = 0)
|
132
|
+
if depth > MAX_DEPTH
|
133
|
+
'{ ... }'
|
134
|
+
else
|
135
|
+
"{ #{fields.map { |field| "#{field.name}: #{t(field.type).to_string(depth + 1)}" }.join(', ')} }"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class UnitType < Base
|
141
|
+
def to_string(_depth = 0)
|
142
|
+
'()'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class SimpleVariant < Dry::Struct
|
147
|
+
attribute :name, Types::Strict::Symbol
|
148
|
+
attribute :index, Types::Strict::Integer
|
149
|
+
end
|
150
|
+
|
151
|
+
class TupleVariant < Dry::Struct
|
152
|
+
attribute :name, Types::Strict::Symbol
|
153
|
+
attribute :index, Types::Strict::Integer
|
154
|
+
attribute :tuple, TupleType
|
155
|
+
end
|
156
|
+
|
157
|
+
class StructVariant < Dry::Struct
|
158
|
+
attribute :name, Types::Strict::Symbol
|
159
|
+
attribute :index, Types::Strict::Integer
|
160
|
+
attribute :struct, StructType
|
161
|
+
end
|
162
|
+
|
163
|
+
VariantKind = Instance(SimpleVariant) | Instance(TupleVariant) | Instance(StructVariant)
|
164
|
+
|
165
|
+
class VariantType < Base
|
166
|
+
attribute :variants, Types::Array.of(VariantKind)
|
167
|
+
|
168
|
+
def to_string(depth = 0)
|
169
|
+
if depth > MAX_DEPTH
|
170
|
+
variants.sort_by(&:index).map { |v| v.name.to_s }.join(' | ')
|
171
|
+
else
|
172
|
+
variants.sort_by(&:index).map do |v|
|
173
|
+
case v
|
174
|
+
when SimpleVariant
|
175
|
+
v.name.to_s
|
176
|
+
when TupleVariant
|
177
|
+
"#{v.name}#{v.tuple.to_string(depth + 1)}"
|
178
|
+
when StructVariant
|
179
|
+
"#{v.name} #{v.struct.to_string(depth + 1)}"
|
180
|
+
end
|
181
|
+
end.join(' | ')
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.option(type, registry)
|
186
|
+
VariantType.new(
|
187
|
+
variants: [
|
188
|
+
SimpleVariant.new(name: :None, index: 0),
|
189
|
+
TupleVariant.new(name: :Some, index: 1, tuple: TupleType.new(tuple: [type], registry:))
|
190
|
+
],
|
191
|
+
registry:
|
192
|
+
)
|
193
|
+
end
|
194
|
+
|
195
|
+
def option?
|
196
|
+
variants.length == 2 &&
|
197
|
+
variants.any? { |v| v.is_a?(SimpleVariant) && v.name == :None && v.index == 0 } &&
|
198
|
+
variants.any? { |v| v.is_a?(TupleVariant) && v.name == :Some && v.index == 1 }
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.result(ok_type, err_type, registry)
|
202
|
+
VariantType.new(
|
203
|
+
variants: [
|
204
|
+
TupleVariant.new(name: :Ok, index: 0, tuple: TupleType.new(tuple: [ok_type], registry:)),
|
205
|
+
TupleVariant.new(name: :Err, index: 1, tuple: TupleType.new(tuple: [err_type], registry:))
|
206
|
+
],
|
207
|
+
registry:
|
208
|
+
)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
PortableType = Instance(VariantType) |
|
213
|
+
Instance(StructType) |
|
214
|
+
Instance(TupleType) |
|
215
|
+
Instance(ArrayType) |
|
216
|
+
Instance(CompactType) |
|
217
|
+
Instance(PrimitiveType) |
|
218
|
+
Instance(UnitType) |
|
219
|
+
Instance(SequenceType) |
|
220
|
+
Instance(BitSequenceType)
|
221
|
+
|
222
|
+
DecodeResult = lambda do |type|
|
223
|
+
Types::Array.of(Types::Any).constrained(size: 2).constructor do |arr|
|
224
|
+
[type[arr[0]], arr[1]] # U8Array[arr[1]], but performance is not good.
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# type = ScaleRb::Types::TypedArray[ScaleRb::Types::UnsignedInteger]
|
231
|
+
# p type
|
232
|
+
# p type[[1, 2]] # => [1, 2]
|
233
|
+
# # p type[[-1, -2]] # => -1 violates constraints (gteq?(0, -1) failed)
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# Check if the key exists in the hash
|
5
|
+
# @param key [String | Symbol] Key to check
|
6
|
+
# @return [Boolean] True if the key exists, false otherwise
|
7
|
+
def _key?(key)
|
8
|
+
ScaleRb::Utils.key?(self, key)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Get the value from the hash
|
12
|
+
# @param keys [Array<String | Symbol>] Keys to get the value from
|
13
|
+
# @return [Object | NilClass] Value if the key exists, nil otherwise
|
14
|
+
def _get(*keys)
|
15
|
+
ScaleRb::Utils.get(self, *keys)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ScaleRb
|
20
|
+
module Utils
|
21
|
+
class << self
|
22
|
+
# https://www.rubyguides.com/2017/01/read-binary-data/
|
23
|
+
def hex_to_u8a(str)
|
24
|
+
data = str.start_with?('0x') ? str[2..] : str
|
25
|
+
raise 'Not valid hex string' if data =~ /[^\da-f]+/i
|
26
|
+
|
27
|
+
data = "0#{data}" if data.length.odd?
|
28
|
+
data.scan(/../).map(&:hex)
|
29
|
+
end
|
30
|
+
|
31
|
+
def camelize(str)
|
32
|
+
str.split('_').collect(&:capitalize).join
|
33
|
+
end
|
34
|
+
|
35
|
+
def underscore(str)
|
36
|
+
str.gsub(/::/, '/')
|
37
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
38
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
39
|
+
.tr('-', '_')
|
40
|
+
.downcase
|
41
|
+
end
|
42
|
+
|
43
|
+
def int_to_u8a(int, bit_length = nil)
|
44
|
+
hex = bit_length ? int.to_s(16).rjust(bit_length / 4, '0') : int.to_s(16)
|
45
|
+
hex_to_u8a(hex)
|
46
|
+
end
|
47
|
+
|
48
|
+
def uint_to_int(unsigned, bit_length)
|
49
|
+
unsigned_mid = 2**(bit_length - 1)
|
50
|
+
unsigned_ceiling = 2**bit_length
|
51
|
+
unsigned >= unsigned_mid ? unsigned - unsigned_ceiling : unsigned
|
52
|
+
end
|
53
|
+
|
54
|
+
def int_to_uint(signed, bit_length)
|
55
|
+
unsigned_mid = 2**(bit_length - 1)
|
56
|
+
unsigned_ceiling = 2**bit_length
|
57
|
+
raise 'Out of scope' if signed >= unsigned_mid || signed <= -unsigned_mid
|
58
|
+
|
59
|
+
signed.negative? ? unsigned_ceiling + signed : signed
|
60
|
+
end
|
61
|
+
|
62
|
+
# unix timestamp to utc
|
63
|
+
def unix_to_utc(unix)
|
64
|
+
Time.at(unix).utc.asctime
|
65
|
+
end
|
66
|
+
|
67
|
+
# utc to unix timestamp
|
68
|
+
def utc_to_unix(utc_asctime)
|
69
|
+
Time.parse(utc_asctime)
|
70
|
+
end
|
71
|
+
|
72
|
+
def u8a?(arr)
|
73
|
+
arr.all? { |e| e >= 0 && e <= 255 }
|
74
|
+
end
|
75
|
+
|
76
|
+
def u8a_to_hex(u8a)
|
77
|
+
raise 'Not a byte array' unless u8a?(u8a)
|
78
|
+
|
79
|
+
u8a.reduce('0x') { |hex, u8| hex + u8.to_s(16).rjust(2, '0') }
|
80
|
+
end
|
81
|
+
|
82
|
+
def u8a_to_bin(u8a)
|
83
|
+
raise 'Not a byte array' unless u8a?(u8a)
|
84
|
+
|
85
|
+
u8a.reduce('0b') { |bin, u8| bin + u8.to_s(2).rjust(8, '0') }
|
86
|
+
end
|
87
|
+
|
88
|
+
def u8a_to_utf8(u8a)
|
89
|
+
raise 'Not a byte array' unless u8a?(u8a)
|
90
|
+
|
91
|
+
u8a.pack('C*').force_encoding('utf-8')
|
92
|
+
end
|
93
|
+
|
94
|
+
def u8a_to_uint(u8a)
|
95
|
+
u8a_to_hex(u8a).to_i(16)
|
96
|
+
end
|
97
|
+
|
98
|
+
def u8a_to_int(u8a, bit_length)
|
99
|
+
uint_to_int(u8a_to_uint(u8a), bit_length)
|
100
|
+
end
|
101
|
+
|
102
|
+
def key?(hash, key)
|
103
|
+
if key.instance_of?(String)
|
104
|
+
hash.key?(key) || hash.key?(key.to_sym)
|
105
|
+
else
|
106
|
+
hash.key?(key) || hash.key?(key.to_s)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def get(hash, *keys)
|
111
|
+
keys.reduce(hash) do |h, key|
|
112
|
+
break nil unless h.is_a?(Hash)
|
113
|
+
|
114
|
+
if key.instance_of?(String)
|
115
|
+
h[key] || h[key.to_sym]
|
116
|
+
elsif key.instance_of?(Symbol)
|
117
|
+
h[key] || h[key.to_s]
|
118
|
+
else
|
119
|
+
h[key]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/scale_rb/version.rb
CHANGED
data/lib/scale_rb.rb
CHANGED
@@ -1,33 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'scale_rb/version'
|
4
|
-
require '
|
5
|
-
|
6
|
-
# scale codec
|
7
|
-
require 'monkey_patching'
|
8
|
-
require 'codec'
|
9
|
-
require 'portable_codec'
|
10
|
-
|
11
|
-
# metadata types, decoding and helpers
|
12
|
-
require 'metadata/metadata_v9'
|
13
|
-
require 'metadata/metadata_v10'
|
14
|
-
require 'metadata/metadata_v11'
|
15
|
-
require 'metadata/metadata_v12'
|
16
|
-
require 'metadata/metadata_v13'
|
17
|
-
require 'metadata/metadata_v14'
|
18
|
-
require 'metadata/metadata'
|
19
|
-
|
20
|
-
require 'hasher'
|
21
|
-
require 'storage_helper'
|
22
|
-
|
23
|
-
# get registry from config
|
24
|
-
require 'registry'
|
25
|
-
|
26
|
-
require 'address'
|
27
|
-
|
28
|
-
# clients
|
29
|
-
require 'client/http_client'
|
30
|
-
require 'client/ws_client'
|
4
|
+
require 'console'
|
31
5
|
|
32
6
|
module ScaleRb
|
33
7
|
class << self
|
@@ -39,6 +13,24 @@ module ScaleRb
|
|
39
13
|
end
|
40
14
|
end
|
41
15
|
|
42
|
-
logger =
|
43
|
-
|
44
|
-
|
16
|
+
ScaleRb.logger = Console
|
17
|
+
|
18
|
+
require 'scale_rb/utils'
|
19
|
+
|
20
|
+
require 'type_enforcer'
|
21
|
+
|
22
|
+
require 'scale_rb/types'
|
23
|
+
require 'scale_rb/portable_registry'
|
24
|
+
require 'scale_rb/codec'
|
25
|
+
|
26
|
+
require 'scale_rb/metadata/metadata'
|
27
|
+
|
28
|
+
require 'scale_rb/hasher'
|
29
|
+
require 'scale_rb/storage_helper'
|
30
|
+
require 'scale_rb/call_helper'
|
31
|
+
|
32
|
+
require 'address'
|
33
|
+
|
34
|
+
# clients
|
35
|
+
require 'scale_rb/client/http_client'
|
36
|
+
require 'scale_rb/client/ws_client'
|