core-type 0.0.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 (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