safestruct 1.0.0 → 1.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 +4 -4
- data/README.md +16 -2
- data/lib/safestruct.rb +10 -5
- data/lib/safestruct/safe_array.rb +3 -1
- data/lib/safestruct/safe_hash.rb +4 -2
- data/lib/safestruct/version.rb +1 -1
- data/test/test_array.rb +70 -0
- data/test/test_hash.rb +49 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 566fae2d8f89cb24afd577666383dd7944811152
|
4
|
+
data.tar.gz: 6b72e279ae328f1fdac760691ad57d92e991ab21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f756d180e311fef89fc4325bcb873bcaaaa02e73cba6ce8d34081352ff46a99307e76470dadec5ede89ab7ea7869d8d1f8a70260860c452f4a5a8783165bd5c2
|
7
|
+
data.tar.gz: bf9226fd8c07a2f63ee309e5b6ebbd7da7551bcaf350691bf715c9ebb8c7e48250b9b88765ad1dbf8d7c09ee07f46b6e3d39e63684276e759529187e7cbc15e4
|
data/README.md
CHANGED
@@ -168,7 +168,7 @@ hash['0x0000'] #=> 42
|
|
168
168
|
Note: Safe Hash will ALWAYS return a value.
|
169
169
|
If the key is missing in the hash mapping on lookup,
|
170
170
|
the key gets auto-added with a zero value.
|
171
|
-
Use `has_key?` or `key?` to check if a key is present.
|
171
|
+
Use `has_key?` or `key?` to check if a key is present (or missing).
|
172
172
|
|
173
173
|
|
174
174
|
Yes, Safe Hash works with structs (or arrays or nested hash mappings) too. Example:
|
@@ -180,8 +180,22 @@ hash['0x0000'] #=> #<Vote @weight=0, @voted=false, @vote=0, @dele
|
|
180
180
|
hash['0x0000'].voted? #=> false
|
181
181
|
hash['0x0000'].voted = true
|
182
182
|
hash['0x0000'].voted? #=> true
|
183
|
-
```
|
184
183
|
|
184
|
+
# or
|
185
|
+
|
186
|
+
allowances = Hash.of( String => Hash.of( String => Integer ) )
|
187
|
+
|
188
|
+
allowances['0x1111']['0xaaaa'] = 100
|
189
|
+
allowances['0x1111']['0xbbbb'] = 200
|
190
|
+
allowances['0x2222']['0xaaaa'] = 300
|
191
|
+
|
192
|
+
allowances['0x1111']['0xaaaa'] #=> 100
|
193
|
+
allowances['0x1111']['0xbbbb'] #=> 200
|
194
|
+
allowances['0x2222']['0xaaaa'] #=> 300
|
195
|
+
|
196
|
+
allowances['0x2222'].delete( '0xaaaa' )
|
197
|
+
allowances['0x2222']['0xaaaa'] #=> 0
|
198
|
+
```
|
185
199
|
|
186
200
|
|
187
201
|
|
data/lib/safestruct.rb
CHANGED
@@ -43,15 +43,17 @@ class Hash
|
|
43
43
|
## e.g. gets passed in [{Address=>Integer}]
|
44
44
|
## check for Integer - use Hash.new(0)
|
45
45
|
## check for Bool - use Hash.new(False)
|
46
|
-
if args[0].is_a? Hash
|
46
|
+
if args[0].is_a?( Hash ) && args.size == 1
|
47
47
|
arg = args[0].to_a ## convert to array (for easier access)
|
48
48
|
klass_key = arg[0][0]
|
49
|
-
|
49
|
+
## note: for nested Hash.of or Array.of a ("prototype") object
|
50
|
+
## gets passed in (NOT class) - auto-convert to use class
|
51
|
+
klass_or_proto_value = arg[0][1]
|
52
|
+
klass_value = klass_or_proto_value.is_a?( Class ) ? klass_or_proto_value : klass_or_proto_value.class
|
50
53
|
klass = Safe::SafeHash.build_class( klass_key, klass_value )
|
51
54
|
klass.new
|
52
55
|
else
|
53
|
-
|
54
|
-
Hash.new ## that is, "plain" {} with all "standard" defaults
|
56
|
+
raise ArgumentError.new( "[Hash.of] wrong argument; expected (default) hash e.g. String => Integer" )
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -61,7 +63,10 @@ class Array
|
|
61
63
|
## "typed" safe array "constructor"
|
62
64
|
## e.g. Array.of( Address ) or Array.of( Money ) or
|
63
65
|
## Array.of( Proposal, 2 ) etc.
|
64
|
-
def self.of(
|
66
|
+
def self.of( klass_or_proto_value, size=0 )
|
67
|
+
## note: for nested Hash.of or Array.of a ("prototype") object
|
68
|
+
## gets passed in (NOT class) - auto-convert to use class
|
69
|
+
klass_value = klass_or_proto_value.is_a?( Class ) ? klass_or_proto_value : klass_or_proto_value.class
|
65
70
|
klass = Safe::SafeArray.build_class( klass_value )
|
66
71
|
klass.new( size )
|
67
72
|
end
|
@@ -98,10 +98,12 @@ RUBY
|
|
98
98
|
## note: Address might be a String too (Address | String)
|
99
99
|
## store Address always as String!!! - why? why not?
|
100
100
|
@ary.push( item )
|
101
|
+
## note: returns array.size (NOT array itself!!!) to keep compatible with solidity - why? why not?
|
102
|
+
@ary.size
|
101
103
|
end
|
102
104
|
|
103
105
|
extend Forwardable
|
104
|
-
def_delegators :@ary, :size, :length,
|
106
|
+
def_delegators :@ary, :size, :length, :clear,
|
105
107
|
:each, :each_with_index
|
106
108
|
|
107
109
|
|
data/lib/safestruct/safe_hash.rb
CHANGED
@@ -93,8 +93,10 @@ RUBY
|
|
93
93
|
end
|
94
94
|
|
95
95
|
extend Forwardable
|
96
|
-
def_delegators :@h, :
|
97
|
-
|
96
|
+
def_delegators :@h, :has_key?, :key?, :delete, :clear
|
97
|
+
|
98
|
+
## note: remove size and length for (safe) hash (for now) - follows solidity convention - why? why not?
|
99
|
+
## :size, :length,
|
98
100
|
|
99
101
|
end # class SafeHash
|
100
102
|
end # module Safe
|
data/lib/safestruct/version.rb
CHANGED
data/test/test_array.rb
CHANGED
@@ -15,6 +15,26 @@ class TestArray < MiniTest::Test
|
|
15
15
|
Array_Integer = SafeArray.build_class( Integer )
|
16
16
|
Array_Bool = SafeArray.build_class( Bool )
|
17
17
|
|
18
|
+
## multi-dimensional / nested array
|
19
|
+
Array_Array_Integer = SafeArray.build_class( Array_Integer )
|
20
|
+
|
21
|
+
|
22
|
+
def test_push_and_clear
|
23
|
+
ary = Array_Integer.new
|
24
|
+
|
25
|
+
## note: push returns array.size after adding new item
|
26
|
+
## std ruby returns reference to array itself
|
27
|
+
assert_equal 0, ary.size
|
28
|
+
assert_equal 1, ary.push( 10 )
|
29
|
+
assert_equal 1, ary.size
|
30
|
+
|
31
|
+
assert_equal 2, ary.push( 20 )
|
32
|
+
assert_equal 2, ary.size
|
33
|
+
|
34
|
+
ary.clear
|
35
|
+
assert_equal 0, ary.size
|
36
|
+
end
|
37
|
+
|
18
38
|
def test_integer
|
19
39
|
pp Array_Integer
|
20
40
|
pp ary = Array_Integer.new(2)
|
@@ -67,5 +87,55 @@ def test_bool
|
|
67
87
|
assert_equal Array_Bool, Array.of( Bool ).class
|
68
88
|
end
|
69
89
|
|
90
|
+
def test_array_of
|
91
|
+
assert_equal true, Array.is_a?( Class )
|
92
|
+
|
93
|
+
ary = Array.of( Integer ) # note:Array.of returns a new ("prototype") object and NOT a class
|
94
|
+
assert_equal false, ary.is_a?( Class )
|
95
|
+
assert_equal true, ary.class.is_a?( Class )
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_multi # nested (multi-dimensional) array
|
99
|
+
## todo/fix: try with size: 3 e.g. 3x3
|
100
|
+
## make it work with size too!!!!!
|
101
|
+
## remember size if passed in in c'tor!!!!!!
|
102
|
+
|
103
|
+
multi = Array_Array_Integer.new
|
104
|
+
multi.push( Array_Integer.new )
|
105
|
+
multi[0].push( 100 )
|
106
|
+
multi[0].push( 200 )
|
107
|
+
multi.push( Array_Integer.new )
|
108
|
+
multi[1].push( 300 )
|
109
|
+
pp multi
|
110
|
+
|
111
|
+
assert_equal 100, multi[0][0]
|
112
|
+
assert_equal 200, multi[0][1]
|
113
|
+
assert_equal 300, multi[1][0]
|
114
|
+
|
115
|
+
multi[1].clear
|
116
|
+
assert_equal 0, multi[1].size
|
117
|
+
multi.clear
|
118
|
+
assert_equal 0, multi.size
|
119
|
+
|
120
|
+
##############################################
|
121
|
+
## try Array.of convenience helper
|
122
|
+
|
123
|
+
multi = Array.of( Array.of( Integer ) )
|
124
|
+
multi.push( Array.of( Integer ) )
|
125
|
+
multi[0].push( 100 )
|
126
|
+
multi[0].push( 200 )
|
127
|
+
multi.push( Array.of( Integer ) )
|
128
|
+
multi[1].push( 300 )
|
129
|
+
pp multi
|
130
|
+
|
131
|
+
assert_equal 100, multi[0][0]
|
132
|
+
assert_equal 200, multi[0][1]
|
133
|
+
assert_equal 300, multi[1][0]
|
134
|
+
|
135
|
+
multi[1].clear
|
136
|
+
assert_equal 0, multi[1].size
|
137
|
+
multi.clear
|
138
|
+
assert_equal 0, multi.size
|
139
|
+
end
|
70
140
|
|
71
141
|
end # class TestArray
|
data/test/test_hash.rb
CHANGED
@@ -19,6 +19,9 @@ class TestHash < MiniTest::Test
|
|
19
19
|
Hash_X_Bool = SafeHash.build_class( String, Bool )
|
20
20
|
Hash_X_Voter = SafeHash.build_class( String, Voter )
|
21
21
|
|
22
|
+
## nested e.g. String => (String => Integer)
|
23
|
+
Hash_Hash_X_Integer = SafeHash.build_class( String, Hash_X_Integer )
|
24
|
+
|
22
25
|
def test_integer
|
23
26
|
pp Hash_X_Integer
|
24
27
|
pp h = Hash_X_Integer.new
|
@@ -27,8 +30,8 @@ def test_integer
|
|
27
30
|
assert_equal false, h.has_key?( '0x1111' )
|
28
31
|
|
29
32
|
## todo/fix: remove size and length for (safe) hash - why? why not?
|
30
|
-
assert_equal 0, h.size
|
31
|
-
assert_equal 0, h.length
|
33
|
+
assert_equal 0, h.instance_variable_get('@h').size
|
34
|
+
assert_equal 0, h.instance_variable_get('@h').length
|
32
35
|
|
33
36
|
assert_equal Hash_X_Integer.zero, h
|
34
37
|
assert_equal Hash_X_Integer.zero, Hash_X_Integer.new
|
@@ -38,7 +41,7 @@ def test_integer
|
|
38
41
|
assert_equal false, Hash_X_Integer.new.frozen?
|
39
42
|
assert_equal false, h.frozen?
|
40
43
|
|
41
|
-
|
44
|
+
|
42
45
|
assert_equal Integer, Hash_X_Integer.klass_value
|
43
46
|
assert_equal 0, h['0x1111']
|
44
47
|
assert_equal 0, h['0x2222']
|
@@ -92,4 +95,47 @@ def test_voter
|
|
92
95
|
end
|
93
96
|
|
94
97
|
|
98
|
+
def test_allowances # nested hash
|
99
|
+
## allowances = Hash.of( String => Hash.of( String => Integer ) )
|
100
|
+
allowances = Hash_Hash_X_Integer.new
|
101
|
+
|
102
|
+
allowances['0x1111']['0xaaaa'] = 100
|
103
|
+
allowances['0x1111']['0xbbbb'] = 200
|
104
|
+
allowances['0x2222']['0xaaaa'] = 300
|
105
|
+
pp allowances
|
106
|
+
|
107
|
+
assert_equal 100, allowances['0x1111']['0xaaaa']
|
108
|
+
assert_equal 200, allowances['0x1111']['0xbbbb']
|
109
|
+
assert_equal 300, allowances['0x2222']['0xaaaa']
|
110
|
+
|
111
|
+
allowances['0x2222'].delete( '0xaaaa' )
|
112
|
+
assert_equal 0, allowances['0x2222']['0xaaaa']
|
113
|
+
|
114
|
+
##############################################
|
115
|
+
## try Hash.of convenience helper
|
116
|
+
allowances = Hash.of( String => Hash.of( String => Integer ))
|
117
|
+
|
118
|
+
allowances['0x1111']['0xaaaa'] = 100
|
119
|
+
allowances['0x1111']['0xbbbb'] = 200
|
120
|
+
allowances['0x2222']['0xaaaa'] = 300
|
121
|
+
pp allowances
|
122
|
+
|
123
|
+
assert_equal 100, allowances['0x1111']['0xaaaa']
|
124
|
+
assert_equal 200, allowances['0x1111']['0xbbbb']
|
125
|
+
assert_equal 300, allowances['0x2222']['0xaaaa']
|
126
|
+
|
127
|
+
allowances['0x2222'].delete( '0xaaaa' )
|
128
|
+
assert_equal 0, allowances['0x2222']['0xaaaa']
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def test_hash_of
|
133
|
+
assert_equal true, Hash.is_a?( Class )
|
134
|
+
|
135
|
+
h = Hash.of( String => Integer ) # note:Hash.of returns a new ("prototype") object and NOT a class
|
136
|
+
assert_equal false, h.is_a?( Class )
|
137
|
+
assert_equal true, h.class.is_a?( Class )
|
138
|
+
end
|
139
|
+
|
140
|
+
|
95
141
|
end # class TestHash
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safestruct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|