safestruct 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|