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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e972352c0dbb2c3684a3de9385f33efb706a7cca
4
- data.tar.gz: 9fb3502f891afab88650aa288bfc39d84ac5f236
3
+ metadata.gz: 04e5c95875cd6c4fbdd2865525ed7853d5c549e3
4
+ data.tar.gz: c2f2eab9840be5183219caec2132c08b5a6d9297
5
5
  SHA512:
6
- metadata.gz: de271ceb36e33cf627911d60e69c5120e2e8cde48ac84d1ef258571a98e36757695345b4e3ac58a77e0086e76f8ad393a13a6567f8b738fe380c41a47c63bb94
7
- data.tar.gz: 4863ee4959e548d6686ca1020b8be99897a0945ebb3eef35becc7bc77d028ba1858d0d2c9b4e6f9b9066baedf636c6c3b2911aaa8a49d1e1b33bda9c2b6420e8
6
+ metadata.gz: 552e6f386d52b6b4bbd312b2c80f9f09073eb187fbb899e0de0d4e0070477da7e8f9bd520bc56c0bdee6fef8462af634c42045ebc87d8c307ff5cd1c4b0003d3
7
+ data.tar.gz: 82725de07669291702ce15b805f24073abe8dce0131f89d98e346c9e19f309d60e1b083c58a04e455a1c950f2674602b8c3e06a1c505463ac9ca68eb7e952bcb
@@ -12,3 +12,4 @@ test/helper.rb
12
12
  test/test_array.rb
13
13
  test/test_hash.rb
14
14
  test/test_struct.rb
15
+ test/voter.rb
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
- Voter = SafeStruct.new( weight: 0, voted: false, vote: 0, delegate: '0x0000' )
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 / module context).
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
@@ -18,6 +18,7 @@ Hoe.spec 'safestruct' do
18
18
  self.history_file = 'CHANGELOG.md'
19
19
 
20
20
  self.extra_deps = [
21
+ ['enums', '>=1.1.0'],
21
22
  ]
22
23
 
23
24
  self.licenses = ['Public Domain']
@@ -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
- end
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
@@ -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
- def self.build_class( **attributes )
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
- klass
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
@@ -4,8 +4,8 @@
4
4
  module Safe
5
5
 
6
6
  MAJOR = 1
7
- MINOR = 1
8
- PATCH = 1
7
+ MINOR = 2
8
+ PATCH = 0
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
11
11
  def self.version
@@ -6,3 +6,6 @@ require 'minitest/autorun'
6
6
  ## our own code
7
7
 
8
8
  require 'safestruct'
9
+
10
+ ## turn on debug out
11
+ Safe::SafeHash.debug = true
@@ -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
@@ -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
- Bet = SafeStruct.new( user: '0x0000', block: 0, cap: 0, amount: 0 )
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
- Game = SafeStruct.new( host: '0x0000',
52
- challenger: '0x0000',
53
- turn: '0x0000', ## address of host/ challenger
54
- winner: Winner.none,
55
- board: Board.zero
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?
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+
4
+ module Safe
5
+
6
+ ## sig: [Integer, Bool, Integer, Address]
7
+ Struct.new( :Voter,
8
+ weight: 0,
9
+ voted: false,
10
+ vote: 0,
11
+ delegate: '0x0000' )
12
+
13
+ end # module Safe
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.1.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-02-21 00:00:00.000000000 Z
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