striuct 0.6.1 → 0.9.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE.txt +21 -0
  3. data/README.md +44 -60
  4. data/lib/striuct/{requirements.rb → bootstrap.rb} +6 -2
  5. data/lib/striuct/classmethods/README.md +2 -2
  6. data/lib/striuct/classmethods/adjustment.rb +77 -13
  7. data/lib/striuct/classmethods/attributes.rb +94 -92
  8. data/lib/striuct/classmethods/conflict_management.rb +109 -106
  9. data/lib/striuct/classmethods/constructor.rb +55 -65
  10. data/lib/striuct/classmethods/copy.rb +45 -43
  11. data/lib/striuct/classmethods/default.rb +23 -21
  12. data/lib/striuct/classmethods/enum.rb +46 -44
  13. data/lib/striuct/classmethods/fix.rb +23 -21
  14. data/lib/striuct/classmethods/hashdeepdupulicatable.rb +15 -15
  15. data/lib/striuct/classmethods/inner.rb +57 -55
  16. data/lib/striuct/classmethods/length.rb +12 -10
  17. data/lib/striuct/classmethods/macro.rb +99 -106
  18. data/lib/striuct/classmethods/names.rb +69 -65
  19. data/lib/striuct/classmethods/predicate.rb +131 -129
  20. data/lib/striuct/classmethods/requirements.rb +2 -2
  21. data/lib/striuct/classmethods/to_struct.rb +21 -18
  22. data/lib/striuct/classmethods/validation.rb +15 -13
  23. data/lib/striuct/instancemethods/README.md +2 -2
  24. data/lib/striuct/instancemethods/assign.rb +29 -27
  25. data/lib/striuct/instancemethods/cast.rb +28 -26
  26. data/lib/striuct/instancemethods/compare.rb +26 -24
  27. data/lib/striuct/instancemethods/default.rb +31 -29
  28. data/lib/striuct/instancemethods/delegate_class_methods.rb +35 -33
  29. data/lib/striuct/instancemethods/enum.rb +86 -84
  30. data/lib/striuct/instancemethods/getter.rb +39 -37
  31. data/lib/striuct/instancemethods/hashy.rb +99 -97
  32. data/lib/striuct/instancemethods/lock.rb +46 -44
  33. data/lib/striuct/instancemethods/object.rb +50 -48
  34. data/lib/striuct/instancemethods/requirements.rb +9 -13
  35. data/lib/striuct/instancemethods/safety.rb +11 -9
  36. data/lib/striuct/instancemethods/setter.rb +46 -45
  37. data/lib/striuct/instancemethods/to_s.rb +39 -37
  38. data/lib/striuct/instancemethods/validation.rb +46 -29
  39. data/lib/striuct/instancemethods/values.rb +50 -48
  40. data/lib/striuct/singleton_class.rb +25 -18
  41. data/lib/striuct/structs.rb +3 -3
  42. data/lib/striuct.rb +7 -3
  43. metadata +18 -209
  44. data/.gitignore +0 -35
  45. data/.travis.yml +0 -17
  46. data/.yardopts +0 -1
  47. data/Gemfile +0 -11
  48. data/MIT-LICENSE +0 -22
  49. data/Rakefile +0 -11
  50. data/benchmark/basics.rb +0 -56
  51. data/example/README.rb +0 -50
  52. data/example/example1.rb +0 -195
  53. data/example/example2.rb +0 -20
  54. data/example/see_trace.rb +0 -32
  55. data/lib/striuct/instancemethods/keyvalidatable.rb +0 -9
  56. data/striuct.gemspec +0 -45
  57. data/test/helper.rb +0 -3
  58. data/test/test_sglc-constructor.rb +0 -36
  59. data/test/test_subc-c-add_members.rb +0 -13
  60. data/test/test_subc-c-close_member.rb +0 -36
  61. data/test/test_subc-c-constructor.rb +0 -92
  62. data/test/test_subc-c-copy.rb +0 -71
  63. data/test/test_subc-c-freeze.rb +0 -36
  64. data/test/test_subc-c-inheritable.rb +0 -58
  65. data/test/test_subc-c-safety_naming.rb +0 -73
  66. data/test/test_subc-f-alias_member.rb +0 -54
  67. data/test/test_subc-f-enum.rb +0 -159
  68. data/test/test_subc-f-predicate.rb +0 -647
  69. data/test/test_subc-f-to_struct.rb +0 -61
  70. data/test/test_subc-f-validation_util.rb +0 -59
  71. data/test/test_subc-f_debug.rb +0 -39
  72. data/test/test_subc-f_name.rb +0 -525
  73. data/test/test_subc-i-accessor.rb +0 -138
  74. data/test/test_subc-i-adjuster.rb +0 -95
  75. data/test/test_subc-i-assign.rb +0 -53
  76. data/test/test_subc-i-basic.rb +0 -43
  77. data/test/test_subc-i-cast.rb +0 -27
  78. data/test/test_subc-i-compare.rb +0 -52
  79. data/test/test_subc-i-copy.rb +0 -23
  80. data/test/test_subc-i-default_value.rb +0 -129
  81. data/test/test_subc-i-freeze.rb +0 -19
  82. data/test/test_subc-i-hashlike.rb +0 -144
  83. data/test/test_subc-i-keyvalidatable.rb +0 -25
  84. data/test/test_subc-i-lock.rb +0 -40
  85. data/test/test_subc-i-must.rb +0 -30
  86. data/test/test_subc-i-to_s_family.rb +0 -26
  87. data/test/test_subc-i-validation_specific_conditions.rb +0 -297
  88. data/test/test_subc-i-validation_with_getter.rb +0 -33
  89. data/test/test_version.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a5238390f14805baa497d1cd3acec45fc10faa233ce94af4782aa5570606b56
4
- data.tar.gz: e703ea310209502b772938d9eee312e26fcfdec30189c41e071107b125574ebb
3
+ metadata.gz: 1a14fe7f8c251b39c9e7a8d65fc96b62519a6e271eb5765b043f92cfe1b8bc3b
4
+ data.tar.gz: be0b9456cee901dc7d0079e5661de91cda71b52cdae47fa1277cd7b833310126
5
5
  SHA512:
6
- metadata.gz: 4650584be9988e6f8ed9b1a58cfa5912d099aed4377e035750ee158216fa8bc06c46c53386bc5b1188dd302847112c337d750ac1a103810bd83ab25ae5f920c4
7
- data.tar.gz: 3edc0199746228322c017bf8eefc619352a53882cf908d9e525392faaa43a5314ec37529ce97cfc7b40917d2dbca5da393cb5580b3d8c1ae673cdeea22efdf42
6
+ metadata.gz: a7600df197c958a8fc6f37cfec1f0bff19ec3c1542f469ed12f927193f060c8e1a4c211d6c0d3411d344e9562714b7c8cf159469409c4635d0018abd5c855bcd
7
+ data.tar.gz: 03b8604868221c485c16c99ce1e428da36f2c5f9db6c0458957f460f0a16aaba55753043cb65901df1f695fc5c9bf069d0b09dae9aa88f50081200844d3ca9c1
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2011 Kenichi Kamiya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,52 +1,40 @@
1
- striuct
2
- =======
1
+ # striuct
3
2
 
4
- [![Build Status](https://secure.travis-ci.org/kachick/striuct.png)](http://travis-ci.org/kachick/striuct)
3
+ ![Build Status](https://github.com/kachick/striuct/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
5
4
  [![Gem Version](https://badge.fury.io/rb/striuct.png)](http://badge.fury.io/rb/striuct)
6
- [![Dependency Status](https://gemnasium.com/kachick/striuct.svg)](https://gemnasium.com/kachick/striuct)
7
-
8
- Description
9
- -----------
10
5
 
11
6
  Struct++
12
7
 
13
- Features
14
- --------
8
+ ## Usage
15
9
 
16
- ### Strict
10
+ Require Ruby 2.6 or later
17
11
 
18
- * Easy and Flexible Validations
19
- * Prevent to conflict member names
20
- * Lock setters for each member
12
+ Add this line to your `Gemfile`
21
13
 
22
- ### Useful
23
-
24
- * Hook just before setters
25
- * Default value
26
- * Member aliasing
27
- * Inheritable
28
- * Handling between nil <-> unassigned
29
- * More flendly API for Hash
14
+ ```ruby
15
+ gem 'striuct', '~> 0.9.0'
16
+ ```
30
17
 
31
- ### Onepoint
18
+ Then add below code into your Ruby code
32
19
 
33
- * Base API looks like Struct
34
- * Pure Ruby :)
20
+ ```ruby
21
+ require 'striuct'
22
+ ```
35
23
 
36
- Usage
37
- -----
24
+ ### Overview
38
25
 
39
- ### Overview - Case 1
26
+ #### Case 1
40
27
 
41
28
  ```ruby
42
29
  require 'striuct'
43
30
 
44
31
  class Person < Striuct
45
- member :fullname, AND(String, /\A.+\z/) # Flexible Validation
46
- alias_member :name, :fullname # Use other name
32
+ member :full_name, AND(String, /\A.+\z/) # Flexible Validation
33
+ alias_member :name, :full_name # Use other name
47
34
  end
48
35
 
49
- class User < Person # Inheritable
36
+ # Inheritable
37
+ class User < Person
50
38
  member :id, Integer, # Looks typed validation
51
39
  default_proc: ->{User.next_id} # With default value
52
40
 
@@ -57,13 +45,14 @@ class User < Person # Inheritable
57
45
  end
58
46
 
59
47
  john = User.new 'john'
60
- john[:name] #=> 'john'
48
+ john[:name] #=> 'john'
61
49
  john.name = '' #=> Exception # Validate with setter
62
50
  john.id #=> 1
63
51
  ken = User[name: 'ken'] # Construct from hash
64
52
  ken.id #=> 2
65
53
  ```
66
- ### Overview - Case 2
54
+
55
+ #### Case 2
67
56
 
68
57
  ```ruby
69
58
  class Foo < Striuct
@@ -75,7 +64,7 @@ end
75
64
 
76
65
  foo = Foo.new
77
66
 
78
- # nil <-> unaasigned
67
+ # nil <-> unassigned
79
68
  foo.foo #=> nil
80
69
  foo.assigned?(:foo) #=> false
81
70
  foo.foo = nil
@@ -93,7 +82,7 @@ foo.with_adjuster = '5'
93
82
  foo.with_adjuster #=> 5 # Casted via adjuster
94
83
  ```
95
84
 
96
- ### Overview - Case 3
85
+ #### Case 3
97
86
 
98
87
  ```ruby
99
88
  class UseMustOption < Striuct
@@ -103,37 +92,32 @@ end
103
92
  UseMustOption.new #=> InvalidOperationError "`foo` require a value under `must` option "
104
93
  ```
105
94
 
95
+ ## Features
106
96
 
107
- ### How to build flexible conditions ?
108
-
109
- * That from validation library.
110
- See the [validation-API](http://kachick.github.com/validation/yard/frames.html)
111
-
112
- Requirements
113
- -------------
97
+ ### Strict
114
98
 
115
- * Ruby - [2.2 or later](http://travis-ci.org/#!/kachick/striuct)
99
+ * Easy and Flexible Validations
100
+ * Basically use `#===` for the validation
101
+ * The pattern builder DSL is just using [eqq](https://github.com/kachick/eqq)
102
+ * When passed the Proc, it will be evaluated in the instance context
103
+ * Prevent to conflict member names
104
+ * Lock setters for each member
116
105
 
117
- Install
118
- -------
106
+ ### Useful
119
107
 
120
- ```bash
121
- gem install striuct
122
- ```
108
+ * Hook just before setters
109
+ * Default value
110
+ * Member aliasing
111
+ * Inheritable
112
+ * Handling between nil <-> unassigned
113
+ * Similar API for Hash
123
114
 
124
- Link
125
- ----
115
+ ### Finally
126
116
 
127
- * [Code](https://github.com/kachick/striuct)
128
- * [Wiki](https://github.com/kachick/striuct/wiki)
129
- * [API](http://www.rubydoc.info/github/kachick/striuct)
130
- * [Issues](https://github.com/kachick/striuct/issues)
131
- * [CI](http://travis-ci.org/#!/kachick/striuct)
132
- * [gem](https://rubygems.org/gems/striuct)
117
+ * Base API looks like Struct
118
+ * Pure Ruby :)
133
119
 
134
- License
135
- --------
120
+ ## Link
136
121
 
137
- The MIT X11 License
138
- Copyright (c) 2011 Kenichi Kamiya
139
- See MIT-LICENSE for further details.
122
+ * [Repository](https://github.com/kachick/striuct)
123
+ * [API documents](https://kachick.github.io/striuct/)
@@ -1,5 +1,9 @@
1
- require 'validation'
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'eqq'
5
+
2
6
  require_relative 'structs'
3
7
  require_relative 'classmethods/requirements'
4
8
  require_relative 'instancemethods/requirements'
5
- require_relative 'singleton_class'
9
+ require_relative 'singleton_class'
@@ -1,10 +1,10 @@
1
1
  Note
2
2
  =====
3
3
 
4
- This dir's tree is diveded under roles/features.
4
+ This dir's tree is divided under roles/features.
5
5
  Not only divided by CONSTANT names.
6
6
 
7
7
  CONSTANT
8
8
  --------
9
9
 
10
- * attributes - Attributes
10
+ * attributes - Attributes
@@ -1,15 +1,79 @@
1
- class Striuct; module ClassMethods
2
-
3
- # @group Adjuster
4
-
5
- # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
6
- def adjuster_for(key)
7
- autonym = autonym_for_key key
8
- raise KeyError unless with_adjuster? autonym
9
-
10
- _attributes_for(autonym).adjuster
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ class Striuct
4
+ module ClassMethods
5
+ # @group Adjuster
6
+
7
+ # Adjuster Builders
8
+ # Apply adjuster when passed pattern.
9
+ # @param pattern [Proc, Method, #===]
10
+ # @param adjuster [Proc, #to_proc]
11
+ # @return [Proc]
12
+ def WHEN(pattern, adjuster)
13
+ unless Eqq.pattern?(pattern)
14
+ raise ArgumentError, 'wrong object for pattern'
15
+ end
16
+
17
+ unless Striuct.adjustable?(adjuster)
18
+ raise ArgumentError, 'wrong object for adjuster'
19
+ end
20
+
21
+ ->v { _valid?(pattern, v) ? adjuster.call(v) : v }
22
+ end
23
+
24
+ # Sequential apply all adjusters.
25
+ # @param adjuster1 [Proc, #to_proc]
26
+ # @param adjuster2 [Proc, #to_proc]
27
+ # @param adjusters [Proc, #to_proc]
28
+ # @return [Proc]
29
+ def INJECT(adjuster1, adjuster2, *adjusters)
30
+ adjusters = [adjuster1, adjuster2, *adjusters]
12
31
 
13
- # @endgroup
32
+ unless adjusters.all? { |f| adjustable?(f) }
33
+ raise ArgumentError, 'wrong object for adjuster'
34
+ end
14
35
 
15
- end; end
36
+ ->v {
37
+ adjusters.reduce(v) { |ret, adjuster| adjuster.call(ret) }
38
+ }
39
+ end
40
+
41
+ # Accept any parser when that respond to parse method.
42
+ # @param parser [#parse]
43
+ # @return [Proc]
44
+ def PARSE(parser)
45
+ if !::Integer.equal?(parser) && !parser.respond_to?(:parse)
46
+ raise ArgumentError, 'wrong object for parser'
47
+ end
48
+
49
+ ->v {
50
+ if ::Integer.equal?(parser)
51
+ ::Kernel.Integer(v)
52
+ else
53
+ parser.parse(
54
+ case v
55
+ when String
56
+ v
57
+ when ->_ { v.respond_to?(:to_str) }
58
+ v.to_str
59
+ when ->_ { v.respond_to?(:read) }
60
+ v.read
61
+ else
62
+ raise TypeError, 'wrong object for parsing source'
63
+ end
64
+ )
65
+ end
66
+ }
67
+ end
68
+
69
+ # @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
70
+ def adjuster_for(key)
71
+ autonym = autonym_for_key(key)
72
+ raise KeyError unless with_adjuster?(autonym)
73
+
74
+ _attributes_for(autonym).adjuster
75
+ end
76
+
77
+ # @endgroup
78
+ end
79
+ end
@@ -1,114 +1,116 @@
1
- class Striuct; module ClassMethods
2
-
3
- # Attributes for autonym of each member
4
- class Attributes
5
-
6
- VALUES = [ :condition,
7
- :adjuster ].freeze
8
-
9
- BOOLEANS = [
10
- :must,
11
- :safety_setter,
12
- :safety_getter
13
- ].freeze
14
-
15
- def initialize
16
- @hash = {
17
- must: false,
18
- safety_setter: false,
19
- safety_getter: false
20
- }
21
- end
22
-
23
- VALUES.each do |role|
24
- define_method :"with_#{role}?" do
25
- @hash.has_key? role
1
+ # frozen_string_literal: true
2
+
3
+ class Striuct
4
+ module ClassMethods
5
+ # Attributes for autonym of each member
6
+ class Attributes
7
+ VALUES = [:condition,
8
+ :adjuster].freeze
9
+
10
+ BOOLEANS = [
11
+ :must,
12
+ :safety_setter,
13
+ :safety_getter
14
+ ].freeze
15
+
16
+ def initialize
17
+ @hash = {
18
+ must: false,
19
+ safety_setter: false,
20
+ safety_getter: false
21
+ }
26
22
  end
27
-
28
- define_method role do
29
- @hash.fetch role
23
+
24
+ VALUES.each do |role|
25
+ define_method :"with_#{role}?" do
26
+ @hash.key?(role)
27
+ end
28
+
29
+ define_method role do
30
+ @hash.fetch(role)
31
+ end
30
32
  end
31
- end
32
33
 
33
- def condition=(condition)
34
- unless ::Validation.conditionable? condition
35
- raise TypeError, 'wrong object for condition'
34
+ def condition=(condition)
35
+ unless Eqq.pattern?(condition)
36
+ raise TypeError, 'wrong object for condition'
37
+ end
38
+
39
+ @hash[:condition] = condition
36
40
  end
37
41
 
38
- @hash[:condition] = condition
39
- end
42
+ def adjuster=(adjuster)
43
+ unless Striuct.adjustable?(adjuster)
44
+ raise ArgumentError, 'wrong object for adjuster'
45
+ end
40
46
 
41
- def adjuster=(adjuster)
42
- unless ::Validation.adjustable? adjuster
43
- raise ArgumentError, 'wrong object for adjuster'
47
+ @hash[:adjuster] = adjuster
44
48
  end
45
49
 
46
- @hash[:adjuster] = adjuster
47
- end
50
+ BOOLEANS.each do |role|
51
+ define_method :"with_#{role}?" do
52
+ @hash.fetch(role)
53
+ end
54
+
55
+ define_method :"#{role}=" do |arg|
56
+ raise TypeError unless arg.equal?(true) || arg.equal?(false)
48
57
 
49
- BOOLEANS.each do |role|
50
- define_method :"with_#{role}?" do
51
- @hash.fetch role
58
+ @hash[role] = arg
59
+ end
52
60
  end
53
-
54
- define_method :"#{role}=" do |arg|
55
- raise TypeError unless arg.equal?(true) or arg.equal?(false)
56
61
 
57
- @hash[role] = arg
58
- end
59
- end
62
+ def with_default?
63
+ @hash.key?(:default_value)
64
+ end
60
65
 
61
- def with_default?
62
- @hash.has_key? :default_value
63
- end
66
+ def default_value
67
+ @hash.fetch(:default_value)
68
+ end
64
69
 
65
- def default_value
66
- @hash.fetch :default_value
67
- end
70
+ def default_type
71
+ @hash.fetch(:default_type)
72
+ end
68
73
 
69
- def default_type
70
- @hash.fetch :default_type
71
- end
74
+ # @param [Symbol] type - :value / :lazy
75
+ def set_default(value, type)
76
+ raise TypeError unless type.equal?(:value) || type.equal?(:lazy)
72
77
 
73
- # @param [Symbol] type - :value / :lazy
74
- def set_default(value, type)
75
- raise TypeError unless type.equal?(:value) or type.equal?(:lazy)
76
- check_default_lazy_proc value if type.equal?(:lazy)
77
-
78
- @hash[:default_type] = type
79
- @hash[:default_value] = value
80
- end
78
+ check_default_lazy_proc(value) if type.equal?(:lazy)
81
79
 
82
- def check_default_lazy_proc(_proc)
83
- raise TypeError unless _proc.respond_to? :call
84
- arity = _proc.arity
85
- unless arity <= 2
86
- raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
80
+ @hash[:default_type] = type
81
+ @hash[:default_value] = value
87
82
  end
88
- end
89
83
 
90
- def freeze
91
- ret = super
92
- @hash.freeze
93
- ret
94
- end
84
+ def check_default_lazy_proc(proc)
85
+ raise TypeError unless proc.respond_to?(:call)
95
86
 
96
- def dup
97
- ret = super
98
- @hash = @hash.dup
99
- ret
100
- end
101
-
102
- private
103
-
104
- def initialize_copy(original)
105
- ret = super original
106
- @hash = @hash.dup
107
- ret
108
- end
87
+ arity = proc.arity
88
+ unless arity <= 2
89
+ raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
90
+ end
91
+ end
109
92
 
110
- end
93
+ def freeze
94
+ ret = super
95
+ @hash.freeze
96
+ ret
97
+ end
98
+
99
+ def dup
100
+ ret = super
101
+ @hash = @hash.dup
102
+ ret
103
+ end
111
104
 
112
- private_constant :Attributes
105
+ private
113
106
 
114
- end; end
107
+ def initialize_copy(original)
108
+ ret = super(original)
109
+ @hash = @hash.dup
110
+ ret
111
+ end
112
+ end
113
+
114
+ private_constant :Attributes
115
+ end
116
+ end