smart_types 0.1.0 → 0.6.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/CHANGELOG.md +57 -0
  4. data/Gemfile.lock +71 -58
  5. data/LICENSE.txt +1 -1
  6. data/README.md +363 -34
  7. data/Rakefile +0 -1
  8. data/bin/console +2 -2
  9. data/lib/smart_core/types/errors.rb +12 -0
  10. data/lib/smart_core/types/primitive/caster.rb +5 -2
  11. data/lib/smart_core/types/primitive/checker.rb +5 -2
  12. data/lib/smart_core/types/primitive/factory/definition_context.rb +140 -4
  13. data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
  14. data/lib/smart_core/types/primitive/factory.rb +104 -7
  15. data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
  16. data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
  17. data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
  18. data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
  19. data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
  20. data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
  21. data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
  22. data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
  23. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +26 -2
  24. data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
  25. data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
  26. data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
  27. data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
  28. data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
  29. data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
  30. data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
  31. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +25 -1
  32. data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
  33. data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
  34. data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
  35. data/lib/smart_core/types/primitive/undefined_caster.rb +4 -1
  36. data/lib/smart_core/types/primitive/validator/result.rb +78 -0
  37. data/lib/smart_core/types/primitive/validator.rb +93 -0
  38. data/lib/smart_core/types/primitive.rb +99 -15
  39. data/lib/smart_core/types/protocol/instance_of.rb +19 -0
  40. data/lib/smart_core/types/protocol.rb +7 -0
  41. data/lib/smart_core/types/value/array.rb +3 -0
  42. data/lib/smart_core/types/value/big_decimal.rb +4 -1
  43. data/lib/smart_core/types/value/boolean.rb +3 -0
  44. data/lib/smart_core/types/value/class.rb +3 -0
  45. data/lib/smart_core/types/value/date.rb +3 -0
  46. data/lib/smart_core/types/value/date_time.rb +3 -0
  47. data/lib/smart_core/types/value/enumerable.rb +1 -1
  48. data/lib/smart_core/types/value/enumerator.rb +13 -0
  49. data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
  50. data/lib/smart_core/types/value/float.rb +3 -0
  51. data/lib/smart_core/types/value/hash.rb +3 -0
  52. data/lib/smart_core/types/value/integer.rb +3 -0
  53. data/lib/smart_core/types/value/io.rb +13 -0
  54. data/lib/smart_core/types/value/method.rb +9 -0
  55. data/lib/smart_core/types/value/module.rb +3 -0
  56. data/lib/smart_core/types/value/nil.rb +0 -2
  57. data/lib/smart_core/types/value/numeric.rb +3 -0
  58. data/lib/smart_core/types/value/proc.rb +3 -0
  59. data/lib/smart_core/types/value/range.rb +9 -0
  60. data/lib/smart_core/types/value/rational.rb +13 -0
  61. data/lib/smart_core/types/value/set.rb +21 -0
  62. data/lib/smart_core/types/value/string.rb +3 -0
  63. data/lib/smart_core/types/value/string_io.rb +15 -0
  64. data/lib/smart_core/types/value/symbol.rb +3 -0
  65. data/lib/smart_core/types/value/text.rb +6 -4
  66. data/lib/smart_core/types/value/time.rb +3 -0
  67. data/lib/smart_core/types/value/time_based.rb +8 -5
  68. data/lib/smart_core/types/value/unbound_method.rb +9 -0
  69. data/lib/smart_core/types/value.rb +9 -0
  70. data/lib/smart_core/types/variadic/array_of.rb +23 -0
  71. data/lib/smart_core/types/variadic/enum.rb +11 -0
  72. data/lib/smart_core/types/variadic/tuple.rb +23 -0
  73. data/lib/smart_core/types/variadic.rb +10 -0
  74. data/lib/smart_core/types/version.rb +2 -1
  75. data/lib/smart_core/types.rb +2 -0
  76. data/smart_types.gemspec +5 -4
  77. metadata +61 -18
  78. data/.travis.yml +0 -21
  79. data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
  80. data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
  81. data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::UndefinedCaster < SmartCore::Types::Primitive::Caster
6
7
  # @param expression [NilClass, Any]
7
8
  # @return [void]
@@ -13,13 +14,15 @@ class SmartCore::Types::Primitive::UndefinedCaster < SmartCore::Types::Primitive
13
14
  end
14
15
 
15
16
  # @param value [Any]
17
+ # @param runtime_attributes [Array<Any>]
16
18
  # @return [void]
17
19
  #
18
20
  # @raise [SmartCore::Types::TypeCastingUnsupportedError]
19
21
  #
20
22
  # @pai private
21
23
  # @since 0.1.0
22
- def call(value)
24
+ # @version 0.3.0
25
+ def call(value, runtime_attributes)
23
26
  raise(SmartCore::Types::TypeCastingUnsupportedError, <<~ERROR_MESSAGE)
24
27
  'This type has no support for type casting'
25
28
  ERROR_MESSAGE
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.2.0
5
+ class SmartCore::Types::Primitive::Validator::Result
6
+ # @return [Array]
7
+ #
8
+ # @api private
9
+ # @since 0.2.0
10
+ NO_INVARIANT_ERRORS = [].freeze
11
+
12
+ # @return [SmartCore::Types::Primitive]
13
+ #
14
+ # @api public
15
+ # @since 0.2.0
16
+ attr_reader :type
17
+
18
+ # @return [Boolean]
19
+ #
20
+ # @api public
21
+ # @since 0.2.0
22
+ attr_reader :is_valid_check
23
+ alias_method :valid_check?, :is_valid_check
24
+
25
+ # @return [Any]
26
+ #
27
+ # @api public
28
+ # @since 0.2.0
29
+ attr_reader :checked_value
30
+ alias_method :value, :checked_value
31
+
32
+ # @return [Array<String>]
33
+ #
34
+ # @api public
35
+ # @since 0.2.0
36
+ attr_reader :invariant_errors
37
+ alias_method :errors, :invariant_errors
38
+ alias_method :error_codes, :invariant_errors
39
+
40
+ # @param type [SmartCore::Types::Primitive]
41
+ # @param checked_value [Any]
42
+ # @param is_valid_check [Boolean]
43
+ # @param invariant_errors [Array<String>]
44
+ # @return [void]
45
+ #
46
+ # @api private
47
+ # @since 0.2.0
48
+ def initialize(type, checked_value, is_valid_check, invariant_errors = NO_INVARIANT_ERRORS.dup)
49
+ @type = type
50
+ @checked_value = checked_value
51
+ @is_valid_check = is_valid_check
52
+ @invariant_errors = invariant_errors.tap(&:freeze)
53
+ end
54
+
55
+ # @return [Boolean]
56
+ #
57
+ # @api public
58
+ # @since 0.2.0
59
+ def valid_invariants?
60
+ invariant_errors.empty?
61
+ end
62
+
63
+ # @return [Boolean]
64
+ #
65
+ # @api public
66
+ # @since 0.2.0
67
+ def success?
68
+ valid_check? && invariant_errors.empty?
69
+ end
70
+
71
+ # @return [Boolean]
72
+ #
73
+ # @api public
74
+ # @since 0.2.0
75
+ def failure?
76
+ !success?
77
+ end
78
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.2.0
5
+ # @version 0.3.0
6
+ class SmartCore::Types::Primitive::Validator
7
+ require_relative 'validator/result'
8
+
9
+ # @return [SmartCore::Type::Primitive]
10
+ #
11
+ # @api private
12
+ # @since 0.2.0
13
+ attr_reader :type
14
+
15
+ # @return [SmartCore::Types::Primitive::Checker]
16
+ #
17
+ # @api private
18
+ # @since 0.2.0
19
+ attr_reader :type_checker
20
+
21
+ # @return [SmartCore::Types::Primitive::InvariantControl]
22
+ #
23
+ # @api private
24
+ # @since 0.2.0
25
+ attr_reader :invariant_control
26
+
27
+ # @param type_checker [SmartCore::Types::Primitive::Checker]
28
+ # @param invariant_control [SmartCore::Types::Primitive::InvariantControl]
29
+ # @return [void]
30
+ #
31
+ # @api private
32
+ # @since 0.2.0
33
+ def initialize(type_checker, invariant_control)
34
+ @type = nil
35
+ @type_checker = type_checker
36
+ @invariant_control = invariant_control
37
+ end
38
+
39
+ # @param type [SmartCore::Types::Primitive]
40
+ # @return [SmartCore::Types::Primitive::Validator]
41
+ #
42
+ # @api private
43
+ # @since 0.3.0
44
+ def ___copy_for___(type)
45
+ self.class.new(type_checker, invariant_control).tap do |instance_copy|
46
+ instance_copy.___assign_type___(type)
47
+ end
48
+ end
49
+
50
+ # @param type [SmartCore::Types::Primitive]
51
+ # @return [void]
52
+ #
53
+ # @api private
54
+ # @since 0.2.0
55
+ def ___assign_type___(type)
56
+ @type = type
57
+ end
58
+
59
+ # @param value [Any]
60
+ # @return [Boolean]
61
+ #
62
+ # @api private
63
+ # @since 0.2.0
64
+ def valid?(value)
65
+ validate(value).success?
66
+ end
67
+
68
+ # @param value [Any]
69
+ # @return [SmartCore::Types::Primitive::Validator::Result]
70
+ #
71
+ # @api private
72
+ # @since 0.2.0
73
+ # @version 0.3.0
74
+ def validate(value)
75
+ checker_result = type_checker.call(value, type.runtime_attributes) # => Boolean
76
+ return Result.new(type, value, checker_result) unless checker_result
77
+ invariant_result = invariant_control.check(value, type.runtime_attributes)
78
+ invariant_errors = invariant_result.invariant_errors.map { |error| "#{type.name}.#{error}" }
79
+ Result.new(type, value, checker_result, invariant_errors)
80
+ end
81
+
82
+ # @param value [Any]
83
+ # @return [void]
84
+ #
85
+ # @raise [SmartCore::Types::TypeError]
86
+ #
87
+ # @api private
88
+ # @since 0.2.0
89
+ def validate!(value)
90
+ return if validate(value).success?
91
+ raise(SmartCore::Types::TypeError, 'Invalid type')
92
+ end
93
+ end
@@ -2,21 +2,28 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive
7
+ require_relative 'primitive/checker'
6
8
  require_relative 'primitive/caster'
9
+ require_relative 'primitive/runtime_attributes_checker'
7
10
  require_relative 'primitive/undefined_caster'
8
- require_relative 'primitive/checker'
9
- require_relative 'primitive/nilable_checker'
10
- require_relative 'primitive/sum_checker'
11
- require_relative 'primitive/mult_checker'
11
+ require_relative 'primitive/invariant_control'
12
+ require_relative 'primitive/validator'
12
13
  require_relative 'primitive/factory'
14
+ require_relative 'primitive/sum_validator'
13
15
  require_relative 'primitive/sum_factory'
16
+ require_relative 'primitive/mult_validator'
14
17
  require_relative 'primitive/mult_factory'
18
+ require_relative 'primitive/nilable_validator'
15
19
  require_relative 'primitive/nilable_factory'
16
20
 
17
21
  class << self
18
22
  # @param type_name [String, Symbol]
19
23
  # @param type_definition [Block]
24
+ # @yield [type]
25
+ # @yieldparam type [SmartCore::Types::Primitive::DefinitionContext]
26
+ # @yieldreturn [void]
20
27
  # @return [SmartCore::Types::Primitive]
21
28
  #
22
29
  # @api public
@@ -26,11 +33,30 @@ class SmartCore::Types::Primitive
26
33
  end
27
34
  end
28
35
 
29
- # @return [SmartCore::Types::Primitive::Checker]
36
+ # @note NilClass is suitable for sum-types, mult-types and nilable types.
37
+ # @return [String, NilClass]
38
+ #
39
+ # @api public
40
+ # @since 0.2.0
41
+ attr_reader :name
42
+
43
+ # @return [Class<SmartCore::Types::Primitive>]
30
44
  #
31
45
  # @api private
32
- # @since 0.1.0
33
- attr_reader :checker
46
+ # @since 0.3.0
47
+ attr_reader :category
48
+
49
+ # @return [Array<Any>]
50
+ #
51
+ # @api private
52
+ # @since 0.3.0
53
+ attr_reader :runtime_attributes
54
+
55
+ # @return [SmartCore::Types::Primitive::RuntimeAttributesChecker]
56
+ #
57
+ # @api private
58
+ # @since 0.3.0
59
+ attr_reader :runtime_attributes_checker
34
60
 
35
61
  # @return [SmartCore::Types::Primitive::Caster]
36
62
  #
@@ -38,17 +64,53 @@ class SmartCore::Types::Primitive
38
64
  # @since 0.1.0
39
65
  attr_reader :caster
40
66
 
41
- # @param checker [SmartCore::Types::Primitive::Checker]
67
+ # @return [SmartCore::Types::Primitive::Validator]
68
+ # @return [SmartCore::Types::Primitive::SumValidator]
69
+ # @return [SmartCore::Types::Primitive::MultValidator]
70
+ # @return [SmartCore::Types::primitive::NilableValidator]
71
+ #
72
+ # @api private
73
+ # @since 0.2.0
74
+ attr_reader :validator
75
+
76
+ # @param name [String, NilClass] NilClass is suitable for sum-types, mult-types and nilable types.
77
+ # @param category [Class<SmartCore::Types::Primitive>, NilClass]
78
+ # @param validator [
79
+ # SmartCore::Types::Primitive::Validator,
80
+ # SmartCore::Types::Primitive::SumValidator,
81
+ # SmartCore::Types::Primitive::MultValidator,
82
+ # SmartCore::Types::Primitive::NilableValidator
83
+ # ]
42
84
  # @param caster [SmartCore::Types::Primitive::Caster]
85
+ # @param runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
86
+ # @param runtime_attributes [Array<Any>]
43
87
  # @return [void]
44
88
  #
45
89
  # @api private
46
90
  # @since 0.1.0
47
- def initialize(checker, caster)
48
- @lock = SmartCore::Engine::Lock.new
49
- @checker = checker
91
+ # @version 0.3.0
92
+ # rubocop:disable Metrics/ParameterLists
93
+ def initialize(name, category, validator, caster, runtime_attributes_checker, *runtime_attributes)
94
+ @name = name
95
+ @category = category
96
+ @validator = validator
50
97
  @caster = caster
51
98
  @nilable = nil
99
+ @runtime_attributes_checker = runtime_attributes_checker
100
+ @runtime_attributes = runtime_attributes
101
+ @lock = SmartCore::Engine::Lock.new
102
+ end
103
+ # rubocop:enable Metrics/ParameterLists
104
+
105
+ # @param cloneable_instance [SmartCore::Types::Primitive]
106
+ # @return [SmartCore::Types::Primitive]
107
+ #
108
+ # @api private
109
+ # @since 0.3.0
110
+ def initialize_copy(cloneable_instance)
111
+ lock.synchronize do
112
+ self.class::Factory::RuntimeTypeBuilder.initialize_clone(self, cloneable_instance)
113
+ end
52
114
  end
53
115
 
54
116
  # @param value [Any]
@@ -56,20 +118,38 @@ class SmartCore::Types::Primitive
56
118
  #
57
119
  # @api public
58
120
  # @since 0.1.0
121
+ # @since 0.2.0
59
122
  def valid?(value)
60
- checker.call(value)
123
+ validator.valid?(value)
61
124
  end
62
125
 
63
126
  # @param value [Any]
64
127
  # @return [void]
65
128
  #
66
129
  # @raise [SmartCore::Types::TypeError]
130
+ # @see SmartCore::Primitive::Validator
131
+ # @see SmartCore::Primitive::MultValidator
132
+ # @see SmartCore::Primitive::SumValidator
133
+ # @see SmartCore::Primitive::NilableValidator
67
134
  #
68
135
  # @api public
69
136
  # @since 0.1.0
137
+ # @version 0.2.0
70
138
  def validate!(value)
71
- return if valid?(value)
72
- raise(SmartCore::Types::TypeError, 'Invalid type')
139
+ validator.validate!(value)
140
+ end
141
+
142
+ # @return [SmartCore::Types::Primitive::Validator::Result]
143
+ #
144
+ # @see SmartCore::Primitive::Validator
145
+ # @see SmartCore::Primitive::MultValidator
146
+ # @see SmartCore::Primitive::SumValidator
147
+ # @see SmartCore::Primitive::NilableValidator
148
+ #
149
+ # @api public
150
+ # @since 0.2.0
151
+ def validate(value)
152
+ validator.validate(value)
73
153
  end
74
154
 
75
155
  # @param value [Any]
@@ -77,8 +157,12 @@ class SmartCore::Types::Primitive
77
157
  #
78
158
  # @api public
79
159
  # @since 0.1.0
160
+ # @version 0.3.0
80
161
  def cast(value)
81
- caster.call(value)
162
+ # TODO (0.x.0):
163
+ # refactor with ValueTransformer with internal reference to the type object
164
+ # in Validator manner (in order to avoid explicit #runtime_attributes passing)
165
+ caster.call(value, runtime_attributes)
82
166
  end
83
167
 
84
168
  # @return [SmartCore::Types::Primitive]
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ using SmartCore::Ext::BasicObjectAsObject
4
+
5
+ # @api public
6
+ # @since 0.3.0
7
+ SmartCore::Types::Protocol.define_type(:InstanceOf) do |type|
8
+ type.runtime_attributes_checker do |runtime_attrs|
9
+ runtime_attrs.any? && runtime_attrs.all? do |runtime_attr|
10
+ runtime_attr.is_a?(::Class)
11
+ end
12
+ end
13
+
14
+ type.define_checker do |value, expected_types|
15
+ expected_types.any? && expected_types.any? do |expected_type|
16
+ value.is_a?(expected_type)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api public
4
+ # @since 0.3.0
5
+ class SmartCore::Types::Protocol < SmartCore::Types::Primitive
6
+ require_relative 'protocol/instance_of'
7
+ end
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using SmartCore::Ext::BasicObjectAsObject
4
+
3
5
  # @api public
4
6
  # @since 0.1.0
7
+ # @version 0.3.0
5
8
  SmartCore::Types::Value.define_type(:Array) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Array)
@@ -3,15 +3,18 @@
3
3
  require 'bigdecimal'
4
4
  require 'bigdecimal/util'
5
5
 
6
+ using SmartCore::Ext::BasicObjectAsObject
7
+
6
8
  # @api public
7
9
  # @since 0.1.0
10
+ # @version 0.3.0
8
11
  SmartCore::Types::Value.define_type(:BigDecimal) do |type|
9
12
  type.define_checker do |value|
10
13
  value.is_a?(::BigDecimal)
11
14
  end
12
15
 
13
16
  type.define_caster do |value|
14
- if SmartCore::Types::Value::Float.valid?(value)
17
+ if SmartCore::Types::Value::Numeric.valid?(value)
15
18
  value = SmartCore::Types::Value::String.cast(value)
16
19
  end
17
20
 
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ using SmartCore::Ext::BasicObjectAsObject
4
+
3
5
  # @api public
4
6
  # @since 0.1.0
7
+ # @version 0.3.0
5
8
  SmartCore::Types::Value.define_type(:Boolean) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::TrueClass) || value.is_a?(::FalseClass)