domainic-type 0.1.0.alpha.2.1.0 → 0.1.0.alpha.3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/LICENSE +1 -1
  4. data/README.md +28 -4
  5. data/lib/domainic/type/accessors.rb +41 -0
  6. data/lib/domainic/type/behavior/enumerable_behavior.rb +262 -0
  7. data/lib/domainic/type/behavior/numeric_behavior.rb +340 -0
  8. data/lib/domainic/type/behavior/sizable_behavior.rb +246 -0
  9. data/lib/domainic/type/behavior/string_behavior.rb +379 -0
  10. data/lib/domainic/type/behavior.rb +239 -0
  11. data/lib/domainic/type/config/registry.yml +101 -0
  12. data/lib/domainic/type/constraint/behavior.rb +342 -0
  13. data/lib/domainic/type/constraint/constraints/all_constraint.rb +81 -0
  14. data/lib/domainic/type/constraint/constraints/and_constraint.rb +105 -0
  15. data/lib/domainic/type/constraint/constraints/any_constraint.rb +83 -0
  16. data/lib/domainic/type/constraint/constraints/case_constraint.rb +104 -0
  17. data/lib/domainic/type/constraint/constraints/character_set_constraint.rb +111 -0
  18. data/lib/domainic/type/constraint/constraints/divisibility_constraint.rb +126 -0
  19. data/lib/domainic/type/constraint/constraints/emptiness_constraint.rb +69 -0
  20. data/lib/domainic/type/constraint/constraints/equality_constraint.rb +75 -0
  21. data/lib/domainic/type/constraint/constraints/finiteness_constraint.rb +123 -0
  22. data/lib/domainic/type/constraint/constraints/inclusion_constraint.rb +74 -0
  23. data/lib/domainic/type/constraint/constraints/match_pattern_constraint.rb +87 -0
  24. data/lib/domainic/type/constraint/constraints/method_presence_constraint.rb +72 -0
  25. data/lib/domainic/type/constraint/constraints/none_constraint.rb +83 -0
  26. data/lib/domainic/type/constraint/constraints/nor_constraint.rb +105 -0
  27. data/lib/domainic/type/constraint/constraints/not_constraint.rb +76 -0
  28. data/lib/domainic/type/constraint/constraints/or_constraint.rb +106 -0
  29. data/lib/domainic/type/constraint/constraints/ordering_constraint.rb +75 -0
  30. data/lib/domainic/type/constraint/constraints/parity_constraint.rb +102 -0
  31. data/lib/domainic/type/constraint/constraints/polarity_constraint.rb +147 -0
  32. data/lib/domainic/type/constraint/constraints/range_constraint.rb +135 -0
  33. data/lib/domainic/type/constraint/constraints/type_constraint.rb +110 -0
  34. data/lib/domainic/type/constraint/constraints/uniqueness_constraint.rb +69 -0
  35. data/lib/domainic/type/constraint/resolver.rb +172 -0
  36. data/lib/domainic/type/constraint/set.rb +266 -0
  37. data/lib/domainic/type/definitions.rb +364 -0
  38. data/lib/domainic/type/types/core/array_type.rb +48 -0
  39. data/lib/domainic/type/types/core/float_type.rb +39 -0
  40. data/lib/domainic/type/types/core/hash_type.rb +143 -0
  41. data/lib/domainic/type/types/core/integer_type.rb +38 -0
  42. data/lib/domainic/type/types/core/string_type.rb +51 -0
  43. data/lib/domainic/type/types/core/symbol_type.rb +51 -0
  44. data/lib/domainic/type/types/specification/anything_type.rb +22 -0
  45. data/lib/domainic/type/types/specification/duck_type.rb +55 -0
  46. data/lib/domainic/type/types/specification/enum_type.rb +26 -0
  47. data/lib/domainic/type/types/specification/union_type.rb +26 -0
  48. data/lib/domainic/type/types/specification/void_type.rb +12 -0
  49. data/lib/domainic/type.rb +7 -0
  50. data/lib/domainic-type.rb +3 -0
  51. data/sig/domainic/type/accessors.rbs +22 -0
  52. data/sig/domainic/type/behavior/enumerable_behavior.rbs +238 -0
  53. data/sig/domainic/type/behavior/numeric_behavior.rbs +299 -0
  54. data/sig/domainic/type/behavior/sizable_behavior.rbs +218 -0
  55. data/sig/domainic/type/behavior/string_behavior.rbs +315 -0
  56. data/sig/domainic/type/behavior.rbs +153 -0
  57. data/sig/domainic/type/constraint/behavior.rbs +258 -0
  58. data/sig/domainic/type/constraint/constraints/all_constraint.rbs +55 -0
  59. data/sig/domainic/type/constraint/constraints/and_constraint.rbs +72 -0
  60. data/sig/domainic/type/constraint/constraints/any_constraint.rbs +57 -0
  61. data/sig/domainic/type/constraint/constraints/case_constraint.rbs +73 -0
  62. data/sig/domainic/type/constraint/constraints/character_set_constraint.rbs +82 -0
  63. data/sig/domainic/type/constraint/constraints/divisibility_constraint.rbs +91 -0
  64. data/sig/domainic/type/constraint/constraints/emptiness_constraint.rbs +54 -0
  65. data/sig/domainic/type/constraint/constraints/equality_constraint.rbs +60 -0
  66. data/sig/domainic/type/constraint/constraints/finiteness_constraint.rbs +82 -0
  67. data/sig/domainic/type/constraint/constraints/inclusion_constraint.rbs +59 -0
  68. data/sig/domainic/type/constraint/constraints/match_pattern_constraint.rbs +66 -0
  69. data/sig/domainic/type/constraint/constraints/method_presence_constraint.rbs +51 -0
  70. data/sig/domainic/type/constraint/constraints/none_constraint.rbs +57 -0
  71. data/sig/domainic/type/constraint/constraints/nor_constraint.rbs +72 -0
  72. data/sig/domainic/type/constraint/constraints/not_constraint.rbs +56 -0
  73. data/sig/domainic/type/constraint/constraints/or_constraint.rbs +74 -0
  74. data/sig/domainic/type/constraint/constraints/ordering_constraint.rbs +60 -0
  75. data/sig/domainic/type/constraint/constraints/parity_constraint.rbs +71 -0
  76. data/sig/domainic/type/constraint/constraints/polarity_constraint.rbs +101 -0
  77. data/sig/domainic/type/constraint/constraints/range_constraint.rbs +88 -0
  78. data/sig/domainic/type/constraint/constraints/type_constraint.rbs +86 -0
  79. data/sig/domainic/type/constraint/constraints/uniqueness_constraint.rbs +54 -0
  80. data/sig/domainic/type/constraint/resolver.rbs +117 -0
  81. data/sig/domainic/type/constraint/set.rbs +159 -0
  82. data/sig/domainic/type/definitions.rbs +304 -0
  83. data/sig/domainic/type/types/core/array_type.rbs +42 -0
  84. data/sig/domainic/type/types/core/float_type.rbs +33 -0
  85. data/sig/domainic/type/types/core/hash_type.rbs +107 -0
  86. data/sig/domainic/type/types/core/integer_type.rbs +32 -0
  87. data/sig/domainic/type/types/core/string_type.rbs +45 -0
  88. data/sig/domainic/type/types/core/symbol_type.rbs +45 -0
  89. data/sig/domainic/type/types/specification/anything_type.rbs +14 -0
  90. data/sig/domainic/type/types/specification/duck_type.rbs +41 -0
  91. data/sig/domainic/type/types/specification/enum_type.rbs +14 -0
  92. data/sig/domainic/type/types/specification/union_type.rbs +14 -0
  93. data/sig/domainic/type/types/specification/void_type.rbs +8 -0
  94. data/sig/domainic/type.rbs +5 -0
  95. data/sig/domainic-type.rbs +1 -0
  96. data/sig/manifest.yaml +2 -0
  97. metadata +108 -71
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+ require 'domainic/type/behavior/string_behavior'
5
+
6
+ module Domainic
7
+ module Type
8
+ # A type for validating Symbol objects with string-like constraints
9
+ #
10
+ # This type provides symbol validation capabilities by leveraging string validation
11
+ # behaviors. It enables validation of symbols using string-based constraints while
12
+ # maintaining proper type checking for Symbol objects.
13
+ #
14
+ # Key features:
15
+ # - Basic symbol type validation
16
+ # - Case checking for symbol names
17
+ # - Character set validation for symbol names
18
+ # - Pattern matching against symbol names
19
+ # - Length constraints for symbol names
20
+ # - String content validation for symbol names
21
+ #
22
+ # @example Basic usage
23
+ # type = SymbolType.new
24
+ # type.validate(:hello) # => true
25
+ # type.validate("hello") # => false
26
+ #
27
+ # @example Complex symbol validation
28
+ # type = SymbolType.new
29
+ # .being_ascii
30
+ # .being_lowercase
31
+ # .having_size_between(2, 30)
32
+ # .matching(/^[a-z]/)
33
+ #
34
+ # @example Symbol name validation
35
+ # type = SymbolType.new
36
+ # .being_alphanumeric
37
+ # .not_matching(/\W/)
38
+ # .having_minimum_size(1)
39
+ #
40
+ # @author {https://aaronmallen.me Aaron Allen}
41
+ # @since 0.1.0
42
+ class SymbolType
43
+ # @rbs! extend Behavior::ClassMethods
44
+
45
+ include Behavior
46
+ include Behavior::StringBehavior
47
+
48
+ intrinsic :self, :type, Symbol, abort_on_failure: true, description: :not_described
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+
5
+ module Domainic
6
+ module Type
7
+ # @since 0.1.0
8
+ class AnythingType
9
+ include Behavior
10
+
11
+ # @rbs (*untyped types) -> self
12
+ def but(*types)
13
+ not_types = types.map do |type|
14
+ @constraints.prepare(:self, :not, @constraints.prepare(:self, :type, type))
15
+ end
16
+ constrain :self, :and, not_types, concerning: :exclusion
17
+ end
18
+ alias except but
19
+ alias excluding but
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+
5
+ module Domainic
6
+ module Type
7
+ # A type that validates objects based on their method interface
8
+ #
9
+ # This type implements duck typing validation by checking whether objects respond
10
+ # to specific methods. It supports both positive validation (must respond to methods)
11
+ # and negative validation (must not respond to methods).
12
+ #
13
+ # @example Validating a simple interface
14
+ # type = DuckType.responding_to(:to_s).not_responding_to(:to_h)
15
+ # type.validate("string") # => true
16
+ # type.validate(Object.new) # => true
17
+ # type.validate({}) # => false (responds to :to_h)
18
+ #
19
+ # @author {https://aaronmallen.me Aaron Allen}
20
+ # @since 0.1.0
21
+ class DuckType
22
+ include Behavior
23
+
24
+ # Add method exclusion constraints to the type
25
+ #
26
+ # @example
27
+ # type = DuckType.new.not_responding_to(:foo, :bar)
28
+ #
29
+ # @param methods [Array<String, Symbol>] the methods that must not be present
30
+ #
31
+ # @return [self] the type for method chaining
32
+ # @rbs (*String | Symbol methods) -> self
33
+ def not_responding_to(*methods)
34
+ not_methods = methods.map do |method|
35
+ @constraints.prepare(:self, :not, @constraints.prepare(:self, :method_presence, method))
36
+ end
37
+ constrain :self, :and, not_methods, concerning: :method_exclusion
38
+ end
39
+
40
+ # Add method presence constraints to the type
41
+ #
42
+ # @example
43
+ # type = DuckType.new.responding_to(:foo, :bar)
44
+ #
45
+ # @param methods [Array<String, Symbol>] the methods that must be present
46
+ #
47
+ # @return [self] the type for method chaining
48
+ # @rbs (*String | Symbol methods) -> self
49
+ def responding_to(*methods)
50
+ methods = methods.map { |method| @constraints.prepare :self, :method_presence, method }
51
+ constrain :self, :and, methods, concerning: :method_presence
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+
5
+ module Domainic
6
+ module Type
7
+ # @since 0.1.0
8
+ class EnumType
9
+ include Behavior
10
+
11
+ # @rbs (*untyped literals, **untyped options) -> void
12
+ def initialize(*literals, **options)
13
+ super(**options.merge(literal: literals))
14
+ end
15
+
16
+ # @rbs (*untyped literals) -> void
17
+ def literal(*literals)
18
+ literals = literals.map do |literal|
19
+ @constraints.prepare :self, :equality, literal
20
+ end
21
+ constrain :self, :or, literals
22
+ end
23
+ alias value literal
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+
5
+ module Domainic
6
+ module Type
7
+ # @since 0.1.0
8
+ class UnionType
9
+ include Behavior
10
+
11
+ # @rbs (*Class | Module | Behavior[untyped, untyped, untyped] types, **untyped options) -> void
12
+ def initialize(*types, **options)
13
+ super(**options.merge(type: types))
14
+ end
15
+
16
+ # @rbs (*Class | Module | Behavior[untyped, untyped, untyped] types) -> self
17
+ def type(*types)
18
+ types = types.map do |type|
19
+ @constraints.prepare :self, :type, type
20
+ end
21
+ constrain :self, :or, types, concerning: :inclusion
22
+ end
23
+ alias or type
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type/behavior'
4
+
5
+ module Domainic
6
+ module Type
7
+ # @since 0.1.0
8
+ class VoidType
9
+ include Behavior
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Domainic
4
+ # @since 0.1.0
5
+ module Type
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'domainic/type'
@@ -0,0 +1,22 @@
1
+ module Domainic
2
+ module Type
3
+ type accessor = :abs | :begin | :chars | :class | :count | :end | :entries | :first | :keys | :last | :length | :self | :size | :values
4
+
5
+ # A list of valid access methods that can be used to retrieve values for constraint validation.
6
+ # These methods represent common Ruby interfaces for accessing collection sizes, ranges, and values.
7
+ #
8
+ # - :abs - For absolute values
9
+ # - :begin, :end - For Range-like objects
10
+ # - :class - For type checking
11
+ # - :count, :length, :size - For measuring collections
12
+ # - :entries, :chars - For accessing sequence elements
13
+ # - :first, :last - For accessing sequence endpoints
14
+ # - :keys, :values - For Hash-like objects
15
+ # - :self - For operating directly on the value
16
+ #
17
+ # @author {https://aaronmallen.me Aaron Allen}
18
+ # @since 0.1.0
19
+ # @return [Array<Symbol>]
20
+ ACCESSORS: Array[accessor]
21
+ end
22
+ end
@@ -0,0 +1,238 @@
1
+ module Domainic
2
+ module Type
3
+ module Behavior
4
+ # A module providing enumerable-specific validation behaviors for types.
5
+ #
6
+ # This module extends the base Type::Behavior with methods specifically designed for validating enumerable
7
+ # collections. It provides a fluent interface for common enumerable validations such as uniqueness, emptiness,
8
+ # ordering, and size constraints.
9
+ #
10
+ # @example Basic usage
11
+ # class ArrayType
12
+ # include Domainic::Type::Behavior::EnumerableBehavior
13
+ #
14
+ # def initialize
15
+ # super
16
+ # being_empty # validates array is empty
17
+ # having_minimum_count(5) # validates at least 5 elements
18
+ # containing(1, 2, 3) # validates specific elements
19
+ # end
20
+ # end
21
+ #
22
+ # @example Combining constraints
23
+ # class OrderedArrayType
24
+ # include Domainic::Type::Behavior::EnumerableBehavior
25
+ #
26
+ # def initialize
27
+ # super
28
+ # being_ordered
29
+ # being_populated
30
+ # having_maximum_count(10)
31
+ # end
32
+ # end
33
+ #
34
+ # @author {https://aaronmallen.me Aaron Allen}
35
+ # @since 0.1.0
36
+ module EnumerableBehavior
37
+ include SizableBehavior
38
+
39
+ def being_distinct: () -> untyped
40
+
41
+ alias being_unique being_distinct
42
+
43
+ alias distinct being_distinct
44
+
45
+ alias unique being_distinct
46
+
47
+ # Validate that the enumerable contains duplicate elements.
48
+ #
49
+ # Creates an inverse uniqueness constraint that ensures the collection has at least one duplicate element.
50
+ #
51
+ # @example
52
+ # type.being_duplicative
53
+ # type.validate([1, 1, 2]) # => true
54
+ # type.validate([1, 2, 3]) # => false
55
+ #
56
+ # @return [self] self for method chaining
57
+ def being_duplicative: () -> Behavior
58
+
59
+ alias being_redundant being_duplicative
60
+
61
+ alias being_repetitive being_duplicative
62
+
63
+ alias duplicative being_duplicative
64
+
65
+ alias redundant being_duplicative
66
+
67
+ alias repetitive being_duplicative
68
+
69
+ # Validate that the enumerable is empty.
70
+ #
71
+ # Creates a constraint that ensures the collection has no elements.
72
+ #
73
+ # @example
74
+ # type.being_empty
75
+ # type.validate([]) # => true
76
+ # type.validate([1]) # => false
77
+ #
78
+ # @return [self] self for method chaining
79
+ def being_empty: () -> Behavior
80
+
81
+ alias being_vacant being_empty
82
+
83
+ alias empty being_empty
84
+
85
+ alias vacant being_empty
86
+
87
+ # Validate that the enumerable contains elements.
88
+ #
89
+ # Creates an inverse emptiness constraint that ensures the collection has at least one element.
90
+ #
91
+ # @example
92
+ # type.being_populated
93
+ # type.validate([1]) # => true
94
+ # type.validate([]) # => false
95
+ #
96
+ # @return [self] self for method chaining
97
+ def being_populated: () -> Behavior
98
+
99
+ alias being_inhabited being_populated
100
+
101
+ alias being_occupied being_populated
102
+
103
+ alias populated being_populated
104
+
105
+ alias inhabited being_populated
106
+
107
+ alias occupied being_populated
108
+
109
+ # Validate that the enumerable elements are in sorted order.
110
+ #
111
+ # Creates a constraint that ensures the collection's elements are in ascending order based on their natural
112
+ # comparison methods.
113
+ #
114
+ # @example
115
+ # type.being_ordered
116
+ # type.validate([1, 2, 3]) # => true
117
+ # type.validate([3, 1, 2]) # => false
118
+ #
119
+ # @return [self] self for method chaining
120
+ def being_sorted: () -> Behavior
121
+
122
+ alias being_aranged being_sorted
123
+
124
+ alias being_ordered being_sorted
125
+
126
+ alias being_sequential being_sorted
127
+
128
+ alias aranged being_sorted
129
+
130
+ alias ordered being_sorted
131
+
132
+ alias sorted being_sorted
133
+
134
+ alias sequential being_sorted
135
+
136
+ # Validate that the enumerable elements are not in sorted order.
137
+ #
138
+ # Creates an inverse ordering constraint that ensures the collection's elements are not in ascending order.
139
+ #
140
+ # @example
141
+ # type.being_unordered
142
+ # type.validate([3, 1, 2]) # => true
143
+ # type.validate([1, 2, 3]) # => false
144
+ #
145
+ # @return [self] self for method chaining
146
+ def being_unsorted: () -> Behavior
147
+
148
+ alias being_disordered being_unsorted
149
+
150
+ alias being_unordered being_unsorted
151
+
152
+ alias disordered being_unsorted
153
+
154
+ alias unsorted being_unsorted
155
+
156
+ alias unordered being_unsorted
157
+
158
+ # Validate that the enumerable contains specific entries.
159
+ #
160
+ # Creates a series of inclusion constraints ensuring the collection contains all specified elements.
161
+ #
162
+ # @example
163
+ # type.containing(1, 2)
164
+ # type.validate([1, 2, 3]) # => true
165
+ # type.validate([1, 3]) # => false
166
+ #
167
+ # @param entries [Array<Object>] the elements that must be present
168
+ # @return [self] self for method chaining
169
+ def containing: (*untyped entries) -> Behavior
170
+
171
+ alias including containing
172
+
173
+ # Validate that the enumerable contains a specific last entry.
174
+ #
175
+ # Creates an equality constraint on the collection's last entry ensuring it is equal to the specified value.
176
+ #
177
+ # @example
178
+ # type.having_last_entry(3)
179
+ # type.validate([1, 2, 3]) # => true
180
+ # type.validate([1, 3, 2]) # => false
181
+ #
182
+ # @param literal [Object] the value that must be the last entry
183
+ # @return [self] self for method chaining
184
+ def ending_with: (untyped literal) -> Behavior
185
+
186
+ alias closing_with ending_with
187
+
188
+ alias finishing_with ending_with
189
+
190
+ # Validate that the enumerable does not contain specific entries.
191
+ #
192
+ # Creates a series of exclusion constraints ensuring the collection does not contain any of the specified
193
+ # elements.
194
+ #
195
+ # @example
196
+ # type.excluding(1, 2)
197
+ # type.validate([3, 4, 5]) # => true
198
+ # type.validate([1, 2, 3]) # => false
199
+ #
200
+ # @param entries [Array<Object>] the elements that must not be present
201
+ # @return [self] self for method chaining
202
+ def excluding: (*untyped entries) -> Behavior
203
+
204
+ alias omitting excluding
205
+
206
+ # Validate that the enumerable contains elements of a specific type.
207
+ #
208
+ # Creates a type constraint on the collection's elements ensuring they are all of the specified type.
209
+ #
210
+ # @example
211
+ # type.of(String)
212
+ # type.validate(['a', 'b', 'c']) # => true
213
+ # type.validate(['a', 1, 'c']) # => false
214
+ #
215
+ # @param type [Class, Module, Behavior] the type that all elements must be
216
+ # @return [self] self for method chaining
217
+ def of: (Class | Module | Behavior type) -> Behavior
218
+
219
+ # Validate that the enumerable contains a specific first entry.
220
+ #
221
+ # Creates an equality constraint on the collection's first entry ensuring it is equal to the specified value.
222
+ #
223
+ # @example
224
+ # type.having_first_entry(1)
225
+ # type.validate([1, 2, 3]) # => true
226
+ # type.validate([2, 3, 1]) # => false
227
+ #
228
+ # @param literal [Object] the value that must be the first entry
229
+ # @return [self] self for method chaining
230
+ def starting_with: (untyped literal) -> Behavior
231
+
232
+ alias begining_with starting_with
233
+
234
+ alias leading_with starting_with
235
+ end
236
+ end
237
+ end
238
+ end