safestruct 1.2.2 → 1.3.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 +56 -3
- data/lib/safestruct.rb +5 -4
- data/lib/safestruct/safe_array.rb +2 -2
- data/lib/safestruct/safe_hash.rb +32 -18
- data/lib/safestruct/version.rb +2 -2
- data/test/test_hash.rb +2 -2
- data/test/voter.rb +11 -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: e5b47433e234edeb8d8ddddfaa7d6eac51ce1845
|
4
|
+
data.tar.gz: 49d711cfbef0941d9cf91762c47858d790d96ef2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ea81799da3ab6d4a4dca8468a5b7515c6ee64717b5350577ad0f8cad32cc2db423fe90ed7d69e018da40044a9d70fa9f643f8723214109d998507f11216dd57
|
7
|
+
data.tar.gz: c4e4388b63a6771fbd98c34aa4bd8599e7a0d70a7efa8400c30461409af833fba0e8bef75a7171fee0e19ea0285b680f8c45c0213c2086b87c68a274206db484
|
data/README.md
CHANGED
@@ -94,11 +94,13 @@ Note: You can use `Struct` as an alias for `SafeStruct`
|
|
94
94
|
class method macro:
|
95
95
|
|
96
96
|
``` ruby
|
97
|
-
struct(
|
97
|
+
struct( :Voter, weight: 0, voted: false, vote: 0, delegate: '0x0000')
|
98
98
|
# or
|
99
|
-
struct
|
99
|
+
struct :Voter, { weight: 0, voted: false, vote: 0, delegate: '0x0000' }
|
100
100
|
# or
|
101
|
-
struct
|
101
|
+
struct :Voter, weight: 0, voted: false, vote: 0, delegate: '0x0000'
|
102
|
+
# or
|
103
|
+
struct :Voter,
|
102
104
|
weight: 0,
|
103
105
|
voted: false,
|
104
106
|
vote: 0,
|
@@ -211,6 +213,57 @@ allowances['0x2222'].delete( '0xaaaa' )
|
|
211
213
|
allowances['0x2222']['0xaaaa'] #=> 0
|
212
214
|
```
|
213
215
|
|
216
|
+
### Bonus: Auto-Generated Unicode (UTF-8) Class Constants / Names for Pretty Printing
|
217
|
+
|
218
|
+
Did you know? Yes, you can use unicode characters in your identifiers.
|
219
|
+
The safe data structures library auto-generates unicode class constants / names
|
220
|
+
for pretty printing and more. Examples:
|
221
|
+
|
222
|
+
| Class Builder | Class Constant / Name |
|
223
|
+
|----------------------------------------|-----------------------|
|
224
|
+
| `Array.of( Integer )` | `Array‹Integer›` |
|
225
|
+
| `Array.of( Bool )` | `Array‹Bool›` |
|
226
|
+
| `Array.of( Bool, 2 )` | `Array‹Bool›×2` |
|
227
|
+
| `Array.of( Vote )` | `Array‹Vote›` |
|
228
|
+
| `Array.of( Array.of( Integer, 3), 3 )` | `Array‹Array‹Integer›×3›×3` |
|
229
|
+
| `Hash.of( String => Integer )` | `Hash‹String→Integer›` |
|
230
|
+
| `Hash.of( String => Vote )` | `Hash‹String→Vote›` |
|
231
|
+
| `Hash.of( String => Hash.of( String => Integer ))` | `Hash‹String→Hash‹String→Integer››` |
|
232
|
+
| ... | |
|
233
|
+
|
234
|
+
|
235
|
+
Note, and yes if the typing is not too much - you can use
|
236
|
+
the "magic" names in your code too. Example:
|
237
|
+
|
238
|
+
``` ruby
|
239
|
+
ary = Array‹Integer›.new
|
240
|
+
ary.size #=> 0
|
241
|
+
ary[0] #=> IndexError: index 0 outside of array bounds
|
242
|
+
ary.size = 2 #=> [0,0]
|
243
|
+
ary[0] #=> 0
|
244
|
+
|
245
|
+
# or
|
246
|
+
|
247
|
+
another_ary = Array‹Bool›×2.new
|
248
|
+
another_ary.size #=> 2
|
249
|
+
another_ary[0] #=> false
|
250
|
+
|
251
|
+
# or
|
252
|
+
|
253
|
+
hash = Hash‹String→Integer›.new
|
254
|
+
hash['0x0000'] #=> 0
|
255
|
+
hash['0x0000'] += 42
|
256
|
+
hash['0x0000'] #=> 42
|
257
|
+
|
258
|
+
# or
|
259
|
+
|
260
|
+
allowances = Hash‹String→Hash‹String→Integer››.new
|
261
|
+
allowances['0x1111']['0xaaaa'] = 100
|
262
|
+
allowances['0x1111']['0xbbbb'] = 200
|
263
|
+
allowances['0x2222']['0xaaaa'] = 300
|
264
|
+
```
|
265
|
+
|
266
|
+
and so on.
|
214
267
|
|
215
268
|
|
216
269
|
### What about Safe Enumeration (Integer) Types?
|
data/lib/safestruct.rb
CHANGED
@@ -89,14 +89,15 @@ class Array
|
|
89
89
|
end
|
90
90
|
|
91
91
|
|
92
|
-
module
|
92
|
+
module Standard
|
93
93
|
############################
|
94
94
|
# note: HACK redefine built in struct in module Safe "context"
|
95
95
|
Struct = ::Struct ## save old classic struct class
|
96
|
-
|
97
|
-
|
96
|
+
Array = ::Array
|
97
|
+
Hash = ::Hash
|
98
98
|
end
|
99
|
-
|
99
|
+
## use/add Unsafe alias too - why? why not?
|
100
|
+
Std = Standard ## add alias lets use you use Std::Struct,Std::Array, Std::Hash etc.
|
100
101
|
|
101
102
|
|
102
103
|
|
@@ -40,12 +40,12 @@ class SafeArray
|
|
40
40
|
|
41
41
|
## note: also add a Constant to Safe for easy debugging and (re)use - will "auto"name class
|
42
42
|
class_name = "Array"
|
43
|
-
class_name << "#{size}" if size > 0 ## add size if non-zero
|
44
43
|
|
45
44
|
name = klass_value.name
|
46
45
|
name = name.sub( /\bSafe::/, '' ) ## remove safe module from name if present
|
47
46
|
name = name.gsub( '::', '' ) ## remove module separator if present
|
48
|
-
class_name << "
|
47
|
+
class_name << "‹#{name}›"
|
48
|
+
class_name << "×#{size}" if size > 0 ## add size if non-zero
|
49
49
|
Safe.const_set( class_name, klass )
|
50
50
|
end
|
51
51
|
klass
|
data/lib/safestruct/safe_hash.rb
CHANGED
@@ -7,6 +7,12 @@ class SafeHash
|
|
7
7
|
def self.debug?() @debug ||= false; end
|
8
8
|
def self.debug=(value) @debug = value; end
|
9
9
|
|
10
|
+
## let's you configure the class name used for auto-generation class constants
|
11
|
+
## e.g. use SafeHash.klass_name = 'Mapping' to rename from (default) 'Hash'
|
12
|
+
def self.klass_name() @@klass_name ||= 'Hash'; end
|
13
|
+
def self.klass_name=(value) @@klass_name = value; end
|
14
|
+
|
15
|
+
|
10
16
|
|
11
17
|
## e.g.
|
12
18
|
## Hash.of( Address => Money )
|
@@ -22,9 +28,13 @@ class SafeHash
|
|
22
28
|
|
23
29
|
## note: keep a class cache
|
24
30
|
cache = @@cache ||= {}
|
25
|
-
|
31
|
+
cache_all_values = cache[ klass_key ] ||= {}
|
32
|
+
klass = cache_all_values[ klass_value ]
|
33
|
+
|
26
34
|
if debug?
|
27
|
-
puts "[debug] SafeHash - build_class klass_value:"
|
35
|
+
puts "[debug] SafeHash - build_class( klass_key, klass_value ):"
|
36
|
+
pp klass_key
|
37
|
+
pp klass_key.to_s ## note: for "anonymous" class something like #<Class:>
|
28
38
|
pp klass_value
|
29
39
|
pp klass_value.to_s ## note: for "anonymous" class something like #<Class:>
|
30
40
|
end
|
@@ -54,16 +64,20 @@ class SafeHash
|
|
54
64
|
# RUBY
|
55
65
|
|
56
66
|
## add to cache for later (re)use
|
57
|
-
cache[ klass_value ] = klass
|
67
|
+
cache[ klass_key ][ klass_value ] = klass
|
58
68
|
|
59
69
|
## note: also add a Constant to Safe for easy debugging and (re)use - will "auto"name class
|
60
|
-
|
61
|
-
|
70
|
+
class_name = "#{klass_name}"
|
71
|
+
|
72
|
+
key_name = klass_key.name
|
73
|
+
key_name = key_name.sub( /\bSafe::/, '' ) ## remove safe module from name if present
|
74
|
+
key_name = key_name.gsub( '::', '' ) ## remove module separator if present
|
75
|
+
|
76
|
+
value_name = klass_value.name
|
77
|
+
value_name = value_name.sub( /\bSafe::/, '' ) ## remove safe module from name if present
|
78
|
+
value_name = value_name.gsub( '::', '' ) ## remove module separator if present
|
62
79
|
|
63
|
-
|
64
|
-
name = name.sub( /\bSafe::/, '' ) ## remove safe module from name if present
|
65
|
-
name = name.gsub( '::', '' ) ## remove module separator if present
|
66
|
-
class_name << "_#{name}"
|
80
|
+
class_name << "‹#{key_name}→#{value_name}›"
|
67
81
|
if debug?
|
68
82
|
puts "[debug] SafeHash - class_name >#{class_name}<"
|
69
83
|
end
|
@@ -87,18 +101,18 @@ class SafeHash
|
|
87
101
|
|
88
102
|
def initialize
|
89
103
|
## todo/check: if hash works if value is a (nested) hash
|
90
|
-
@
|
104
|
+
@table = {}
|
91
105
|
end
|
92
106
|
|
93
107
|
def freeze
|
94
108
|
super
|
95
|
-
@
|
109
|
+
@table.freeze ## note: pass on freeze to "wrapped" hash
|
96
110
|
self # return reference to self
|
97
111
|
end
|
98
112
|
|
99
113
|
def ==( other )
|
100
|
-
if other.is_a?( self.class ) ## note: must be same hash class
|
101
|
-
@
|
114
|
+
if other.is_a?( self.class ) ## note: must be same hash (table) class
|
115
|
+
@table == other.instance_variable_get( '@table' ) ## compare "wrapped" hash
|
102
116
|
else
|
103
117
|
false
|
104
118
|
end
|
@@ -109,11 +123,11 @@ class SafeHash
|
|
109
123
|
|
110
124
|
|
111
125
|
def []=(key, value)
|
112
|
-
@
|
126
|
+
@table[key] = value
|
113
127
|
end
|
114
128
|
|
115
129
|
def [](key)
|
116
|
-
item = @
|
130
|
+
item = @table[ key ]
|
117
131
|
if item.nil?
|
118
132
|
## pp self.class.klass_value
|
119
133
|
## pp self.class.klass_value.zero
|
@@ -126,17 +140,17 @@ class SafeHash
|
|
126
140
|
if self.class.klass_value.respond_to?( :new_zero )
|
127
141
|
## note: use a dup(licated) unfrozen copy of the zero object
|
128
142
|
## changes to the object MUST be possible (new "empty" modifable object expected)
|
129
|
-
item = @
|
143
|
+
item = @table[ key ] = self.class.klass_value.new_zero
|
130
144
|
else # assume value semantics e.g. Integer, Bool, etc. zero values gets replaced
|
131
145
|
## puts "use value semantics"
|
132
|
-
item = @
|
146
|
+
item = @table[ key ] = self.class.klass_value.zero
|
133
147
|
end
|
134
148
|
end
|
135
149
|
item
|
136
150
|
end
|
137
151
|
|
138
152
|
extend Forwardable
|
139
|
-
def_delegators :@
|
153
|
+
def_delegators :@table, :has_key?, :key?, :delete, :clear
|
140
154
|
|
141
155
|
## note: remove size and length for (safe) hash (for now) - follows solidity convention - why? why not?
|
142
156
|
## :size, :length,
|
data/lib/safestruct/version.rb
CHANGED
data/test/test_hash.rb
CHANGED
@@ -46,8 +46,8 @@ def test_integer
|
|
46
46
|
assert_equal false, h.has_key?( '0x1111' )
|
47
47
|
|
48
48
|
## todo/fix: remove size and length for (safe) hash - why? why not?
|
49
|
-
assert_equal 0, h.instance_variable_get('@
|
50
|
-
assert_equal 0, h.instance_variable_get('@
|
49
|
+
assert_equal 0, h.instance_variable_get('@table').size
|
50
|
+
assert_equal 0, h.instance_variable_get('@table').length
|
51
51
|
|
52
52
|
assert_equal true, Hash_X_Integer.zero == h
|
53
53
|
assert_equal true, Hash_X_Integer.zero == Hash_X_Integer.new
|
data/test/voter.rb
CHANGED
@@ -3,17 +3,25 @@
|
|
3
3
|
|
4
4
|
module Safe
|
5
5
|
|
6
|
-
##
|
6
|
+
##[sig(Integer, Bool, Integer, Address)]
|
7
|
+
##
|
7
8
|
## Struct.new( :Voter,
|
8
9
|
## weight: 0,
|
9
10
|
## voted: false,
|
10
11
|
## vote: 0,
|
11
12
|
## delegate: '0x0000' )
|
12
13
|
|
13
|
-
struct :Voter,
|
14
|
+
struct :Voter, {
|
14
15
|
weight: 0,
|
15
16
|
voted: false,
|
16
17
|
vote: 0,
|
17
|
-
delegate: '0x0000'
|
18
|
+
delegate: '0x0000' }
|
19
|
+
|
20
|
+
### -or-
|
21
|
+
# struct :Voter,
|
22
|
+
# weight: 0,
|
23
|
+
# voted: false,
|
24
|
+
# vote: 0,
|
25
|
+
# delegate: '0x0000'
|
18
26
|
|
19
27
|
end # module Safe
|
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.3.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-03-
|
11
|
+
date: 2019-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: enums
|