smart_types 0.1.0.alpha5 → 0.4.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 (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
data/Rakefile CHANGED
@@ -11,8 +11,8 @@ require 'rubocop-rake'
11
11
  RuboCop::RakeTask.new(:rubocop) do |t|
12
12
  config_path = File.expand_path(File.join('.rubocop.yml'), __dir__)
13
13
  t.options = ['--config', config_path]
14
- t.requires << 'rubocop-performance'
15
14
  t.requires << 'rubocop-rspec'
15
+ t.requires << 'rubocop-performance'
16
16
  t.requires << 'rubocop-rake'
17
17
  end
18
18
 
@@ -4,5 +4,5 @@
4
4
  require 'bundler/setup'
5
5
  require 'smart_core/types'
6
6
 
7
- require 'irb'
8
- IRB.start(__FILE__)
7
+ require 'pry'
8
+ Pry.start
@@ -10,4 +10,6 @@ module SmartCore::Types
10
10
  require_relative 'types/system'
11
11
  require_relative 'types/primitive'
12
12
  require_relative 'types/value'
13
+ require_relative 'types/protocol'
14
+ require_relative 'types/variadic'
13
15
  end
@@ -13,6 +13,18 @@ module SmartCore::Types
13
13
  # @since 0.1.0
14
14
  NameError = Class.new(SmartCore::NameError)
15
15
 
16
+ # @api public
17
+ # @since 0.3.0
18
+ TypeDefinitionError = Class.new(ArgumentError)
19
+
20
+ # @api public
21
+ # @since 0.3.0
22
+ IncorrectRuntimeAttributesError = Class.new(TypeDefinitionError)
23
+
24
+ # @api public
25
+ # @since 0.3.0
26
+ RuntimeAttriburtesUnsupportedError = Class.new(TypeDefinitionError)
27
+
16
28
  # @api public
17
29
  # @since 0.1.0
18
30
  TypeError = Class.new(SmartCore::TypeError)
@@ -21,6 +33,10 @@ module SmartCore::Types
21
33
  # @since 0.1.0
22
34
  TypeCastingError = Class.new(Error)
23
35
 
36
+ # @api public
37
+ # @since 0.1.0
38
+ TypeCastingUnsupportedError = Class.new(TypeCastingError)
39
+
24
40
  # @api public
25
41
  # @since 0.1.0
26
42
  NoCheckerDefinitionError = Class.new(Error)
@@ -2,26 +2,61 @@
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
- # @since 0.1.0
18
- include SmartCore::Types::System::ProducerDSL
21
+ class << self
22
+ # @param type_name [String, Symbol]
23
+ # @param type_definition [Block]
24
+ # @yield [type]
25
+ # @yieldparam type [SmartCore::Types::Primitive::DefinitionContext]
26
+ # @yieldreturn [void]
27
+ # @return [SmartCore::Types::Primitive]
28
+ #
29
+ # @api public
30
+ # @since 0.1.0
31
+ def define_type(type_name, &type_definition)
32
+ self::Factory.create_type(self, type_name, type_definition)
33
+ end
34
+ end
35
+
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
19
42
 
20
- # @return [SmartCore::Types::Primitive::Checker]
43
+ # @return [Class<SmartCore::Types::Primitive>]
21
44
  #
22
45
  # @api private
23
- # @since 0.1.0
24
- 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
25
60
 
26
61
  # @return [SmartCore::Types::Primitive::Caster]
27
62
  #
@@ -29,25 +64,53 @@ class SmartCore::Types::Primitive
29
64
  # @since 0.1.0
30
65
  attr_reader :caster
31
66
 
32
- # @return [String]
67
+ # @return [SmartCore::Types::Primitive::Validator]
68
+ # @return [SmartCore::Types::Primitive::SumValidator]
69
+ # @return [SmartCore::Types::Primitive::MultValidator]
70
+ # @return [SmartCore::Types::primitive::NilableValidator]
33
71
  #
34
72
  # @api private
35
- # @since 0.1.0
36
- attr_reader :name
73
+ # @since 0.2.0
74
+ attr_reader :validator
37
75
 
38
- # @param checker [SmartCore::Types::Primitive::Checker]
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
+ # ]
39
84
  # @param caster [SmartCore::Types::Primitive::Caster]
40
- # @param name [String]
85
+ # @param runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
86
+ # @param runtime_attributes [Array<Any>]
41
87
  # @return [void]
42
88
  #
43
89
  # @api private
44
90
  # @since 0.1.0
45
- def initialize(checker, caster, name)
46
- @lock = SmartCore::Engine::Lock.new
47
- @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
48
97
  @caster = caster
49
98
  @nilable = nil
50
- @name = name.freeze
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
51
114
  end
52
115
 
53
116
  # @param value [Any]
@@ -55,20 +118,38 @@ class SmartCore::Types::Primitive
55
118
  #
56
119
  # @api public
57
120
  # @since 0.1.0
121
+ # @since 0.2.0
58
122
  def valid?(value)
59
- checker.call(value)
123
+ validator.valid?(value)
60
124
  end
61
125
 
126
+ # @param value [Any]
62
127
  # @return [void]
63
128
  #
64
- # @raise [SmartCore::TypeError]
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
65
134
  #
66
135
  # @api public
67
136
  # @since 0.1.0
137
+ # @version 0.2.0
68
138
  def validate!(value)
69
- valid?(value) || raise(SmartCore::Types::TypeError, <<~ERROR_MESSAGE)
70
- Invalid type (given #{(class << value; superclass; end).name}, expects #{name}/SmartCore)
71
- ERROR_MESSAGE
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)
72
153
  end
73
154
 
74
155
  # @param value [Any]
@@ -76,8 +157,12 @@ class SmartCore::Types::Primitive
76
157
  #
77
158
  # @api public
78
159
  # @since 0.1.0
160
+ # @version 0.3.0
79
161
  def cast(value)
80
- 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)
81
166
  end
82
167
 
83
168
  # @return [SmartCore::Types::Primitive]
@@ -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::Caster
6
7
  # @param expression [Proc]
7
8
  # @return [void]
@@ -13,12 +14,14 @@ class SmartCore::Types::Primitive::Caster
13
14
  end
14
15
 
15
16
  # @param value [Any]
17
+ # @param runtime_attributes [Array<Any>]
16
18
  # @return [Any]
17
19
  #
18
20
  # @api private
19
21
  # @since 0.1.0
20
- def call(value)
21
- expression.call(value)
22
+ # @version 0.3.0
23
+ def call(value, runtime_attributes)
24
+ expression.call(value, runtime_attributes)
22
25
  end
23
26
 
24
27
  private
@@ -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::Checker
6
7
  # @param expression [Proc]
7
8
  # @return [void]
@@ -13,12 +14,14 @@ class SmartCore::Types::Primitive::Checker
13
14
  end
14
15
 
15
16
  # @param value [Any]
17
+ # @param runtime_attributes [Array<Any>]
16
18
  # @return [Boolean]
17
19
  #
18
20
  # @api private
19
21
  # @since 0.1.0
20
- def call(value)
21
- !!expression.call(value)
22
+ # @version 0.3.0
23
+ def call(value, runtime_attributes)
24
+ !!expression.call(value, runtime_attributes)
22
25
  end
23
26
 
24
27
  private
@@ -2,8 +2,10 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.1.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::Factory
6
7
  require_relative 'factory/definition_context'
8
+ require_relative 'factory/runtime_type_builder'
7
9
 
8
10
  class << self
9
11
  # @param type_category [Class<SmartCore::Types::Primitive>]
@@ -13,12 +15,26 @@ class SmartCore::Types::Primitive::Factory
13
15
  #
14
16
  # @api private
15
17
  # @since 0.1.0
18
+ # @version 0.3.0
16
19
  def create_type(type_category, type_name, type_definition)
17
20
  type_definitions = build_type_definitions(type_definition)
21
+ type_runtime_attributes_checker = build_type_runtime_attributes_checker(type_definitions)
18
22
  type_checker = build_type_checker(type_definitions)
19
23
  type_caster = build_type_caster(type_definitions)
20
- type = build_type(type_category, type_name, type_checker, type_caster)
21
- type.tap { register_new_type(type_category, type_name, type) }
24
+ type_invariant_control = build_type_invariant_control(type_definitions)
25
+ type_validator = build_type_validator(type_checker, type_invariant_control)
26
+ build_type(
27
+ type_category,
28
+ type_name,
29
+ type_validator,
30
+ type_caster,
31
+ type_runtime_attributes_checker
32
+ ).tap do |type|
33
+ assign_type_validator(type, type_validator)
34
+ assign_type_runtime_attributes_checker(type, type_runtime_attributes_checker)
35
+ register_new_type(type_category, type_name, type)
36
+ register_runtime_type_builder(type_category, type_name)
37
+ end
22
38
  end
23
39
 
24
40
  private
@@ -37,11 +53,34 @@ class SmartCore::Types::Primitive::Factory
37
53
  end.tap do |context|
38
54
  raise(
39
55
  SmartCore::Types::NoCheckerDefinitionError,
40
- 'Type checker is not provided (use .define_checker for it)'
41
- ) if context.type_checker.nil?
56
+ 'Type checker is not provided. You should define it via .define_checker(&block)'
57
+ ) if context.type_checker == nil
42
58
  end
43
59
  end
44
60
 
61
+ # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
62
+ # @return [SmartCore::Types::Primitive::RuntimeAttributesChecker]
63
+ #
64
+ # @api private
65
+ # @since 0.3.0
66
+ def build_type_runtime_attributes_checker(type_definitions)
67
+ SmartCore::Types::Primitive::RuntimeAttributesChecker.new(
68
+ type_definitions.type_runtime_attributes_checker
69
+ )
70
+ end
71
+
72
+ # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
73
+ # @return [SmartCore::Types::Primitive::InvariantControl]
74
+ #
75
+ # @api private
76
+ # @since 0.2.0
77
+ def build_type_invariant_control(type_definitions)
78
+ SmartCore::Types::Primitive::InvariantControl.create(
79
+ type_definitions.type_invariant_chains,
80
+ type_definitions.type_invariants
81
+ )
82
+ end
83
+
45
84
  # @param type_definitions [SmartCore::Types::Primitive::Factory::DefinitionContext]
46
85
  # @return [SmartCore::Types::Primitive::Checker]
47
86
  #
@@ -57,23 +96,67 @@ class SmartCore::Types::Primitive::Factory
57
96
  # @api private
58
97
  # @since 0.1.0
59
98
  def build_type_caster(type_definitions)
60
- if type_definitions.type_caster.nil?
99
+ if type_definitions.type_caster == nil
61
100
  SmartCore::Types::Primitive::UndefinedCaster.new
62
101
  else
63
102
  SmartCore::Types::Primitive::Caster.new(type_definitions.type_caster)
64
103
  end
65
104
  end
66
105
 
106
+ # @param checker [SmartCore::Types::Primitive::Checker]
107
+ # @param invariant_control [SmartCore::Types::Primitive::InvariantControl]
108
+ # @return [void]
109
+ #
110
+ # @api private
111
+ # @since 0.2.0
112
+ def build_type_validator(type_checker, type_invariant_control)
113
+ SmartCore::Types::Primitive::Validator.new(type_checker, type_invariant_control)
114
+ end
115
+
67
116
  # @param type_klass [Class<SmartCore::Types::Primitive>]
68
117
  # @param type_name [String, Symbol]
69
- # @param type_checker [SmartCore::Types::Primitive::Checker]
118
+ # @param type_validator [SmartCore::Types::Primitive::Validator]
70
119
  # @param type_caster [SmartCore::Types::Primitive::Caster]
120
+ # @param type_runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
71
121
  # @return [SmartCore::Types::Primitive]
72
122
  #
73
123
  # @api private
74
124
  # @since 0.1.0
75
- def build_type(type_category, type_name, type_checker, type_caster)
76
- Class.new(type_category).new(type_checker, type_caster, type_name.to_s)
125
+ # @version 0.3.0
126
+ def build_type(
127
+ type_category,
128
+ type_name,
129
+ type_validator,
130
+ type_caster,
131
+ type_runtime_attributes_checker
132
+ )
133
+ Class.new(type_category).new(
134
+ type_name,
135
+ type_category,
136
+ type_validator,
137
+ type_caster,
138
+ type_runtime_attributes_checker
139
+ )
140
+ end
141
+
142
+ # @param type [SmartCore::Types::Primitive]
143
+ # @param type_validator [SmartCore::Types::Primitive::Validator]
144
+ # @return [void]
145
+ #
146
+ # @api private
147
+ # @since 0.2.0
148
+ def assign_type_validator(type, type_validator)
149
+ type_validator.___assign_type___(type)
150
+ end
151
+
152
+ # @param type [SmartCore::Types::Primitive]
153
+ # @param type_runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
154
+ # @return [void]
155
+ #
156
+ # @api private
157
+ # @since 0.3.0
158
+ def assign_type_runtime_attributes_checker(type, type_runtime_attributes_checker)
159
+ type_runtime_attributes_checker.___assign_type___(type)
77
160
  end
78
161
 
79
162
  # @param type_category [Class<SmartCore::Types::Primitive>]
@@ -93,5 +176,19 @@ class SmartCore::Types::Primitive::Factory
93
176
  "Incorrect constant name for new type (#{type_name})"
94
177
  )
95
178
  end
179
+
180
+ # @param type_category [Class<SmartCore::Types::Primitive>]
181
+ # @param type_name [String, Symbol]
182
+ # @return [void]
183
+ #
184
+ # @raise [SmartCore::Types::IncorrectTypeNameError]
185
+ #
186
+ # @api private
187
+ # @since 0.3.0
188
+ def register_runtime_type_builder(type_category, type_name)
189
+ type_category.define_singleton_method(type_name) do |*runtime_attributes|
190
+ RuntimeTypeBuilder.build_with_runtime(type_name, type_category, runtime_attributes)
191
+ end
192
+ end
96
193
  end
97
194
  end