stannum 0.1.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 (79) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +21 -0
  3. data/CODE_OF_CONDUCT.md +132 -0
  4. data/DEVELOPMENT.md +105 -0
  5. data/LICENSE +22 -0
  6. data/README.md +1327 -0
  7. data/config/locales/en.rb +47 -0
  8. data/lib/stannum/attribute.rb +115 -0
  9. data/lib/stannum/constraint.rb +65 -0
  10. data/lib/stannum/constraints/absence.rb +42 -0
  11. data/lib/stannum/constraints/anything.rb +28 -0
  12. data/lib/stannum/constraints/base.rb +285 -0
  13. data/lib/stannum/constraints/boolean.rb +33 -0
  14. data/lib/stannum/constraints/delegator.rb +71 -0
  15. data/lib/stannum/constraints/enum.rb +64 -0
  16. data/lib/stannum/constraints/equality.rb +47 -0
  17. data/lib/stannum/constraints/hashes/extra_keys.rb +126 -0
  18. data/lib/stannum/constraints/hashes/indifferent_key.rb +74 -0
  19. data/lib/stannum/constraints/hashes.rb +11 -0
  20. data/lib/stannum/constraints/identity.rb +46 -0
  21. data/lib/stannum/constraints/nothing.rb +28 -0
  22. data/lib/stannum/constraints/presence.rb +42 -0
  23. data/lib/stannum/constraints/signature.rb +92 -0
  24. data/lib/stannum/constraints/signatures/map.rb +17 -0
  25. data/lib/stannum/constraints/signatures/tuple.rb +17 -0
  26. data/lib/stannum/constraints/signatures.rb +11 -0
  27. data/lib/stannum/constraints/tuples/extra_items.rb +84 -0
  28. data/lib/stannum/constraints/tuples.rb +10 -0
  29. data/lib/stannum/constraints/type.rb +113 -0
  30. data/lib/stannum/constraints/types/array_type.rb +148 -0
  31. data/lib/stannum/constraints/types/big_decimal_type.rb +16 -0
  32. data/lib/stannum/constraints/types/date_time_type.rb +16 -0
  33. data/lib/stannum/constraints/types/date_type.rb +16 -0
  34. data/lib/stannum/constraints/types/float_type.rb +14 -0
  35. data/lib/stannum/constraints/types/hash_type.rb +205 -0
  36. data/lib/stannum/constraints/types/hash_with_indifferent_keys.rb +21 -0
  37. data/lib/stannum/constraints/types/hash_with_string_keys.rb +21 -0
  38. data/lib/stannum/constraints/types/hash_with_symbol_keys.rb +21 -0
  39. data/lib/stannum/constraints/types/integer_type.rb +14 -0
  40. data/lib/stannum/constraints/types/nil_type.rb +20 -0
  41. data/lib/stannum/constraints/types/proc_type.rb +14 -0
  42. data/lib/stannum/constraints/types/string_type.rb +14 -0
  43. data/lib/stannum/constraints/types/symbol_type.rb +14 -0
  44. data/lib/stannum/constraints/types/time_type.rb +14 -0
  45. data/lib/stannum/constraints/types.rb +25 -0
  46. data/lib/stannum/constraints/union.rb +85 -0
  47. data/lib/stannum/constraints.rb +26 -0
  48. data/lib/stannum/contract.rb +243 -0
  49. data/lib/stannum/contracts/array_contract.rb +108 -0
  50. data/lib/stannum/contracts/base.rb +597 -0
  51. data/lib/stannum/contracts/builder.rb +72 -0
  52. data/lib/stannum/contracts/definition.rb +74 -0
  53. data/lib/stannum/contracts/hash_contract.rb +136 -0
  54. data/lib/stannum/contracts/indifferent_hash_contract.rb +78 -0
  55. data/lib/stannum/contracts/map_contract.rb +199 -0
  56. data/lib/stannum/contracts/parameters/arguments_contract.rb +185 -0
  57. data/lib/stannum/contracts/parameters/keywords_contract.rb +174 -0
  58. data/lib/stannum/contracts/parameters/signature_contract.rb +29 -0
  59. data/lib/stannum/contracts/parameters.rb +15 -0
  60. data/lib/stannum/contracts/parameters_contract.rb +530 -0
  61. data/lib/stannum/contracts/tuple_contract.rb +213 -0
  62. data/lib/stannum/contracts.rb +19 -0
  63. data/lib/stannum/errors.rb +730 -0
  64. data/lib/stannum/messages/default_strategy.rb +124 -0
  65. data/lib/stannum/messages.rb +25 -0
  66. data/lib/stannum/parameter_validation.rb +216 -0
  67. data/lib/stannum/rspec/match_errors.rb +17 -0
  68. data/lib/stannum/rspec/match_errors_matcher.rb +93 -0
  69. data/lib/stannum/rspec/validate_parameter.rb +23 -0
  70. data/lib/stannum/rspec/validate_parameter_matcher.rb +506 -0
  71. data/lib/stannum/rspec.rb +8 -0
  72. data/lib/stannum/schema.rb +131 -0
  73. data/lib/stannum/struct.rb +444 -0
  74. data/lib/stannum/support/coercion.rb +114 -0
  75. data/lib/stannum/support/optional.rb +69 -0
  76. data/lib/stannum/support.rb +8 -0
  77. data/lib/stannum/version.rb +57 -0
  78. data/lib/stannum.rb +27 -0
  79. metadata +216 -0
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/base'
4
+ require 'stannum/support/optional'
5
+
6
+ module Stannum::Constraints
7
+ # A type constraint asserts that the object is of the expected type.
8
+ #
9
+ # @example Using a Type constraint with a Class
10
+ # constraint = Stannum::Constraints::Type.new(StandardError)
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?(StandardError.new) # => true
15
+ # constraint.matches?(RuntimeError.new) # => true
16
+ #
17
+ # @example Using a Type constraint with a Module
18
+ # constraint = Stannum::Constraints::Type.new(Enumerable)
19
+ #
20
+ # constraint.matches?(nil) #=> false
21
+ # constraint.matches?(Object.new) #=> false
22
+ # constraint.matches?(Array) #=> true
23
+ # constraint.matches?(Object.new.extend(Enumerable)) #=> true
24
+ #
25
+ # @example Using a Type constraint with a Class name
26
+ # constraint = Stannum::Constraints::Type.new('StandardError')
27
+ #
28
+ # constraint.matches?(nil) # => false
29
+ # constraint.matches?(Object.new) # => false
30
+ # constraint.matches?(StandardError.new) # => true
31
+ # constraint.matches?(RuntimeError.new) # => true
32
+ class Type < Stannum::Constraints::Base
33
+ include Stannum::Support::Optional
34
+
35
+ # The :type of the error generated for a matching object.
36
+ NEGATED_TYPE = 'stannum.constraints.is_type'
37
+
38
+ # The :type of the error generated for a non-matching object.
39
+ TYPE = 'stannum.constraints.is_not_type'
40
+
41
+ # @param expected_type [Class, Module, String] The type the object is
42
+ # expected to belong to. Can be a Class or a Module, or the name of a
43
+ # class or module.
44
+ # @param options [Hash<Symbol, Object>] Configuration options for the
45
+ # constraint. Defaults to an empty Hash.
46
+ def initialize(expected_type, optional: nil, required: nil, **options)
47
+ expected_type = resolve_expected_type(expected_type)
48
+
49
+ super(
50
+ expected_type: expected_type,
51
+ **resolve_required_option(
52
+ optional: optional,
53
+ required: required,
54
+ **options
55
+ )
56
+ )
57
+ end
58
+
59
+ # (see Stannum::Constraints::Base#errors_for)
60
+ def errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
61
+ (errors || Stannum::Errors.new).add(type, **error_properties)
62
+ end
63
+
64
+ # @return [Class, Module, String] the type the object is expected to belong
65
+ # to.
66
+ def expected_type
67
+ options[:expected_type]
68
+ end
69
+
70
+ # Checks that the object is an instance of the expected type.
71
+ #
72
+ # @return [true, false] true if the object is an instance of the expected
73
+ # type, otherwise false.
74
+ #
75
+ # @see Stannum::Constraint#matches?
76
+ def matches?(actual)
77
+ matches_type?(actual)
78
+ end
79
+ alias match? matches?
80
+
81
+ # (see Stannum::Constraints::Base#negated_errors_for)
82
+ def negated_errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
83
+ (errors || Stannum::Errors.new).add(negated_type, **error_properties)
84
+ end
85
+
86
+ # (see Stannum::Constraints::Base#with_options)
87
+ def with_options(**options)
88
+ options = options.merge(required_by_default: required?)
89
+
90
+ super(**resolve_required_option(**options))
91
+ end
92
+
93
+ private
94
+
95
+ def error_properties
96
+ { required: required?, type: expected_type }
97
+ end
98
+
99
+ def matches_type?(actual)
100
+ actual.is_a?(expected_type) || (optional? && actual.nil?)
101
+ end
102
+
103
+ def resolve_expected_type(type_or_name)
104
+ return type_or_name if type_or_name.is_a?(Module)
105
+
106
+ return Object.const_get(type_or_name) if type_or_name.is_a?(String)
107
+
108
+ raise ArgumentError,
109
+ 'expected type must be a Class or Module',
110
+ caller[1..-1]
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+ require 'stannum/support/coercion'
5
+
6
+ module Stannum::Constraints::Types
7
+ # An Array type constraint asserts that the object is an Array.
8
+ #
9
+ # @example Using an Array type constraint
10
+ # constraint = Stannum::Constraints::Types::ArrayType.new
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?([]) # => true
15
+ # constraint.matches?([1, 2, 3]) # => true
16
+ #
17
+ # @example Using an Array type constraint with an item constraint
18
+ # constraint = Stannum::Constraints::Types::ArrayType.new(item_type: String)
19
+ #
20
+ # constraint.matches?(nil) # => false
21
+ # constraint.matches?(Object.new) # => false
22
+ # constraint.matches?([]) # => true
23
+ # constraint.matches?([1, 2, 3]) # => false
24
+ # constraint.matches?(%w[one two three]) # => true
25
+ #
26
+ # @example Using an Array type constraint with a presence constraint
27
+ # constraint = Stannum::Constraints::Types::ArrayType.new(allow_empty: false)
28
+ #
29
+ # constraint.matches?(nil) # => false
30
+ # constraint.matches?(Object.new) # => false
31
+ # constraint.matches?([]) # => false
32
+ # constraint.matches?([1, 2, 3]) # => true
33
+ # constraint.matches?(%w[one two three]) # => true
34
+ class ArrayType < Stannum::Constraints::Type
35
+ # @param allow_empty [true, false] If false, then the constraint will not
36
+ # match against an Array with no items.
37
+ # @param item_type [Stannum::Constraints::Base, Class, nil] If set, then
38
+ # the constraint will check the types of each item in the Array against
39
+ # the expected type and will fail if any items do not match.
40
+ # @param options [Hash<Symbol, Object>] Configuration options for the
41
+ # constraint. Defaults to an empty Hash.
42
+ def initialize(allow_empty: true, item_type: nil, **options)
43
+ super(
44
+ ::Array,
45
+ allow_empty: !!allow_empty,
46
+ item_type: coerce_item_type(item_type),
47
+ **options
48
+ )
49
+ end
50
+
51
+ # @return [true, false] if false, then the constraint will not
52
+ # match against an Array with no items.
53
+ def allow_empty?
54
+ options[:allow_empty]
55
+ end
56
+
57
+ # Checks that the object is not an Array instance.
58
+ #
59
+ # @return [true, false] true if the object is not an Array instance,
60
+ # otherwise false.
61
+ #
62
+ # @see Stannum::Constraints::Types::ArrayType#matches?
63
+ def does_not_match?(actual)
64
+ !matches_type?(actual)
65
+ end
66
+
67
+ # (see Stannum::Constraints::Base#errors_for)
68
+ def errors_for(actual, errors: nil)
69
+ return super unless actual.is_a?(expected_type)
70
+
71
+ errors ||= Stannum::Errors.new
72
+
73
+ return add_presence_error(errors) unless presence_matches?(actual)
74
+
75
+ unless item_type_matches?(actual)
76
+ non_matching_items(actual).each do |item, index|
77
+ item_type.errors_for(item, errors: errors[index])
78
+ end
79
+ end
80
+
81
+ errors
82
+ end
83
+
84
+ # @return [Stannum::Constraints::Base, nil] the expected type for the items
85
+ # in the array.
86
+ def item_type
87
+ options[:item_type]
88
+ end
89
+
90
+ # Checks that the object is an Array instance and that the items match.
91
+ #
92
+ # If the constraint was configured with an item_type, each item in the Array
93
+ # will be compared to the expected type. If any items do not match the
94
+ # expectation, then #matches? will return false.
95
+ #
96
+ # @return [true, false] true if the object is an Array instance with
97
+ # matching items, otherwise false.
98
+ #
99
+ # @see Stannum::Constraints::Types::ArrayType#does_not_match?
100
+ def matches?(actual)
101
+ return false unless super
102
+
103
+ return false unless presence_matches?(actual)
104
+
105
+ return false unless item_type_matches?(actual)
106
+
107
+ true
108
+ end
109
+ alias match? matches?
110
+
111
+ private
112
+
113
+ def add_presence_error(errors)
114
+ errors.add(
115
+ Stannum::Constraints::Presence::TYPE,
116
+ **error_properties
117
+ )
118
+ end
119
+
120
+ def coerce_item_type(item_type)
121
+ Stannum::Support::Coercion.type_constraint(
122
+ item_type,
123
+ allow_nil: true,
124
+ as: 'item type'
125
+ )
126
+ end
127
+
128
+ def error_properties
129
+ super().merge(allow_empty: allow_empty?)
130
+ end
131
+
132
+ def item_type_matches?(actual)
133
+ return true unless item_type
134
+
135
+ return true if actual.nil?
136
+
137
+ actual.all? { |item| item_type.matches?(item) }
138
+ end
139
+
140
+ def non_matching_items(actual)
141
+ actual.each.with_index.reject { |item, _| item_type.matches?(item) }
142
+ end
143
+
144
+ def presence_matches?(actual)
145
+ allow_empty? || !actual.empty?
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bigdecimal'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A BigDecimal type constraint asserts that the object is a BigDecimal.
9
+ class BigDecimalType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::BigDecimal, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A DateTimeType constraint asserts that the object is a DateTime.
9
+ class DateTimeType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::DateTime, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ require 'stannum/constraints/types'
6
+
7
+ module Stannum::Constraints::Types
8
+ # A DateType constraint asserts that the object is a Date.
9
+ class DateType < Stannum::Constraints::Type
10
+ # @param options [Hash<Symbol, Object>] Configuration options for the
11
+ # constraint. Defaults to an empty Hash.
12
+ def initialize(**options)
13
+ super(::Date, **options)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A FloatType constraint asserts that the object is a Float.
7
+ class FloatType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Float, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+ require 'stannum/support/coercion'
5
+
6
+ module Stannum::Constraints::Types
7
+ # A Hash type constraint asserts that the object is a Hash.
8
+ #
9
+ # @example Using a Hash type constraint
10
+ # constraint = Stannum::Constraints::Types::HashType.new
11
+ #
12
+ # constraint.matches?(nil) # => false
13
+ # constraint.matches?(Object.new) # => false
14
+ # constraint.matches?({}) # => true
15
+ # constraint.matches?({ key: 'value' }) # => true
16
+ #
17
+ # @example Using a Hash type constraint with a key constraint
18
+ # constraint = Stannum::Constraints::Types::HashType.new(key_type: String)
19
+ #
20
+ # constraint.matches?(nil) # => false
21
+ # constraint.matches?(Object.new) # => false
22
+ # constraint.matches?({}) # => true
23
+ # constraint.matches?({ key: 'value' }) # => false
24
+ # constraint.matches?({ 'key' => 'value' }) # => true
25
+ #
26
+ # @example Using a Hash type constraint with a value constraint
27
+ # constraint = Stannum::Constraints::Types::HashType.new(value_type: String)
28
+ #
29
+ # constraint.matches?(nil) # => false
30
+ # constraint.matches?(Object.new) # => false
31
+ # constraint.matches?({}) # => true
32
+ # constraint.matches?({ key: :value }) # => false
33
+ # constraint.matches?({ key: 'value' }) # => true
34
+ #
35
+ # @example Using a Hash type constraint with a presence constraint
36
+ # constraint = Stannum::Constraints::Types::HashType.new(allow_empty: false)
37
+ #
38
+ # constraint.matches?(nil) # => false
39
+ # constraint.matches?(Object.new) # => false
40
+ # constraint.matches?({}) # => false
41
+ # constraint.matches?({ key: :value }) # => true
42
+ # constraint.matches?({ key: 'value' }) # => true
43
+ class HashType < Stannum::Constraints::Type
44
+ # @param allow_empty [true, false] If false, then the constraint will not
45
+ # match against a Hash with no keys.
46
+ # @param key_type [Stannum::Constraints::Base, Class, nil] If set, then the
47
+ # constraint will check the types of each key in the Hash against the
48
+ # expected type and will fail if any keys do not match.
49
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
50
+ # the constraint will check the types of each value in the Hash against
51
+ # the expected type and will fail if any values do not match.
52
+ # @param options [Hash<Symbol, Object>] Configuration options for the
53
+ # constraint. Defaults to an empty Hash.
54
+ def initialize(allow_empty: true, key_type: nil, value_type: nil, **options)
55
+ super(
56
+ ::Hash,
57
+ allow_empty: !!allow_empty,
58
+ key_type: coerce_key_type(key_type),
59
+ value_type: coerce_value_type(value_type),
60
+ **options
61
+ )
62
+ end
63
+
64
+ # @return [true, false] if false, then the constraint will not
65
+ # match against a Hash with no keys.
66
+ def allow_empty?
67
+ options[:allow_empty]
68
+ end
69
+
70
+ # Checks that the object is not a Hash instance.
71
+ #
72
+ # @return [true, false] true if the object is not a Hash instance, otherwise
73
+ # false.
74
+ #
75
+ # @see Stannum::Constraints::Types::HashType#matches?
76
+ def does_not_match?(actual)
77
+ !matches_type?(actual)
78
+ end
79
+
80
+ # (see Stannum::Constraints::Base#errors_for)
81
+ def errors_for(actual, errors: nil)
82
+ return super unless actual.is_a?(expected_type)
83
+
84
+ errors ||= Stannum::Errors.new
85
+
86
+ return add_presence_error(errors) unless presence_matches?(actual)
87
+
88
+ update_key_errors_for(actual: actual, errors: errors)
89
+
90
+ update_value_errors_for(actual: actual, errors: errors)
91
+
92
+ errors
93
+ end
94
+
95
+ # @return [Stannum::Constraints::Base, nil] the expected type for the keys
96
+ # in the hash.
97
+ def key_type
98
+ options[:key_type]
99
+ end
100
+
101
+ # Checks that the object is a Hash instance and that the keys/values match.
102
+ #
103
+ # If the constraint was configured with a key_type, each key in the hash
104
+ # will be compared to the expected type. Likewise, if the constraint was
105
+ # configured with a value_type, each value in the hash will be compared. If
106
+ # any keys and/or values do not match the expectation, then #matches? will
107
+ # return false.
108
+ #
109
+ # @return [true, false] true if the object is a Hash instance with matching
110
+ # keys and values, otherwise false.
111
+ #
112
+ # @see Stannum::Constraints::Types::HashType#does_not_match?
113
+ def matches?(actual)
114
+ return false unless super
115
+
116
+ return false unless presence_matches?(actual)
117
+
118
+ return false unless key_type_matches?(actual)
119
+
120
+ return false unless value_type_matches?(actual)
121
+
122
+ true
123
+ end
124
+ alias match? matches?
125
+
126
+ # @return [Stannum::Constraints::Base, nil] the expected type for the values
127
+ # in the hash.
128
+ def value_type
129
+ options[:value_type]
130
+ end
131
+
132
+ private
133
+
134
+ def add_presence_error(errors)
135
+ errors.add(
136
+ Stannum::Constraints::Presence::TYPE,
137
+ **error_properties
138
+ )
139
+ end
140
+
141
+ def coerce_key_type(key_type)
142
+ Stannum::Support::Coercion.type_constraint(
143
+ key_type,
144
+ allow_nil: true,
145
+ as: 'key type'
146
+ )
147
+ end
148
+
149
+ def coerce_value_type(value_type)
150
+ Stannum::Support::Coercion.type_constraint(
151
+ value_type,
152
+ allow_nil: true,
153
+ as: 'value type'
154
+ )
155
+ end
156
+
157
+ def error_properties
158
+ super().merge(allow_empty: allow_empty?)
159
+ end
160
+
161
+ def key_type_matches?(actual)
162
+ return true unless key_type
163
+
164
+ return true if actual.nil?
165
+
166
+ actual.each_key.all? { |key| key_type.matches?(key) }
167
+ end
168
+
169
+ def non_matching_keys(actual)
170
+ return [] unless key_type && actual.is_a?(Hash)
171
+
172
+ actual.each_key.reject { |key| key_type.matches?(key) }
173
+ end
174
+
175
+ def non_matching_values(actual)
176
+ return [] unless value_type && actual.is_a?(Hash)
177
+
178
+ actual.each.reject { |_, value| value_type.matches?(value) }
179
+ end
180
+
181
+ def presence_matches?(actual)
182
+ allow_empty? || !actual.empty?
183
+ end
184
+
185
+ def update_key_errors_for(actual:, errors:)
186
+ non_matching_keys(actual).each do |key|
187
+ key_type.errors_for(key, errors: errors[:keys][key])
188
+ end
189
+ end
190
+
191
+ def update_value_errors_for(actual:, errors:)
192
+ non_matching_values(actual).each do |key, value|
193
+ value_type.errors_for(value, errors: errors[key])
194
+ end
195
+ end
196
+
197
+ def value_type_matches?(actual)
198
+ return true unless value_type
199
+
200
+ return true if actual.nil?
201
+
202
+ actual.each_value.all? { |value| value_type.matches?(value) }
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with String or Symbol keys.
7
+ class HashWithIndifferentKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Hashes::IndifferentKey.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with String keys.
7
+ class HashWithStringKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Types::StringType.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # Asserts that the object is a Hash with Symbol keys.
7
+ class HashWithSymbolKeys < Stannum::Constraints::Types::HashType
8
+ # @param value_type [Stannum::Constraints::Base, Class, nil] If set, then
9
+ # the constraint will check the types of each value in the Hash against
10
+ # the expected type and will fail if any values do not match.
11
+ # @param options [Hash<Symbol, Object>] Configuration options for the
12
+ # constraint. Defaults to an empty Hash.
13
+ def initialize(value_type: nil, **options)
14
+ super(
15
+ key_type: Stannum::Constraints::Types::SymbolType.new,
16
+ value_type: coerce_value_type(value_type),
17
+ **options
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # An IntegerType constraint asserts that the object is an Integer.
7
+ class IntegerType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Integer, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Nil type constraint asserts that the object is nil.
7
+ class NilType < Stannum::Constraints::Type
8
+ # The :type of the error generated for a matching object.
9
+ NEGATED_TYPE = 'stannum.constraints.types.is_nil'
10
+
11
+ # The :type of the error generated for a non-matching object.
12
+ TYPE = 'stannum.constraints.types.is_not_nil'
13
+
14
+ # @param options [Hash<Symbol, Object>] Configuration options for the
15
+ # constraint. Defaults to an empty Hash.
16
+ def initialize(**options)
17
+ super(::NilClass, **options)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Proc type constraint asserts that the object is a Proc.
7
+ class ProcType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Proc, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A String type constraint asserts that the object is a String.
7
+ class StringType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::String, **options)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stannum/constraints/types'
4
+
5
+ module Stannum::Constraints::Types
6
+ # A Symbol type constraint asserts that the object is a Symbol.
7
+ class SymbolType < Stannum::Constraints::Type
8
+ # @param options [Hash<Symbol, Object>] Configuration options for the
9
+ # constraint. Defaults to an empty Hash.
10
+ def initialize(**options)
11
+ super(::Symbol, **options)
12
+ end
13
+ end
14
+ end