smart_types 0.1.0.alpha5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -1
  3. data/CHANGELOG.md +46 -0
  4. data/Gemfile.lock +80 -52
  5. data/README.md +437 -27
  6. data/Rakefile +1 -1
  7. data/bin/console +2 -2
  8. data/lib/smart_core/types.rb +2 -0
  9. data/lib/smart_core/types/errors.rb +16 -0
  10. data/lib/smart_core/types/primitive.rb +109 -24
  11. data/lib/smart_core/types/primitive/caster.rb +5 -2
  12. data/lib/smart_core/types/primitive/checker.rb +5 -2
  13. data/lib/smart_core/types/primitive/factory.rb +105 -8
  14. data/lib/smart_core/types/primitive/factory/definition_context.rb +142 -6
  15. data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
  16. data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
  17. data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
  18. data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
  19. data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
  20. data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
  21. data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
  22. data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
  23. data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
  24. data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
  25. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +27 -3
  26. data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
  27. data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
  28. data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
  29. data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
  30. data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
  31. data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
  32. data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
  33. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +26 -2
  34. data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
  35. data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
  36. data/lib/smart_core/types/primitive/undefined_caster.rb +7 -5
  37. data/lib/smart_core/types/primitive/validator.rb +93 -0
  38. data/lib/smart_core/types/primitive/validator/result.rb +78 -0
  39. data/lib/smart_core/types/protocol.rb +7 -0
  40. data/lib/smart_core/types/protocol/instance_of.rb +19 -0
  41. data/lib/smart_core/types/system.rb +21 -5
  42. data/lib/smart_core/types/value.rb +16 -0
  43. data/lib/smart_core/types/value/array.rb +3 -0
  44. data/lib/smart_core/types/value/big_decimal.rb +31 -0
  45. data/lib/smart_core/types/value/boolean.rb +3 -0
  46. data/lib/smart_core/types/value/class.rb +3 -0
  47. data/lib/smart_core/types/value/comparable.rb +13 -0
  48. data/lib/smart_core/types/value/date.rb +24 -0
  49. data/lib/smart_core/types/value/date_time.rb +24 -0
  50. data/lib/smart_core/types/value/enumerable.rb +13 -0
  51. data/lib/smart_core/types/value/enumerator.rb +13 -0
  52. data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
  53. data/lib/smart_core/types/value/float.rb +9 -2
  54. data/lib/smart_core/types/value/hash.rb +11 -1
  55. data/lib/smart_core/types/value/integer.rb +13 -3
  56. data/lib/smart_core/types/value/io.rb +13 -0
  57. data/lib/smart_core/types/value/method.rb +9 -0
  58. data/lib/smart_core/types/value/module.rb +3 -0
  59. data/lib/smart_core/types/value/nil.rb +3 -3
  60. data/lib/smart_core/types/value/numeric.rb +16 -3
  61. data/lib/smart_core/types/value/proc.rb +14 -1
  62. data/lib/smart_core/types/value/range.rb +9 -0
  63. data/lib/smart_core/types/value/rational.rb +13 -0
  64. data/lib/smart_core/types/value/set.rb +21 -0
  65. data/lib/smart_core/types/value/string.rb +10 -1
  66. data/lib/smart_core/types/value/string_io.rb +15 -0
  67. data/lib/smart_core/types/value/symbol.rb +10 -1
  68. data/lib/smart_core/types/value/text.rb +21 -4
  69. data/lib/smart_core/types/value/time.rb +24 -0
  70. data/lib/smart_core/types/value/time_based.rb +32 -0
  71. data/lib/smart_core/types/value/unbound_method.rb +9 -0
  72. data/lib/smart_core/types/variadic.rb +7 -0
  73. data/lib/smart_core/types/variadic/tuple.rb +23 -0
  74. data/lib/smart_core/types/version.rb +2 -2
  75. data/smart_types.gemspec +6 -5
  76. metadata +69 -23
  77. data/.travis.yml +0 -20
  78. data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
  79. data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
  80. data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
  81. data/lib/smart_core/types/system/definition_dsl.rb +0 -40
  82. data/lib/smart_core/types/system/producer_dsl.rb +0 -30
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.2.0
5
+ # @version 0.3.0
6
+ class SmartCore::Types::Primitive::SumValidator
7
+ require_relative 'sum_validator/result'
8
+
9
+ # @param validators [Array<SmartCore::Types::Primitive::Validator>]
10
+ # @return [void]
11
+ #
12
+ # @api private
13
+ # @since 0.2.0
14
+ def initialize(*validators)
15
+ @type = nil
16
+ @validators = validators
17
+ end
18
+
19
+ # @param type [SmartCore::Types::Primitive]
20
+ # @return [SmartCore::Types::Primitive::SumValidator]
21
+ #
22
+ # @api private
23
+ # @since 0.3.0
24
+ def ___copy_for___(type)
25
+ self.class.new(type_checker, invariant_control).tap do |instance_copy|
26
+ instance_copy.___assign_type___(type)
27
+ end
28
+ end
29
+
30
+ # @param type [SmartCore::Types::Primitive]
31
+ # @return [void]
32
+ #
33
+ # @api private
34
+ # @since 0.2.0
35
+ def ___assign_type___(type)
36
+ @type = type
37
+ end
38
+
39
+ # @return [Boolean]
40
+ #
41
+ # @api private
42
+ # @since 0.2.0
43
+ # @version 0.3.0
44
+ def valid?(value)
45
+ # NOTE: at this moment type sum does not support invariant checking
46
+ # TODO (0.x.0):
47
+ # validators.any? { |validator| validator.valid?(value) }
48
+ validators.any? do |validator|
49
+ validator.type_checker.call(value, type.runtime_attributes)
50
+ end
51
+ end
52
+
53
+ # @param value [Any]
54
+ # @return [SmartCore::Types::Primitive::SumValidator::Result]
55
+ #
56
+ # @api private
57
+ # @since 0.2.0
58
+ # @version 0.3.0
59
+ def validate(value)
60
+ compile_validation_result do
61
+ SmartCore::Engine::Atom.new.tap do |result|
62
+ validators.each do |validator|
63
+ # NOTE: at this moment type sum does not support invariant checking
64
+ # TODO (0.x.0):
65
+ # result.swap { validator.validate(value) }
66
+ # break if result.value.success?
67
+ result.swap { validator.type_checker.call(value, type.runtime_attributes) }
68
+ break if result.value # => boolean
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ # @param value [Any]
75
+ # @return [void]
76
+ #
77
+ # @raise [SmartCore::Types::TypeError]
78
+ #
79
+ # @api private
80
+ # @since 0.2.0
81
+ def validate!(value)
82
+ return if valid?(value)
83
+ raise(SmartCore::Types::TypeError, 'Invalid type')
84
+ end
85
+
86
+ private
87
+
88
+ # @return [SmartCore::Types::Primitive]
89
+ #
90
+ # @api private
91
+ # @since 0.2.0
92
+ attr_reader :type
93
+
94
+ # @return [Array<SmartCore::Types::Primitive::Validator>]
95
+ #
96
+ # @api private
97
+ # @since 0.2.0
98
+ attr_reader :validators
99
+
100
+ # @param validation [Block]
101
+ # @yieldparam [void]
102
+ # @yieldreturn [SmartCore::Engine::Atom]
103
+ # @return [SmartCore::Types::Primitive::SumValidator::Result]
104
+ #
105
+ # @api private
106
+ # @since 0.2.0
107
+ def compile_validation_result(&validation)
108
+ # NOTE: at this moment type sum does not support invariant checking
109
+ # TODO (0.x.0):
110
+ # @yieldreturn [SmartCore::Types::Primitive::Validator::Result]
111
+ # => and:
112
+ # SmartCore::Types::Primitive::SumValidator::Result.new(
113
+ # type, final_result.value, final_result.value.invariant_errors
114
+ # )
115
+ SmartCore::Types::Primitive::SumValidator::Result.new(type, yield.value)
116
+ end
117
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.2.0
5
+ class SmartCore::Types::Primitive::SumValidator::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 concrete_validation_result [
19
+ # SmartCore::Types::Primitive::Validator::Result,
20
+ # SmartCore::Types::Primitive::SumValidator::Result,
21
+ # SmartCore::Types::Primitive::MultValidator::Result,
22
+ # SmartCore::Types::Primitive::NilableValidator::Result
23
+ # ]
24
+ #
25
+ # @api private
26
+ # @since 0.2.0
27
+ attr_reader :concrete_validation_result
28
+
29
+ # @return [Array<String>]
30
+ #
31
+ # @api public
32
+ # @since 0.2.0
33
+ attr_reader :invariant_errors
34
+ alias_method :errors, :invariant_errors
35
+ alias_method :error_codes, :invariant_errors
36
+
37
+ # @param type [SmartCore::Types::Primitive]
38
+ # @param concrete_validation_result [
39
+ # Boolean, (TEMPORARY)
40
+ # SmartCore::Types::Primitive::Validator::Result,
41
+ # SmartCore::Types::Primitive::SumValidator::Result,
42
+ # SmartCore::Types::Primitive::MultValidator::Result,
43
+ # SmartCore::Types::Primitive::NilableValidator::Result
44
+ # ]
45
+ # @param invariant_errors [Array<String>]
46
+ # @return [void]
47
+ #
48
+ # @api private
49
+ # @since 0.2.0
50
+ def initialize(type, concrete_validation_result, invariant_errors = NO_INVARIANT_ERRORS.dup)
51
+ @type = type
52
+ @concrete_validation_result = concrete_validation_result
53
+ @invariant_errors = invariant_errors.dup.tap(&:freeze)
54
+ end
55
+
56
+ # @return [Boolean]
57
+ #
58
+ # @api public
59
+ # @since 0.2.0
60
+ def valid_invariants?
61
+ # NOTE: at this moment type sum does not support invariant checking
62
+ # TODO (0.x.0):
63
+ # concrete_validation_result.valid_invariants?
64
+ true
65
+ end
66
+
67
+ # @return [Boolean]
68
+ #
69
+ # @api public
70
+ # @since 0.2.0
71
+ def is_valid_check
72
+ # NOTE: at this moment type sum does not support invariant checking
73
+ # TODO (0.x.0):
74
+ # concrete_validation_result.is_valid_check
75
+ concrete_validation_result
76
+ end
77
+ alias_method :valid_check?, :is_valid_check
78
+
79
+ # @return [Boolean]
80
+ #
81
+ # @api public
82
+ # @since 0.2.0
83
+ def success?
84
+ # NOTE: at this moment type sum does not support invariant checking
85
+ # TODO (0.x.0):
86
+ # concrete_validation_result.success?
87
+ concrete_validation_result
88
+ end
89
+
90
+ # @return [Boolean]
91
+ #
92
+ # @api public
93
+ # @since 0.2.0
94
+ def failure?
95
+ # NOTE: at this moment type sum does not support invariant checking
96
+ # TODO (0.x.0):
97
+ # concrete_validation_result.failure?
98
+ !success?
99
+ end
100
+ end
@@ -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,16 +14,17 @@ 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
- # @raise [SmartCore::Types::TypeCastingError]
20
+ # @raise [SmartCore::Types::TypeCastingUnsupportedError]
19
21
  #
20
22
  # @pai private
21
23
  # @since 0.1.0
22
- def call(value)
23
- raise(
24
- SmartCore::Types::TypeCastingError,
24
+ # @version 0.3.0
25
+ def call(value, runtime_attributes)
26
+ raise(SmartCore::Types::TypeCastingUnsupportedError, <<~ERROR_MESSAGE)
25
27
  'This type has no support for type casting'
26
- )
28
+ ERROR_MESSAGE
27
29
  end
28
30
  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
@@ -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,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
@@ -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