safestruct 1.1.1 → 1.2.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/Manifest.txt +1 -0
- data/README.md +33 -2
- data/Rakefile +1 -0
- data/lib/safestruct.rb +15 -1
- data/lib/safestruct/safe_hash.rb +17 -0
- data/lib/safestruct/safe_struct.rb +34 -2
- data/lib/safestruct/version.rb +2 -2
- data/test/helper.rb +3 -0
- data/test/test_hash.rb +5 -3
- data/test/test_struct.rb +25 -36
- data/test/voter.rb +13 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04e5c95875cd6c4fbdd2865525ed7853d5c549e3
|
4
|
+
data.tar.gz: c2f2eab9840be5183219caec2132c08b5a6d9297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 552e6f386d52b6b4bbd312b2c80f9f09073eb187fbb899e0de0d4e0070477da7e8f9bd520bc56c0bdee6fef8462af634c42045ebc87d8c307ff5cd1c4b0003d3
|
7
|
+
data.tar.gz: 82725de07669291702ce15b805f24073abe8dce0131f89d98e346c9e19f309d60e1b083c58a04e455a1c950f2674602b8c3e06a1c505463ac9ca68eb7e952bcb
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -61,7 +61,7 @@ Let's you define (auto-build) new struct classes.
|
|
61
61
|
Example:
|
62
62
|
|
63
63
|
``` ruby
|
64
|
-
|
64
|
+
SafeStruct.new( 'Voter', weight: 0, voted: false, vote: 0, delegate: '0x0000' )
|
65
65
|
|
66
66
|
voter1 = Voter.new # or Voter.new_zero
|
67
67
|
voter1.weight #=> 0
|
@@ -71,6 +71,7 @@ voter1.delegate #=> '0x0000'
|
|
71
71
|
voter1.frozen? #=> false
|
72
72
|
|
73
73
|
voter1 == Voter.zero #=> true
|
74
|
+
voter1 == Voter(0) #=> true
|
74
75
|
|
75
76
|
voter1.delegate = '0x1111'
|
76
77
|
voter1 == Voter.zero #=> false
|
@@ -89,7 +90,20 @@ voter3 = Voter.new( 0 ) #=> ArgumentError: wrong number of arguments
|
|
89
90
|
|
90
91
|
|
91
92
|
Note: You can use `Struct` as an alias for `SafeStruct`
|
92
|
-
(in the `Safe` namespace
|
93
|
+
(in the `Safe` namespace) or use the `struct`
|
94
|
+
class method macro:
|
95
|
+
|
96
|
+
``` ruby
|
97
|
+
struct( 'Voter', weight: 0, voted: false, vote: 0, delegate: '0x0000')
|
98
|
+
# or
|
99
|
+
struct 'Voter', weight: 0, voted: false, vote: 0, delegate: '0x0000'
|
100
|
+
# or
|
101
|
+
struct 'Voter',
|
102
|
+
weight: 0,
|
103
|
+
voted: false,
|
104
|
+
vote: 0,
|
105
|
+
delegate: '0x0000'
|
106
|
+
```
|
93
107
|
|
94
108
|
|
95
109
|
### Safe Array
|
@@ -199,6 +213,23 @@ allowances['0x2222']['0xaaaa'] #=> 0
|
|
199
213
|
|
200
214
|
|
201
215
|
|
216
|
+
### What about Safe Enumeration (Integer) Types?
|
217
|
+
|
218
|
+
Yes, yes, yes. The `Enum` class from the enums library gets auto-required.
|
219
|
+
Use like:
|
220
|
+
|
221
|
+
``` ruby
|
222
|
+
Enum.new( 'Color', :red, :green, :blue )
|
223
|
+
## or
|
224
|
+
enum 'Color', :red, :green, :blue
|
225
|
+
## or
|
226
|
+
enum 'Color', [:red, :green, :blue]
|
227
|
+
```
|
228
|
+
|
229
|
+
See the [enums library documentation for more »](https://github.com/s6ruby/enums)
|
230
|
+
|
231
|
+
|
232
|
+
|
202
233
|
## More "Real World" Safe Data Structures (Array, Hash, Struct) Samples
|
203
234
|
|
204
235
|
- [The "Red Paper" about sruby](https://github.com/s6ruby/redpaper) - Small, Smart, Secure, Safe, Solid & Sound (S6) Ruby - The Ruby Programming Language for Contract / Transaction Scripts on the Blockchain World Computer - Yes, It's Just Ruby
|
data/Rakefile
CHANGED
data/lib/safestruct.rb
CHANGED
@@ -3,10 +3,13 @@
|
|
3
3
|
require 'pp'
|
4
4
|
require 'forwardable' # uses def_delegator
|
5
5
|
|
6
|
+
## 3rd party libs
|
7
|
+
require 'enums'
|
6
8
|
|
7
9
|
## our own code
|
8
10
|
require 'safestruct/version' # note: let version always go first
|
9
11
|
|
12
|
+
|
10
13
|
require 'safestruct/safe_array'
|
11
14
|
require 'safestruct/safe_hash'
|
12
15
|
require 'safestruct/safe_struct'
|
@@ -79,6 +82,17 @@ module Safe
|
|
79
82
|
# note: HACK redefine built in struct in module Safe "context"
|
80
83
|
ClassicStruct = ::Struct ## save old classic struct class
|
81
84
|
Struct = SafeStruct
|
82
|
-
|
85
|
+
|
86
|
+
module ClassMethods
|
87
|
+
## add more convenience "constructor" methods
|
88
|
+
## e.g. struct 'Voter', { weight: 0, voted: false, vote: 0, delegate: '0x0000'}
|
89
|
+
## or struct 'Voter', weight: 0, voted: false, vote: 0, delegate: '0x0000'
|
90
|
+
def struct( class_name, **attributes )
|
91
|
+
SafeStruct.new( class_name, attributes )
|
92
|
+
end
|
93
|
+
end # module ClassMethods
|
94
|
+
end # module Safe
|
95
|
+
|
96
|
+
|
83
97
|
|
84
98
|
puts Safe.banner ## say hello
|
data/lib/safestruct/safe_hash.rb
CHANGED
@@ -4,6 +4,10 @@ module Safe
|
|
4
4
|
|
5
5
|
class SafeHash
|
6
6
|
|
7
|
+
def self.debug?() @debug ||= false; end
|
8
|
+
def self.debug=(value) @debug = value; end
|
9
|
+
|
10
|
+
|
7
11
|
## e.g.
|
8
12
|
## Hash.of( Address => Money )
|
9
13
|
|
@@ -19,8 +23,16 @@ class SafeHash
|
|
19
23
|
## note: keep a class cache
|
20
24
|
cache = @@cache ||= {}
|
21
25
|
klass = cache[ klass_value ]
|
26
|
+
if debug?
|
27
|
+
puts "[debug] SafeHash - build_class klass_value:"
|
28
|
+
pp klass_value
|
29
|
+
end
|
22
30
|
|
23
31
|
if klass.nil?
|
32
|
+
if debug?
|
33
|
+
puts "[debug] SafeHash - build_class new class (no cache hit)"
|
34
|
+
end
|
35
|
+
|
24
36
|
klass = Class.new( SafeHash )
|
25
37
|
klass.class_eval( <<RUBY )
|
26
38
|
def self.klass_key
|
@@ -32,6 +44,11 @@ class SafeHash
|
|
32
44
|
RUBY
|
33
45
|
## add to cache for later (re)use
|
34
46
|
cache[ klass_value ] = klass
|
47
|
+
else
|
48
|
+
if debug?
|
49
|
+
puts "[debug] SafeHash - build_class bingo!! (re)use cached class:"
|
50
|
+
pp klass
|
51
|
+
end
|
35
52
|
end
|
36
53
|
|
37
54
|
klass
|
@@ -4,7 +4,24 @@ module Safe
|
|
4
4
|
|
5
5
|
class SafeStruct
|
6
6
|
|
7
|
-
|
7
|
+
|
8
|
+
def self.convert( arg )
|
9
|
+
## note: for now only supports 0 for Vote(0) as Vote.zero shortcut
|
10
|
+
if arg == 0
|
11
|
+
zero
|
12
|
+
else
|
13
|
+
raise ArgumentError.new( "[SafeStruct] invalid argument #{arg} - cannot convert to #{name}" )
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def self.build_class( class_name, **attributes )
|
19
|
+
|
20
|
+
## todo/fix:
|
21
|
+
## check if valid class_name MUST start with uppercase letter etc.
|
22
|
+
## todo/fix: check if constant is undefined in Safe namespace!!!!
|
23
|
+
|
24
|
+
|
8
25
|
klass = Class.new( SafeStruct ) do
|
9
26
|
define_method( :initialize ) do |*args|
|
10
27
|
attributes.keys.zip( args ).each do |key, arg|
|
@@ -82,7 +99,22 @@ def self.build_class( **attributes )
|
|
82
99
|
old_new( *values )
|
83
100
|
end
|
84
101
|
|
85
|
-
|
102
|
+
|
103
|
+
## note: use Object for "namespacing"
|
104
|
+
## make all enums convenience converters (always) global
|
105
|
+
## including uppercase methods (e.g. State(), Color(), etc.) does NOT work otherwise (with other module includes)
|
106
|
+
|
107
|
+
## add global convenience converter function
|
108
|
+
## e.g. Vote(0) is same as Vote.convert(0)
|
109
|
+
Object.class_eval( <<RUBY )
|
110
|
+
def #{class_name}( arg )
|
111
|
+
#{class_name}.convert( arg )
|
112
|
+
end
|
113
|
+
RUBY
|
114
|
+
|
115
|
+
## note: use Safe (module) and NOT Object for namespacing
|
116
|
+
## use include Safe to make all structs global
|
117
|
+
Safe.const_set( class_name, klass ) ## returns klass (plus sets global constant class name)
|
86
118
|
end # method build_class
|
87
119
|
|
88
120
|
class << self
|
data/lib/safestruct/version.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/test_hash.rb
CHANGED
@@ -8,13 +8,14 @@
|
|
8
8
|
require 'helper'
|
9
9
|
|
10
10
|
|
11
|
+
## note: require voter to avoid DUPLICATE definition (with undefined state/errors etc.)
|
12
|
+
require_relative 'voter'
|
13
|
+
|
14
|
+
|
11
15
|
class TestHash < MiniTest::Test
|
12
16
|
|
13
17
|
include Safe
|
14
18
|
|
15
|
-
## sig: [Integer, Bool, Integer, Address]
|
16
|
-
Voter = SafeStruct.new( weight: 0, voted: false, vote: 0, delegate: '0x0000' )
|
17
|
-
|
18
19
|
Hash_X_Integer = SafeHash.build_class( String, Integer )
|
19
20
|
Hash_X_Bool = SafeHash.build_class( String, Bool )
|
20
21
|
Hash_X_Voter = SafeHash.build_class( String, Voter )
|
@@ -22,6 +23,7 @@ class TestHash < MiniTest::Test
|
|
22
23
|
## nested e.g. String => (String => Integer)
|
23
24
|
Hash_Hash_X_Integer = SafeHash.build_class( String, Hash_X_Integer )
|
24
25
|
|
26
|
+
|
25
27
|
def test_integer
|
26
28
|
pp Hash_X_Integer
|
27
29
|
pp h = Hash_X_Integer.new
|
data/test/test_struct.rb
CHANGED
@@ -8,52 +8,41 @@
|
|
8
8
|
require 'helper'
|
9
9
|
|
10
10
|
|
11
|
+
## note: require voter to avoid DUPLICATE definition (with undefined state/errors etc.)
|
12
|
+
require_relative 'voter'
|
13
|
+
|
14
|
+
|
11
15
|
class TestStruct < MiniTest::Test
|
12
16
|
|
13
17
|
include Safe
|
14
18
|
|
15
|
-
## sig: [Integer, Bool, Integer, Address]
|
16
|
-
Voter = SafeStruct.new( weight: 0, voted: false, vote: 0, delegate: '0x0000' )
|
17
|
-
|
18
19
|
## sig: [Address, Integer, Integer, Money]
|
19
|
-
|
20
|
+
## SafeStruct.new( 'Bet', user: '0x0000', block: 0, cap: 0, amount: 0 )
|
21
|
+
struct :Bet,
|
22
|
+
user: '0x0000',
|
23
|
+
block: 0,
|
24
|
+
cap: 0,
|
25
|
+
amount: 0
|
20
26
|
|
21
|
-
|
22
|
-
|
23
|
-
### test with "real" enum
|
24
|
-
class Enum
|
25
|
-
def initialize( key, value )
|
26
|
-
@key = key
|
27
|
-
@value = value
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Winner < Enum
|
32
|
-
NONE = new(:none, 0 )
|
33
|
-
DRAW = new(:draw, 1 )
|
34
|
-
HOST = new(:host, 2 )
|
35
|
-
CHALLENGER = new(:challenger, 3)
|
36
|
-
|
37
|
-
def self.none() NONE; end
|
38
|
-
def self.draw() DRAW; end
|
39
|
-
def self.host() HOST; end
|
40
|
-
def self.challenger() CHALLENGER; end
|
41
|
-
|
42
|
-
def none?() self == NONE; end
|
43
|
-
def draw?() self == DRAW; end
|
44
|
-
def host?() self == HOST; end
|
45
|
-
def challenger?() self == CHALLENGER; end
|
46
|
-
end
|
27
|
+
## Enum.new( 'Winner', :none, :draw, :host, :challenger )
|
28
|
+
enum :Winner, :none, :draw, :host, :challenger
|
47
29
|
|
48
30
|
Board = Array_9_Integer = SafeArray.build_class( Integer, 3*3 )
|
49
31
|
|
50
32
|
## sig: [Address, Address, Address, Winner(Enum), Board(Array9)]
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
33
|
+
## SafeStruct.new( 'Game',
|
34
|
+
## host: '0x0000',
|
35
|
+
## challenger: '0x0000',
|
36
|
+
## turn: '0x0000', ## address of host/ challenger
|
37
|
+
## winner: Winner.none, ## e.g. Winner(0)
|
38
|
+
## board: Board.zero)
|
39
|
+
struct :Game,
|
40
|
+
host: '0x0000',
|
41
|
+
challenger: '0x0000',
|
42
|
+
turn: '0x0000', ## address of host/ challenger
|
43
|
+
winner: Winner.none, ## e.g. Winner(0)
|
44
|
+
board: Board.zero
|
45
|
+
|
57
46
|
|
58
47
|
def test_voter
|
59
48
|
assert_equal true, Voter.zero.frozen?
|
data/test/voter.rb
ADDED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safestruct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.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-
|
11
|
+
date: 2019-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: enums
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rdoc
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -63,6 +77,7 @@ files:
|
|
63
77
|
- test/test_array.rb
|
64
78
|
- test/test_hash.rb
|
65
79
|
- test/test_struct.rb
|
80
|
+
- test/voter.rb
|
66
81
|
homepage: https://github.com/s6ruby/safestruct
|
67
82
|
licenses:
|
68
83
|
- Public Domain
|