scale_rb 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|