core-type 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE +353 -0
  4. data/README.md +4 -0
  5. data/lib/core/type/check_failed.rb +12 -0
  6. data/lib/core/type/coercions/array.rb +23 -0
  7. data/lib/core/type/coercions/decimal.rb +26 -0
  8. data/lib/core/type/coercions/float.rb +23 -0
  9. data/lib/core/type/coercions/hash.rb +23 -0
  10. data/lib/core/type/coercions/integer.rb +23 -0
  11. data/lib/core/type/coercions/string.rb +23 -0
  12. data/lib/core/type/coercions/symbol.rb +23 -0
  13. data/lib/core/type/coercions.rb +17 -0
  14. data/lib/core/type/composed.rb +72 -0
  15. data/lib/core/type/conversions/array.rb +19 -0
  16. data/lib/core/type/conversions/decimal.rb +26 -0
  17. data/lib/core/type/conversions/float.rb +28 -0
  18. data/lib/core/type/conversions/hash.rb +27 -0
  19. data/lib/core/type/conversions/integer.rb +28 -0
  20. data/lib/core/type/conversions/string.rb +23 -0
  21. data/lib/core/type/conversions/symbol.rb +36 -0
  22. data/lib/core/type/conversions.rb +17 -0
  23. data/lib/core/type/error.rb +10 -0
  24. data/lib/core/type/inputs/array.rb +31 -0
  25. data/lib/core/type/inputs/boolean.rb +58 -0
  26. data/lib/core/type/inputs/date.rb +21 -0
  27. data/lib/core/type/inputs/date_time.rb +21 -0
  28. data/lib/core/type/inputs/decimal.rb +11 -0
  29. data/lib/core/type/inputs/float.rb +11 -0
  30. data/lib/core/type/inputs/hash.rb +31 -0
  31. data/lib/core/type/inputs/integer.rb +11 -0
  32. data/lib/core/type/inputs/string.rb +11 -0
  33. data/lib/core/type/inputs/symbol.rb +11 -0
  34. data/lib/core/type/inputs/time.rb +21 -0
  35. data/lib/core/type/inputs.rb +21 -0
  36. data/lib/core/type/types/array.rb +25 -0
  37. data/lib/core/type/types/boolean.rb +25 -0
  38. data/lib/core/type/types/class.rb +25 -0
  39. data/lib/core/type/types/date.rb +25 -0
  40. data/lib/core/type/types/date_time.rb +27 -0
  41. data/lib/core/type/types/decimal.rb +27 -0
  42. data/lib/core/type/types/false.rb +25 -0
  43. data/lib/core/type/types/float.rb +25 -0
  44. data/lib/core/type/types/hash.rb +25 -0
  45. data/lib/core/type/types/integer.rb +25 -0
  46. data/lib/core/type/types/nil.rb +25 -0
  47. data/lib/core/type/types/object.rb +25 -0
  48. data/lib/core/type/types/string.rb +25 -0
  49. data/lib/core/type/types/symbol.rb +25 -0
  50. data/lib/core/type/types/time.rb +25 -0
  51. data/lib/core/type/types/true.rb +25 -0
  52. data/lib/core/type/types.rb +26 -0
  53. data/lib/core/type/validator.rb +37 -0
  54. data/lib/core/type/version.rb +13 -0
  55. data/lib/core/type.rb +19 -0
  56. data/lib/is/typed.rb +112 -0
  57. metadata +153 -0
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ require "bigdecimal"
6
+ require "bigdecimal/util"
7
+
8
+ module Core
9
+ module Type
10
+ module Conversions
11
+ # [public] Convertible decimal type.
12
+ #
13
+ class Decimal
14
+ include Is::Typed
15
+
16
+ def self.build(value)
17
+ value.to_d
18
+ end
19
+
20
+ check "must be a numeric value" do |value|
21
+ value.is_a?(::NilClass) || value.is_a?(::Numeric) || (value.is_a?(::String) && value =~ /^[-+]*[0-9]*[.]*[0-9]+$/)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Conversions
8
+ # [public] Convertible float type.
9
+ #
10
+ class Float
11
+ include Is::Typed
12
+
13
+ def self.build(value)
14
+ case value
15
+ when nil
16
+ 0.0
17
+ else
18
+ Kernel.Float(value)
19
+ end
20
+ end
21
+
22
+ check "must be a numeric value" do |value|
23
+ value.is_a?(::NilClass) || value.is_a?(::Numeric) || (value.is_a?(::String) && value =~ /^[-+]*[0-9]*[.]*[0-9]+$/)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Conversions
8
+ # [public] Convertible hash type.
9
+ #
10
+ class Hash
11
+ include Is::Typed
12
+
13
+ def self.build(value)
14
+ if value.respond_to?(:to_hash)
15
+ value.to_hash
16
+ elsif value.respond_to?(:to_h)
17
+ value.to_h
18
+ end
19
+ end
20
+
21
+ check "must respond to `to_hash` or `to_h`" do |value|
22
+ value.respond_to?(:to_hash) || value.respond_to?(:to_h)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Conversions
8
+ # [public] Convertible integer type.
9
+ #
10
+ class Integer
11
+ include Is::Typed
12
+
13
+ def self.build(value)
14
+ case value
15
+ when nil
16
+ 0
17
+ else
18
+ Kernel.Integer(value)
19
+ end
20
+ end
21
+
22
+ check "must respond to `to_int` or `to_i`" do |value|
23
+ value.respond_to?(:to_int) || value.respond_to?(:to_i)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Conversions
8
+ # [public] Convertible string type.
9
+ #
10
+ class String
11
+ include Is::Typed
12
+
13
+ def self.build(value)
14
+ Kernel.String(value)
15
+ end
16
+
17
+ check "must respond to `to_str` or `to_s`" do |value|
18
+ value.respond_to?(:to_str) || value.respond_to?(:to_s)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Conversions
8
+ # [public] Convertible symbol type.
9
+ #
10
+ class Symbol
11
+ include Is::Typed
12
+
13
+ def self.build(value)
14
+ Kernel.String(value).to_sym
15
+ end
16
+
17
+ check "must not be nil" do |value|
18
+ !value.nil?
19
+ end
20
+
21
+ check "must not be an empty string" do |value|
22
+ case value
23
+ when ::String
24
+ !value.empty?
25
+ else
26
+ true
27
+ end
28
+ end
29
+
30
+ check "must respond to `to_str` or `to_s`" do |value|
31
+ (value.respond_to?(:to_str) || value.respond_to?(:to_s))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Core
4
+ module Type
5
+ # [public] Explicitly converts one type to another.
6
+ #
7
+ module Conversions
8
+ require_relative "conversions/array"
9
+ require_relative "conversions/decimal"
10
+ require_relative "conversions/float"
11
+ require_relative "conversions/hash"
12
+ require_relative "conversions/integer"
13
+ require_relative "conversions/string"
14
+ require_relative "conversions/symbol"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Core
4
+ module Type
5
+ # [public]
6
+ #
7
+ class Error < StandardError
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+ require_relative "../conversions/array"
5
+
6
+ module Core
7
+ module Type
8
+ module Inputs
9
+ # [public]
10
+ #
11
+ class Array
12
+ include Is::Typed
13
+
14
+ def self.build(value)
15
+ return [] if value == ""
16
+
17
+ Conversions::Array.build(value)
18
+ end
19
+
20
+ def self.normalize(value)
21
+ case value
22
+ when ::String
23
+ value.strip
24
+ else
25
+ value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ # [public]
9
+ #
10
+ class Boolean
11
+ include Is::Typed
12
+
13
+ FALSE_VALUES = [
14
+ 0,
15
+ false,
16
+ "0",
17
+ "f",
18
+ "false",
19
+ "n",
20
+ "no",
21
+ "off"
22
+ ].freeze
23
+
24
+ TRUE_VALUES = [
25
+ 1,
26
+ true,
27
+ "1",
28
+ "on",
29
+ "t",
30
+ "true",
31
+ "y",
32
+ "yes"
33
+ ].freeze
34
+
35
+ BOOLEAN_VALUES = (FALSE_VALUES + TRUE_VALUES).each_with_object({}) { |value, hash|
36
+ hash[value] = TRUE_VALUES.include?(value)
37
+ }.freeze
38
+
39
+ def self.build(value)
40
+ BOOLEAN_VALUES[value]
41
+ end
42
+
43
+ def self.normalize(value)
44
+ case value
45
+ when ::String
46
+ value.downcase.strip
47
+ else
48
+ value
49
+ end
50
+ end
51
+
52
+ check "must be one of: #{BOOLEAN_VALUES.keys.join(", ")}" do |value|
53
+ BOOLEAN_VALUES.include?(value)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ require_relative "../../../is/typed"
6
+
7
+ module Core
8
+ module Type
9
+ module Inputs
10
+ # [public]
11
+ #
12
+ class Date
13
+ include Is::Typed
14
+
15
+ def self.build(value)
16
+ ::Date.parse(value)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ require_relative "../../../is/typed"
6
+
7
+ module Core
8
+ module Type
9
+ module Inputs
10
+ # [public]
11
+ #
12
+ class DateTime
13
+ include Is::Typed
14
+
15
+ def self.build(value)
16
+ ::DateTime.parse(value)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../conversions/decimal"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ Decimal = Conversions::Decimal
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../conversions/float"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ Float = Conversions::Float
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+ require_relative "../conversions/hash"
5
+
6
+ module Core
7
+ module Type
8
+ module Inputs
9
+ # [public]
10
+ #
11
+ class Hash
12
+ include Is::Typed
13
+
14
+ def self.build(value)
15
+ return {} if value == ""
16
+
17
+ Conversions::Hash.build(value)
18
+ end
19
+
20
+ def self.normalize(value)
21
+ case value
22
+ when ::String
23
+ value.strip
24
+ else
25
+ value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../conversions/integer"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ Integer = Conversions::Integer
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../conversions/string"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ String = Conversions::String
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../coercions/symbol"
4
+
5
+ module Core
6
+ module Type
7
+ module Inputs
8
+ Symbol = Coercions::Symbol
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ require_relative "../../../is/typed"
6
+
7
+ module Core
8
+ module Type
9
+ module Inputs
10
+ # [public]
11
+ #
12
+ class Time
13
+ include Is::Typed
14
+
15
+ def self.build(value)
16
+ ::DateTime.parse(value).to_time
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Core
4
+ module Type
5
+ # [public] Converts user-input into typed values.
6
+ #
7
+ module Inputs
8
+ require_relative "inputs/array"
9
+ require_relative "inputs/boolean"
10
+ require_relative "inputs/date"
11
+ require_relative "inputs/date_time"
12
+ require_relative "inputs/decimal"
13
+ require_relative "inputs/float"
14
+ require_relative "inputs/hash"
15
+ require_relative "inputs/integer"
16
+ require_relative "inputs/string"
17
+ require_relative "inputs/symbol"
18
+ require_relative "inputs/time"
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict array type.
9
+ #
10
+ class Array
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be a array" do |value|
20
+ value.is_a?(::Array)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict boolean type.
9
+ #
10
+ class Boolean
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be true or false" do |value|
20
+ value.is_a?(::TrueClass) || value.is_a?(::FalseClass)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict class type.
9
+ #
10
+ class Class
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be a class" do |value|
20
+ value.is_a?(::Class)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict date type.
9
+ #
10
+ class Date
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be a date" do |value|
20
+ value.is_a?(::Date)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ require "date"
6
+
7
+ module Core
8
+ module Type
9
+ module Types
10
+ # [public] Strict datetime type.
11
+ #
12
+ class DateTime
13
+ include Is::Typed
14
+
15
+ # [public]
16
+ #
17
+ def self.build(value)
18
+ value
19
+ end
20
+
21
+ check "must be a datetime" do |value|
22
+ value.is_a?(::DateTime)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ require "bigdecimal"
6
+
7
+ module Core
8
+ module Type
9
+ module Types
10
+ # [public] Strict decimal type.
11
+ #
12
+ class Decimal
13
+ include Is::Typed
14
+
15
+ # [public]
16
+ #
17
+ def self.build(value)
18
+ value
19
+ end
20
+
21
+ check "must be a decimal" do |value|
22
+ value.is_a?(::BigDecimal)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict false type.
9
+ #
10
+ class False
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be false" do |value|
20
+ value.is_a?(::FalseClass)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../is/typed"
4
+
5
+ module Core
6
+ module Type
7
+ module Types
8
+ # [public] Strict float type.
9
+ #
10
+ class Float
11
+ include Is::Typed
12
+
13
+ # [public]
14
+ #
15
+ def self.build(value)
16
+ value
17
+ end
18
+
19
+ check "must be a float" do |value|
20
+ value.is_a?(::Float)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end