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 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