smart_types 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/Gemfile.lock +33 -32
  4. data/README.md +161 -16
  5. data/lib/smart_core/types.rb +2 -0
  6. data/lib/smart_core/types/errors.rb +12 -0
  7. data/lib/smart_core/types/primitive.rb +49 -4
  8. data/lib/smart_core/types/primitive/caster.rb +5 -2
  9. data/lib/smart_core/types/primitive/checker.rb +5 -2
  10. data/lib/smart_core/types/primitive/factory.rb +64 -6
  11. data/lib/smart_core/types/primitive/factory/definition_context.rb +37 -11
  12. data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
  13. data/lib/smart_core/types/primitive/invariant_control.rb +6 -3
  14. data/lib/smart_core/types/primitive/invariant_control/chain.rb +5 -2
  15. data/lib/smart_core/types/primitive/invariant_control/single.rb +5 -2
  16. data/lib/smart_core/types/primitive/mult_factory.rb +40 -6
  17. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +23 -1
  18. data/lib/smart_core/types/primitive/mult_validator.rb +8 -0
  19. data/lib/smart_core/types/primitive/nilable_factory.rb +10 -3
  20. data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
  21. data/lib/smart_core/types/primitive/sum_factory.rb +40 -6
  22. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +23 -1
  23. data/lib/smart_core/types/primitive/sum_validator.rb +18 -2
  24. data/lib/smart_core/types/primitive/undefined_caster.rb +4 -1
  25. data/lib/smart_core/types/primitive/validator.rb +16 -7
  26. data/lib/smart_core/types/protocol.rb +7 -0
  27. data/lib/smart_core/types/protocol/instance_of.rb +19 -0
  28. data/lib/smart_core/types/value/array.rb +3 -0
  29. data/lib/smart_core/types/value/big_decimal.rb +4 -1
  30. data/lib/smart_core/types/value/boolean.rb +3 -0
  31. data/lib/smart_core/types/value/class.rb +3 -0
  32. data/lib/smart_core/types/value/date.rb +3 -0
  33. data/lib/smart_core/types/value/date_time.rb +3 -0
  34. data/lib/smart_core/types/value/enumerable.rb +1 -1
  35. data/lib/smart_core/types/value/float.rb +3 -0
  36. data/lib/smart_core/types/value/hash.rb +3 -0
  37. data/lib/smart_core/types/value/integer.rb +3 -0
  38. data/lib/smart_core/types/value/module.rb +3 -0
  39. data/lib/smart_core/types/value/numeric.rb +3 -0
  40. data/lib/smart_core/types/value/proc.rb +3 -0
  41. data/lib/smart_core/types/value/set.rb +11 -3
  42. data/lib/smart_core/types/value/string.rb +3 -0
  43. data/lib/smart_core/types/value/string_io.rb +2 -0
  44. data/lib/smart_core/types/value/symbol.rb +3 -0
  45. data/lib/smart_core/types/value/text.rb +6 -4
  46. data/lib/smart_core/types/value/time.rb +3 -0
  47. data/lib/smart_core/types/value/time_based.rb +8 -5
  48. data/lib/smart_core/types/variadic.rb +7 -0
  49. data/lib/smart_core/types/variadic/tuple.rb +23 -0
  50. data/lib/smart_core/types/version.rb +2 -2
  51. data/smart_types.gemspec +3 -3
  52. metadata +15 -10
  53. data/.travis.yml +0 -21
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.2.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::SumValidator
6
7
  require_relative 'sum_validator/result'
7
8
 
@@ -15,6 +16,17 @@ class SmartCore::Types::Primitive::SumValidator
15
16
  @validators = validators
16
17
  end
17
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
+
18
30
  # @param type [SmartCore::Types::Primitive]
19
31
  # @return [void]
20
32
  #
@@ -28,11 +40,14 @@ class SmartCore::Types::Primitive::SumValidator
28
40
  #
29
41
  # @api private
30
42
  # @since 0.2.0
43
+ # @version 0.3.0
31
44
  def valid?(value)
32
45
  # NOTE: at this moment type sum does not support invariant checking
33
46
  # TODO (0.x.0):
34
47
  # validators.any? { |validator| validator.valid?(value) }
35
- validators.any? { |validator| validator.type_checker.call(value) }
48
+ validators.any? do |validator|
49
+ validator.type_checker.call(value, type.runtime_attributes)
50
+ end
36
51
  end
37
52
 
38
53
  # @param value [Any]
@@ -40,6 +55,7 @@ class SmartCore::Types::Primitive::SumValidator
40
55
  #
41
56
  # @api private
42
57
  # @since 0.2.0
58
+ # @version 0.3.0
43
59
  def validate(value)
44
60
  compile_validation_result do
45
61
  SmartCore::Engine::Atom.new.tap do |result|
@@ -48,7 +64,7 @@ class SmartCore::Types::Primitive::SumValidator
48
64
  # TODO (0.x.0):
49
65
  # result.swap { validator.validate(value) }
50
66
  # break if result.value.success?
51
- result.swap { validator.type_checker.call(value) }
67
+ result.swap { validator.type_checker.call(value, type.runtime_attributes) }
52
68
  break if result.value # => boolean
53
69
  end
54
70
  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,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
@@ -2,6 +2,7 @@
2
2
 
3
3
  # @api private
4
4
  # @since 0.2.0
5
+ # @version 0.3.0
5
6
  class SmartCore::Types::Primitive::Validator
6
7
  require_relative 'validator/result'
7
8
 
@@ -23,11 +24,7 @@ class SmartCore::Types::Primitive::Validator
23
24
  # @since 0.2.0
24
25
  attr_reader :invariant_control
25
26
 
26
- # @param type_checker [
27
- # SmartCore::Types::Primitive::Checker,
28
- # SmartCore::Types::Primitive::MultChecker,
29
- # SmartCore::Types::Primitive::SumChecker
30
- # ]
27
+ # @param type_checker [SmartCore::Types::Primitive::Checker]
31
28
  # @param invariant_control [SmartCore::Types::Primitive::InvariantControl]
32
29
  # @return [void]
33
30
  #
@@ -39,6 +36,17 @@ class SmartCore::Types::Primitive::Validator
39
36
  @invariant_control = invariant_control
40
37
  end
41
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
+
42
50
  # @param type [SmartCore::Types::Primitive]
43
51
  # @return [void]
44
52
  #
@@ -62,10 +70,11 @@ class SmartCore::Types::Primitive::Validator
62
70
  #
63
71
  # @api private
64
72
  # @since 0.2.0
73
+ # @version 0.3.0
65
74
  def validate(value)
66
- checker_result = type_checker.call(value) # => Boolean
75
+ checker_result = type_checker.call(value, type.runtime_attributes) # => Boolean
67
76
  return Result.new(type, value, checker_result) unless checker_result
68
- invariant_result = invariant_control.check(value)
77
+ invariant_result = invariant_control.check(value, type.runtime_attributes)
69
78
  invariant_errors = invariant_result.invariant_errors.map { |error| "#{type.name}.#{error}" }
70
79
  Result.new(type, value, checker_result, invariant_errors)
71
80
  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
@@ -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)
@@ -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(:Class) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Class)
@@ -2,8 +2,11 @@
2
2
 
3
3
  require 'date'
4
4
 
5
+ using SmartCore::Ext::BasicObjectAsObject
6
+
5
7
  # @api public
6
8
  # @since 0.1.0
9
+ # @version 0.3.0
7
10
  SmartCore::Types::Value.define_type(:Date) do |type|
8
11
  type.define_checker do |value|
9
12
  value.is_a?(::Date) || value == ::Date::Infinity
@@ -2,8 +2,11 @@
2
2
 
3
3
  require 'date'
4
4
 
5
+ using SmartCore::Ext::BasicObjectAsObject
6
+
5
7
  # @api public
6
8
  # @since 0.1.0
9
+ # @version 0.3.0
7
10
  SmartCore::Types::Value.define_type(:DateTime) do |type|
8
11
  type.define_checker do |value|
9
12
  value.is_a?(::DateTime) || value == ::DateTime::Infinity
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # @api public
4
- # @since 0.1.0
4
+ # @since 0.x.0
5
5
  SmartCore::Types::Value.define_type(:Enumerable) do |type|
6
6
  type.define_checker do |value|
7
7
  # TODO: realize
@@ -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(:Float) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Float)
@@ -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(:Hash) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Hash)
@@ -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(:Integer) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Integer)
@@ -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(:Module) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Module)
@@ -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(:Numeric) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Numeric)
@@ -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(:Proc) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Proc)
@@ -1,13 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
5
+ using SmartCore::Ext::BasicObjectAsObject
6
+
3
7
  # @api public
4
- # @since 0.x.0
8
+ # @since 0.3.0
5
9
  SmartCore::Types::Value.define_type(:Set) do |type|
6
10
  type.define_checker do |value|
7
- # TODO: realize
11
+ value.is_a?(::Set)
8
12
  end
9
13
 
10
14
  type.define_caster do |value|
11
- # TODO: realize
15
+ begin
16
+ ::Set.new(SmartCore::Types::Value::Array.cast(value))
17
+ rescue ::ArgumentError, ::NoMethodError
18
+ raise(SmartCore::Types::TypeCastingError, 'Non-castable to Set')
19
+ end
12
20
  end
13
21
  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(:String) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::String)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'stringio'
4
+
3
5
  # @api public
4
6
  # @since 0.x.0
5
7
  SmartCore::Types::Value.define_type(:StringIO) do |type|
@@ -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(:Symbol) do |type|
6
9
  type.define_checker do |value|
7
10
  value.is_a?(::Symbol)
@@ -2,10 +2,12 @@
2
2
 
3
3
  # @api public
4
4
  # @since 0.1.0
5
- SmartCore::Types::Value::Text = SmartCore::Types::System.type_sum(
6
- SmartCore::Types::Value::String,
7
- SmartCore::Types::Value::Symbol
8
- ) do |type|
5
+ # @version 0.3.0
6
+ SmartCore::Types::Value.define_type(:Text) do |type|
7
+ type.define_checker do |value|
8
+ SmartCore::Types::Value::String.valid?(value) || SmartCore::Types::Value::Symbol.valid?(value)
9
+ end
10
+
9
11
  type.define_caster do |value|
10
12
  next value if SmartCore::Types::Value::String.valid?(value)
11
13
  next value if SmartCore::Types::Value::Symbol.valid?(value)
@@ -2,8 +2,11 @@
2
2
 
3
3
  require 'time'
4
4
 
5
+ using SmartCore::Ext::BasicObjectAsObject
6
+
5
7
  # @api public
6
8
  # @since 0.1.0
9
+ # @version 0.3.0
7
10
  SmartCore::Types::Value.define_type(:Time) do |type|
8
11
  type.define_checker do |value|
9
12
  value.is_a?(::Time)
@@ -2,11 +2,14 @@
2
2
 
3
3
  # @api public
4
4
  # @since 0.1.0
5
- SmartCore::Types::Value::TimeBased = SmartCore::Types::System.type_sum(
6
- SmartCore::Types::Value::Time,
7
- SmartCore::Types::Value::DateTime,
8
- SmartCore::Types::Value::Date
9
- ) do |type|
5
+ # @version 0.3.0
6
+ SmartCore::Types::Value.define_type(:TimeBased) do |type|
7
+ type.define_checker do |value|
8
+ SmartCore::Types::Value::Time.valid?(value) ||
9
+ SmartCore::Types::Value::DateTime.valid?(value) ||
10
+ SmartCore::Types::Value::Date.valid?(value)
11
+ end
12
+
10
13
  type.define_caster do |value|
11
14
  next value if SmartCore::Types::Value::Time.valid?(value)
12
15
  next value if SmartCore::Types::Value::DateTime.valid?(value)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api public
4
+ # @since 0.3.0
5
+ class SmartCore::Types::Variadic < SmartCore::Types::Primitive
6
+ require_relative 'variadic/tuple'
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ using SmartCore::Ext::BasicObjectAsObject
4
+
5
+ # @api public
6
+ # @since 0.3.0
7
+ SmartCore::Types::Variadic.define_type(:Tuple) 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, tuple_signature|
15
+ next false unless SmartCore::Types::Value::Array.valid?(value)
16
+ next false if value.size != tuple_signature.size
17
+
18
+ value.each_with_index.all? do |tuple_val, tuple_val_index|
19
+ expected_tuple_type = tuple_signature.at(tuple_val_index)
20
+ tuple_val.is_a?(expected_tuple_type)
21
+ end
22
+ end
23
+ end