smart_types 0.1.0 → 0.6.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/CHANGELOG.md +57 -0
  4. data/Gemfile.lock +71 -58
  5. data/LICENSE.txt +1 -1
  6. data/README.md +363 -34
  7. data/Rakefile +0 -1
  8. data/bin/console +2 -2
  9. data/lib/smart_core/types/errors.rb +12 -0
  10. data/lib/smart_core/types/primitive/caster.rb +5 -2
  11. data/lib/smart_core/types/primitive/checker.rb +5 -2
  12. data/lib/smart_core/types/primitive/factory/definition_context.rb +140 -4
  13. data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
  14. data/lib/smart_core/types/primitive/factory.rb +104 -7
  15. data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
  16. data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
  17. data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
  18. data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
  19. data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
  20. data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
  21. data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
  22. data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
  23. data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +26 -2
  24. data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
  25. data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
  26. data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
  27. data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
  28. data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
  29. data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
  30. data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
  31. data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +25 -1
  32. data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
  33. data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
  34. data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
  35. data/lib/smart_core/types/primitive/undefined_caster.rb +4 -1
  36. data/lib/smart_core/types/primitive/validator/result.rb +78 -0
  37. data/lib/smart_core/types/primitive/validator.rb +93 -0
  38. data/lib/smart_core/types/primitive.rb +99 -15
  39. data/lib/smart_core/types/protocol/instance_of.rb +19 -0
  40. data/lib/smart_core/types/protocol.rb +7 -0
  41. data/lib/smart_core/types/value/array.rb +3 -0
  42. data/lib/smart_core/types/value/big_decimal.rb +4 -1
  43. data/lib/smart_core/types/value/boolean.rb +3 -0
  44. data/lib/smart_core/types/value/class.rb +3 -0
  45. data/lib/smart_core/types/value/date.rb +3 -0
  46. data/lib/smart_core/types/value/date_time.rb +3 -0
  47. data/lib/smart_core/types/value/enumerable.rb +1 -1
  48. data/lib/smart_core/types/value/enumerator.rb +13 -0
  49. data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
  50. data/lib/smart_core/types/value/float.rb +3 -0
  51. data/lib/smart_core/types/value/hash.rb +3 -0
  52. data/lib/smart_core/types/value/integer.rb +3 -0
  53. data/lib/smart_core/types/value/io.rb +13 -0
  54. data/lib/smart_core/types/value/method.rb +9 -0
  55. data/lib/smart_core/types/value/module.rb +3 -0
  56. data/lib/smart_core/types/value/nil.rb +0 -2
  57. data/lib/smart_core/types/value/numeric.rb +3 -0
  58. data/lib/smart_core/types/value/proc.rb +3 -0
  59. data/lib/smart_core/types/value/range.rb +9 -0
  60. data/lib/smart_core/types/value/rational.rb +13 -0
  61. data/lib/smart_core/types/value/set.rb +21 -0
  62. data/lib/smart_core/types/value/string.rb +3 -0
  63. data/lib/smart_core/types/value/string_io.rb +15 -0
  64. data/lib/smart_core/types/value/symbol.rb +3 -0
  65. data/lib/smart_core/types/value/text.rb +6 -4
  66. data/lib/smart_core/types/value/time.rb +3 -0
  67. data/lib/smart_core/types/value/time_based.rb +8 -5
  68. data/lib/smart_core/types/value/unbound_method.rb +9 -0
  69. data/lib/smart_core/types/value.rb +9 -0
  70. data/lib/smart_core/types/variadic/array_of.rb +23 -0
  71. data/lib/smart_core/types/variadic/enum.rb +11 -0
  72. data/lib/smart_core/types/variadic/tuple.rb +23 -0
  73. data/lib/smart_core/types/variadic.rb +10 -0
  74. data/lib/smart_core/types/version.rb +2 -1
  75. data/lib/smart_core/types.rb +2 -0
  76. data/smart_types.gemspec +5 -4
  77. metadata +61 -18
  78. data/.travis.yml +0 -21
  79. data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
  80. data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
  81. data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12c87a28e4cb88c84907c5d811253c4cb70e3e4aad462010c47c1a6d88c21d81
4
- data.tar.gz: af0155909d10f02369aa5b60c97de4b0b91fbfad92ba79d1f94b5b3333ede373
3
+ metadata.gz: 7d46db58ce368955b324f4acb5fbfa74100789abe263c8e83fa8a73c482b6dd4
4
+ data.tar.gz: f5377e4cc8693855b885d197f1d5b8429ba78efc30b781703a2ba95230d58d2b
5
5
  SHA512:
6
- metadata.gz: aa5eb3001d7909b30e9fe2df27b92bff6ee22d9e92ef27f37dfbe11c18f968ee932cf0e064ecb2db808d8a0913d3c5fe7650d0d7b15af51bbe4591afeef39670
7
- data.tar.gz: e0fa90c1783113d8d702414596cf001e0e54b786c6d21248e52f5e2401901eddebb09d182349abccda301998782242fa02d4a94e61eb2a3f301fe982a7d5ceff
6
+ metadata.gz: 294f3ef4a287aef01cbf48c6250ece9190effee142b42596a453657f7ed541080d964c4d22e56113c8a7fc80298f2dfd5fefe92159a8499829b34d5a993b0ddb
7
+ data.tar.gz: a515dad1255bf4b3e757d12011f8c4eedde8a79fd265e5acba10e5a19282c40f3f61d85aa094cb962c1029329b06cd225a828aa9bd23bfaec6e575b89bd945a0
data/.rubocop.yml CHANGED
@@ -5,7 +5,8 @@ inherit_gem:
5
5
  - lib/rubocop.rspec.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: 2.7.1
8
+ TargetRubyVersion: 3.0.0
9
+ NewCops: enable
9
10
  Include:
10
11
  - lib/**/*.rb
11
12
  - spec/**/*.rb
@@ -17,3 +18,7 @@ AllCops:
17
18
  # NOTE: support for old ruby versions
18
19
  Style/RedundantBegin:
19
20
  Enabled: false
21
+
22
+ # NOTE: used only in specs and it is ok in specs
23
+ Lint/EmptyBlock:
24
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,2 +1,59 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
+
4
+ # [0.6.0] - 2021-04-29
5
+ ### Added
6
+ - New type of `SmartCode::Types::Variadic` category:
7
+ - `SmartCore::Types::Variadic::ArrayOf` (`Array` with element types validation)
8
+
9
+
10
+ # [0.5.0] - 2021-01-28
11
+ ### Added
12
+ - New types of `SmartCore::Types::Variadic` category:
13
+ - `SmartCore::Types::Variadic::Enum` (a simple enumeration on plain values);
14
+
15
+ # [0.4.0] - 2021-01-18
16
+ ### Added
17
+ - Support for *Ruby 3*;
18
+
19
+ ## [0.3.0] - 2020-12-22
20
+ ### Added
21
+ - Extended **Type Definition API**: support for **runtime attributes**:
22
+ - Type checkers, type casters and type invariants now receives runtime attributes (you can omit these);
23
+ - Type definitioning extended with `runtime_attribute_checker`-checker definition (runtime attributes validator);
24
+ - Types with incorrect runtime attributes will raise `SmartCore::Types::IncorrectRuntimeAttributesError` exception;
25
+ - Types which has no support for runtime attributes will raise `SmartCore::Types::RuntimeAttributesUnsupportedError` excpetion;
26
+ - All types by default has a method alias (`()`) which does not allow runtime attributes (for example: `SmartCore::Types::Value::String` has
27
+ a runtime-based alias `SmartCore::Types::Value::String()` which does not accept any attribute
28
+ (`SmartCore::Types::Value::String('test')` will raise `SmartCore::Types::RuntimeAttributesUnsupportedError` respectively));
29
+ - Extended Internal **Type Development API**:
30
+ - all types has a reference to it's type category;
31
+ - Brand new `SmartCore::Types::Protocol` type category and new types:
32
+ - `SmartCore::Types::Protocol::InstanceOf` (runtime-based type);
33
+ - Brand new `SmartCore::Types::Variadic` type category and new types:
34
+ - `SmartCore::Types::Variadic::Tuple` (runtime-based type);
35
+ - New types of `SmartCore::Types::Value` category:
36
+ - `SmartCore::Types::Value::Set` (based on `Set` type with a support for type casting);
37
+ - Support for BasicObject values inside type checkers that can not be checked correctly via `#is_a?/#kind_of?` before;
38
+
39
+ ### Changed
40
+ - Updated development dependencies;
41
+ - Drop `Travis CI` (TODO: migrate to `Github Actions`);
42
+ - **Ruby@2.4** is no longer supported;
43
+
44
+ ## [0.2.0] - 2020-11-21
45
+ ### Added
46
+ - Brand new **Type invariant API**:
47
+ - globally refactored validation logic (with backward compatability for `#valid?(value)` method);
48
+ - new type definition DSL: `.invariant(name)` and `.invariant_chain(name)`;
49
+ - chained invariants will be invoked according to the definition order (second invokation
50
+ depends on previous successful invariant check);
51
+ - new validation API: `validate(value)` (with `#errors` support based on invariant names);
52
+ - at this moment Invariant API is supported only by primitive types (type sum and type multiplication support coming soon);
53
+
54
+ ### Changed
55
+
56
+ - Updated `smart_engine` dependency (to `~> 0.7`) (need `SmartCore::Engine::Atom`);
57
+
58
+ ## [0.1.0] - 2020-05-05
59
+ - Release :)
data/Gemfile.lock CHANGED
@@ -1,92 +1,105 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_types (0.1.0)
5
- smart_engine (~> 0.6)
4
+ smart_types (0.6.0)
5
+ smart_engine (~> 0.11)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activesupport (6.0.2.2)
10
+ activesupport (6.1.1)
11
11
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
- i18n (>= 0.7, < 2)
13
- minitest (~> 5.1)
14
- tzinfo (~> 1.1)
15
- zeitwerk (~> 2.2)
16
- armitage-rubocop (0.82.0.2)
17
- rubocop (= 0.82.0)
18
- rubocop-performance (= 1.5.2)
19
- rubocop-rails (= 2.5.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ zeitwerk (~> 2.3)
16
+ armitage-rubocop (1.7.0.1)
17
+ rubocop (= 1.7.0)
18
+ rubocop-performance (= 1.9.1)
19
+ rubocop-rails (= 2.9.1)
20
20
  rubocop-rake (= 0.5.1)
21
- rubocop-rspec (= 1.39.0)
22
- ast (2.4.0)
23
- concurrent-ruby (1.1.6)
24
- diff-lcs (1.3)
25
- docile (1.3.2)
26
- i18n (1.8.2)
21
+ rubocop-rspec (= 2.1.0)
22
+ ast (2.4.1)
23
+ coderay (1.1.3)
24
+ concurrent-ruby (1.1.7)
25
+ diff-lcs (1.4.4)
26
+ docile (1.3.5)
27
+ i18n (1.8.7)
27
28
  concurrent-ruby (~> 1.0)
28
- jaro_winkler (1.5.4)
29
- minitest (5.14.0)
30
- parallel (1.19.1)
31
- parser (2.7.1.2)
32
- ast (~> 2.4.0)
33
- rack (2.2.2)
29
+ method_source (1.0.0)
30
+ minitest (5.14.3)
31
+ parallel (1.20.1)
32
+ parser (3.0.0.0)
33
+ ast (~> 2.4.1)
34
+ pry (0.13.1)
35
+ coderay (~> 1.1)
36
+ method_source (~> 1.0)
37
+ rack (2.2.3)
34
38
  rainbow (3.0.0)
35
- rake (13.0.1)
39
+ rake (13.0.3)
40
+ regexp_parser (2.0.3)
36
41
  rexml (3.2.4)
37
- rspec (3.9.0)
38
- rspec-core (~> 3.9.0)
39
- rspec-expectations (~> 3.9.0)
40
- rspec-mocks (~> 3.9.0)
41
- rspec-core (3.9.2)
42
- rspec-support (~> 3.9.3)
43
- rspec-expectations (3.9.1)
42
+ rspec (3.10.0)
43
+ rspec-core (~> 3.10.0)
44
+ rspec-expectations (~> 3.10.0)
45
+ rspec-mocks (~> 3.10.0)
46
+ rspec-core (3.10.1)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-expectations (3.10.1)
44
49
  diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.9.0)
46
- rspec-mocks (3.9.1)
50
+ rspec-support (~> 3.10.0)
51
+ rspec-mocks (3.10.1)
47
52
  diff-lcs (>= 1.2.0, < 2.0)
48
- rspec-support (~> 3.9.0)
49
- rspec-support (3.9.3)
50
- rubocop (0.82.0)
51
- jaro_winkler (~> 1.5.1)
53
+ rspec-support (~> 3.10.0)
54
+ rspec-support (3.10.1)
55
+ rubocop (1.7.0)
52
56
  parallel (~> 1.10)
53
- parser (>= 2.7.0.1)
57
+ parser (>= 2.7.1.5)
54
58
  rainbow (>= 2.2.2, < 4.0)
59
+ regexp_parser (>= 1.8, < 3.0)
55
60
  rexml
61
+ rubocop-ast (>= 1.2.0, < 2.0)
56
62
  ruby-progressbar (~> 1.7)
57
63
  unicode-display_width (>= 1.4.0, < 2.0)
58
- rubocop-performance (1.5.2)
59
- rubocop (>= 0.71.0)
60
- rubocop-rails (2.5.2)
61
- activesupport
64
+ rubocop-ast (1.4.0)
65
+ parser (>= 2.7.1.5)
66
+ rubocop-performance (1.9.1)
67
+ rubocop (>= 0.90.0, < 2.0)
68
+ rubocop-ast (>= 0.4.0)
69
+ rubocop-rails (2.9.1)
70
+ activesupport (>= 4.2.0)
62
71
  rack (>= 1.1)
63
- rubocop (>= 0.72.0)
72
+ rubocop (>= 0.90.0, < 2.0)
64
73
  rubocop-rake (0.5.1)
65
74
  rubocop
66
- rubocop-rspec (1.39.0)
67
- rubocop (>= 0.68.1)
68
- ruby-progressbar (1.10.1)
69
- simplecov (0.18.5)
75
+ rubocop-rspec (2.1.0)
76
+ rubocop (~> 1.0)
77
+ rubocop-ast (>= 1.1.0)
78
+ ruby-progressbar (1.11.0)
79
+ simplecov (0.21.2)
70
80
  docile (~> 1.1)
71
81
  simplecov-html (~> 0.11)
72
- simplecov-html (0.12.2)
73
- smart_engine (0.6.0)
74
- thread_safe (0.3.6)
75
- tzinfo (1.2.7)
76
- thread_safe (~> 0.1)
82
+ simplecov_json_formatter (~> 0.1)
83
+ simplecov-html (0.12.3)
84
+ simplecov_json_formatter (0.1.2)
85
+ smart_engine (0.11.0)
86
+ tzinfo (2.0.4)
87
+ concurrent-ruby (~> 1.0)
77
88
  unicode-display_width (1.7.0)
78
- zeitwerk (2.3.0)
89
+ zeitwerk (2.4.2)
79
90
 
80
91
  PLATFORMS
81
- ruby
92
+ x86_64-darwin-19
93
+ x86_64-darwin-20
82
94
 
83
95
  DEPENDENCIES
84
- armitage-rubocop (~> 0.82)
96
+ armitage-rubocop (~> 1.7)
85
97
  bundler (~> 2.1)
98
+ pry (~> 0.13)
86
99
  rake (~> 13.0)
87
- rspec (~> 3.9)
88
- simplecov (~> 0.18)
100
+ rspec (~> 3.10)
101
+ simplecov (~> 0.21)
89
102
  smart_types!
90
103
 
91
104
  BUNDLED WITH
92
- 2.1.4
105
+ 2.2.3
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Rustam Ibragimov
3
+ Copyright (c) 2020-2021 Rustam Ibragimov
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SmartCore::Types &middot; [![Gem Version](https://badge.fury.io/rb/smart_types.svg)](https://badge.fury.io/rb/smart_types) [![Build Status](https://travis-ci.org/smart-rb/smart_types.svg?branch=master)](https://travis-ci.org/smart-rb/smart_types)
1
+ # SmartCore::Types &middot; [![Supporting](https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_badge.png)](https://github.com/Cado-Labs/) &middot; [![Gem Version](https://badge.fury.io/rb/smart_types.svg)](https://badge.fury.io/rb/smart_types)
2
2
 
3
3
  > A set of objects that acts like types (type checking and type casting) with a support for basic type algebra.
4
4
 
@@ -6,6 +6,16 @@ Minimalistic type system for any ruby project. Supports custom type definitionin
6
6
  type validation, type casting and type categorizing. Provides a set of commonly used type
7
7
  categories and general purpose types. Has a flexible and simplest type definition toolchain.
8
8
 
9
+ ---
10
+
11
+ <p>
12
+ <a href="https://github.com/Cado-Labs">
13
+ <img src="https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_supporting.svg" alt="Supported by Cado Labs" />
14
+ </a>
15
+ </p>
16
+
17
+ ---
18
+
9
19
  ## Installation
10
20
 
11
21
  ```ruby
@@ -24,7 +34,28 @@ require 'smart_core/types'
24
34
 
25
35
  ---
26
36
 
27
- ## Type Interface
37
+ ## Usage
38
+
39
+ - [Type interface and basic type algebra](#type-interface-and-basic-type-algebra)
40
+ - [Supported types](#supported-types)
41
+ - [Primitives](#primitives) (`SmartCore::Types::Value`)
42
+ - [Protocols](#protocols) (`SmartCore::Types::Protocol`)
43
+ - [Variadic](#variadic) (`SmartCore::Types::Variadic`)
44
+ - [Nilable types](#nilable-types)
45
+ - [Custom type definition](#custom-type-definition)
46
+ - [Primitive type definition](#primitive-type-definition)
47
+ - [With type invariants](#with-type-invariants)
48
+ - [Type validation](#type-validation)
49
+ - [Type casting](#type-casting)
50
+ - [Roadmap](#roadmap)
51
+ - [Contributing](#contributing)
52
+ - [Build](#build)
53
+ - [License](#license)
54
+ - [Authors](#authors)
55
+
56
+ ---
57
+
58
+ ## Type Interface and basic type algebra
28
59
 
29
60
  ```ruby
30
61
  # documentation is coming
@@ -37,9 +68,24 @@ type3 = type1 | type2
37
68
  type4 = type1 & type2
38
69
  ```
39
70
 
71
+ Types with runtime:
72
+
73
+ ```ruby
74
+ # get a type object with a custom runtime (instances of String or Symbol):
75
+ type = SmartCore::Types::Protocol::InstanceOf(::String, ::Symbol)
76
+ type.valid?(:test) # => true
77
+ type.valid?('test') # => true
78
+ type.valid?(123.456) # => false
79
+
80
+ # another type object with a custom runtime (tuple (String, Integer, Time)):
81
+ type = SmartCore::Types::Variadic::Tuple(::String, ::Integer, ::DateTime)
82
+ type.valid?(['test', 1, DateTime.new]) # => true
83
+ type.valid?([:test, 2]) # => false
84
+ ```
85
+
40
86
  ## Supported types
41
87
 
42
- - Primitive Value Types:
88
+ #### Primitives:
43
89
 
44
90
  ```ruby
45
91
  SmartCore::Types::Value::Any
@@ -53,6 +99,7 @@ SmartCore::Types::Value::Numeric
53
99
  SmartCore::Types::Value::BigDecimal
54
100
  SmartCore::Types::Value::Boolean
55
101
  SmartCore::Types::Value::Array
102
+ SmartCore::Types::Value::Set
56
103
  SmartCore::Types::Value::Hash
57
104
  SmartCore::Types::Value::Proc
58
105
  SmartCore::Types::Value::Class
@@ -65,52 +112,188 @@ SmartCore::Types::Value::TimeBased
65
112
 
66
113
  ---
67
114
 
68
- ## Nilable types
115
+ #### Protocols:
69
116
 
70
117
  ```ruby
71
- SmartCore::Types::Value::Any.nilable
72
- SmartCore::Types::Value::Nil.nilable
73
- SmartCore::Types::Value::String.nilable
74
- SmartCore::Types::Value::Symbol.nilable
75
- SmartCore::Types::Value::Text.nilable
76
- SmartCore::Types::Value::Integer.nilable
77
- SmartCore::Types::Value::Float.nilable
78
- SmartCore::Types::Value::Numeric.nilable
79
- SmartCore::Types::Value::BigDecimal.nilable
80
- SmartCore::Types::Value::Boolean.nilable
81
- SmartCore::Types::Value::Array.nilable
82
- SmartCore::Types::Value::Hash.nilable
83
- SmartCore::Types::Value::Proc.nilable
84
- SmartCore::Types::Value::Class.nilable
85
- SmartCore::Types::Value::Module.nilable
86
- SmartCore::Types::Value::Time.nilable.nilable
87
- SmartCore::Types::Value::DateTime.nilable
88
- SmartCore::Types::Value::Date.nilable
89
- SmartCore::Types::Value::TimeBased
118
+ SmartCore::Types::Protocol::InstanceOf
119
+ ```
120
+
121
+ ```ruby
122
+ # examples (SmartCore::Types::Protocol::InstanceOf):
123
+ SmartCore::Types::Protocol::InstanceOf(::Integer) # only integer
124
+ SmartCore::Types::Protocol::InstanceOf(::String, ::Symbol) # string or symbol
125
+ SmartCore::Types::Protocol::InstanceOf(::Time, ::DateTime, ::Date) # time or datetime or date
90
126
  ```
91
127
 
92
128
  ---
93
129
 
94
- ## Type validation and type casting
130
+ #### Variadic:
95
131
 
96
132
  ```ruby
97
- # documentation is coming
133
+ SmartCore::Types::Variadic::ArrayOf
134
+ SmartCore::Types::Variadic::Enum
135
+ SmartCore::Types::Variadic::Tuple
136
+ ```
98
137
 
99
- SmartCore::Types::Value::String.valid?('test') # => true
100
- SmartCore::Types::Value::String.valid?(123.45) # => false
138
+ ```ruby
139
+ # example (SmartCore::Types::Variadic::ArrayOf):
140
+ SmartCore::Types::Variadic::ArrayOf(::String, ::Array) # array of strings or arrays
101
141
 
102
- SmartCore::Types::Value::String.cast(123) # => "123"
103
- SmartCore::Types::Value::Float.cast('55') # => 55.0
142
+ # example (SmartCore::Types::Variadic::Enum):
143
+ SmartCore::Types::Variadic::Enum('string', 1337, :symbol) # one of enumerated values
144
+
145
+ # examples (SmartCore::Types::Variadic::Tuple):
146
+ SmartCore::Types::Variadic::Tuple(::String, ::Integer, ::Time) # array with signature [<string>, <integer>, <time>]
147
+ SmartCore::Types::Variadic::Tuple(::Symbol, ::Float) # array with signature [<symbol>, <float>]
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Nilable types
153
+
154
+ - invoke `.nilable` on any type object:
155
+
156
+ ```ruby
157
+ SmartCore::Types::Value::String.nilable
158
+ # -- or --
159
+ SmartCore::Types::Value::Time.nilable
160
+ # and etc.
104
161
  ```
105
162
 
106
163
  ---
107
164
 
108
165
  ## Custom type definition
109
166
 
167
+ Type definition is a composition of:
168
+
169
+ - type checker (required);
170
+ - type caster (optional);
171
+ - type invariants (optional);
172
+ - type invariant chains (optional);
173
+
174
+ Invariant is a custom validation block that will work as a logical value checker. You can have as much invariants as you want.
175
+
176
+ Type invariants does not depends on each other (invariant defined out from chain does not depends on other invariants);
177
+
178
+ Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
179
+
180
+ **!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
181
+ Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
182
+
183
+ Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section). Invariant error code pattern:
184
+ - for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
185
+ - for single invariant: `TypeName.invariant_name`;
186
+
187
+ #### Primitive type definition
188
+
110
189
  ```ruby
111
190
  # documentation is coming
112
191
 
113
192
  # example:
193
+ SmartCore::Types::Value.define_type(:String) do |type|
194
+ type.define_checker do |value, runtime_attrs| # runtime attributes are optional
195
+ value.is_a?(::String)
196
+ end
197
+
198
+ type.define_caster do |value, runtime_attrs| # runtime attributes are optional
199
+ value.to_s
200
+ end
201
+ end
202
+
203
+ # get a type object:
204
+ SmartCore::Types::Value::String
205
+ # --- or ---
206
+ SmartCore::Types::Value::String() # without runtime attributes
207
+ # --- or ---
208
+ SmartCore::Types::Value::String('some_attr', :another_attr) # with runtime attributes
209
+
210
+ # work with type object: see documentation below
211
+ ```
212
+
213
+ #### With type invariants
214
+
215
+ ```ruby
216
+ SmartCore::Types::Value.define_type(:String) do |type|
217
+ type.define_checker do |value, runtime_attrs|
218
+ value.is_a?(::String)
219
+ end
220
+
221
+ type.define_caster do |value, runtime_attrs|
222
+ value.to_s
223
+ end
224
+
225
+ # NOTE:
226
+ # invariant defined out from chain does not depends on other invariants
227
+ type.invariant(:uncensored_content) do |value, runtime_attrs|
228
+ !value.include?('uncensored_word')
229
+ end
230
+
231
+ type.invariant(:filled) do |value, runtime_attrs|
232
+ value != ''
233
+ end
234
+
235
+ type.invariant_chain(:password) do
236
+ invariant(:should_present) do |value, runtime_attrs|
237
+ value != ''
238
+ end
239
+
240
+ invariant(:should_have_numbers) do |value, runtime_attrs|
241
+ v.match?(/[0-9]+/)
242
+ end
243
+
244
+ # NOTE:
245
+ # inside a chain each next invariant invokation
246
+ # depends on previous successful invariant check
247
+ end
248
+ end
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Type validation
254
+
255
+ Type validation reflects on two APIs:
256
+
257
+ - type checker ([how to define type checkers](#custom-type-definition));
258
+ - type invariants (invariants and invariant chains) ([how to define type invariants](#custom-type-definition));
259
+
260
+ Type invariants does not depends on each other (invariant defined out from the chain does not depends on other invariants);
261
+
262
+ Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
263
+
264
+ **!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
265
+ Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
266
+
267
+ Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section) and represents a set of error codes in result object;
268
+
269
+ Type valdiation interface:
270
+
271
+ - `valid?(value)` - validates value and returns `true` or `false`;
272
+ - returns `ture` only if the type checker returns `true` and all invariants are valid;
273
+ - `validate(value)` - validates value and returns the monadic result object:
274
+ - `SmartCore::Types::Primitive::Validator::Result` for primitive types;
275
+ - `SmartCore::Types::Primitive::SumValidator::Result` for sum-based types;
276
+ - `SmartCore::Types::Primitive::MultValidator::Result` for mult-based types;
277
+ - `SmartCore::Types::Primitive::NilableValidator::Result` for nilable types;
278
+ - `validate!(value)` - validates value and returns nothing (for successful validation) or
279
+ raises an exception (`SmartCore::Types::TypeError`) (for unsuccessful validation);
280
+
281
+ Validation result object interface:
282
+
283
+ - `#success?` / `#failure?` (`#success?` is a combination of `valid_check? && valid_invariants?`; `#failure?` - is an opposite of `#success?`);
284
+ - `#valid_check?` (valid type checker or not);
285
+ - `#valid_invariants?` (`false` if at least one invariant is invalid);
286
+ - `#errors` (the same as `#invariant_errors` and the same as `#error_codes`) - an array of failed invariant names;
287
+ - error code patterns:
288
+ - for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
289
+ - for single invariant: `TypeName.invariant_name`;
290
+ - `#checked_value` (the same as `#value`) - checked value :)
291
+
292
+ ---
293
+
294
+ Imagine that we have `String` type like this:
295
+
296
+ ```ruby
114
297
  SmartCore::Types::Value.define_type(:String) do |type|
115
298
  type.define_checker do |value|
116
299
  value.is_a?(::String)
@@ -119,21 +302,94 @@ SmartCore::Types::Value.define_type(:String) do |type|
119
302
  type.define_caster do |value|
120
303
  value.to_s
121
304
  end
305
+
306
+ type.invariant(:uncensored_content) do |value|
307
+ !value.include?('uncensored_word')
308
+ end
309
+
310
+ type.invariant(:filled) do |value|
311
+ value != ''
312
+ end
313
+
314
+ type.invariant_chain(:password) do
315
+ invariant(:should_present) { |value| value != '' }
316
+ invariant(:should_have_numbers) { |value| v.match?(/[0-9]+/) }
317
+ end
122
318
  end
123
319
  ```
124
320
 
321
+ Validation interface and usage:
322
+
323
+ ```ruby
324
+ SmartCore::Types::Value::String.valid?('test123') # => true
325
+ SmartCore::Types::Value::String.valid?(123.45) # => false
326
+ ```
327
+
328
+ ```ruby
329
+ result = SmartCore::Types::Value::String.validate('test')
330
+
331
+ result.checked_value # => 'test'
332
+ # --- same as: ---
333
+ result.value
334
+
335
+ result.success? # => false (valid_check? && valid_invariants?)
336
+ result.failure? # => true
337
+
338
+ result.valid_check? # => true
339
+ result.valid_invariants? # => false
340
+
341
+ # invariant errors:
342
+ result.errors # => ['String.password.should_have_numbers']
343
+ # -- same as: ---
344
+ result.invariant_errors
345
+ # -- same as: ---
346
+ result.error_codes
347
+ ```
348
+
349
+ ```ruby
350
+ result = SmartCore::Types::Value::String.validate('test1234')
351
+ result.success? # => true
352
+ result.errors # => []
353
+ ```
354
+
355
+ ```ruby
356
+ SmartCore::Types::Value::String.validate!('test') # => SmartCore::Types::TypeError
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Type casting
362
+
363
+ ```ruby
364
+ SmartCore::Types::Value::String.cast(123) # => "123"
365
+ SmartCore::Types::Value::Float.cast('55') # => 55.0
366
+ ```
367
+
125
368
  ---
126
369
 
127
370
  ## Basic type algebra
128
371
 
372
+ > (type sum and type multiplication does not support invariants at this moment (in development yet));
373
+
129
374
  ```ruby
130
375
  # documentation is coming
376
+
377
+ # how to define primitive type sum:
378
+ SmartCore::Types::Value::Text = SmartCore::Types::Value::String | SmartCore::Types::Value::Symbol
379
+ SmartCore::Types::Value::Numeric = SmartCore::Types::Value::Float | SmartCore::Types::Value::Integer
380
+
381
+ # how to define primitive type multiplication:
382
+ SmartCore::Types::Value::CryptoString = SmartCore::Types::Value::NumberdString & SmartCore::Types::Value::SymbolicString
131
383
  ```
132
384
 
133
385
  ---
134
386
 
135
387
  ## Roadmap
136
388
 
389
+ - migrate to `Github Actions`;
390
+
391
+ - support for `block`-attribute in runtime attributes;
392
+
137
393
  - type configuration:
138
394
 
139
395
  ```ruby
@@ -195,6 +451,18 @@ end
195
451
  SmartCore::Types::Value::Time.refine_caster do |value, original_caster|
196
452
  # new type caster
197
453
  end
454
+
455
+ SmartCore::Types::Value::Time.refine_runtime_attributes_checker do |value, original_checker|
456
+ # new runtime attribute checker
457
+ end
458
+
459
+ SmartCore::Types::Value::Time.refine_invariant(:name) do |value|
460
+ # new invariant
461
+ end
462
+
463
+ SmartCore::Types::Value::Time.refine_invariant_chain(:chain_name) do
464
+ # new invariant chain
465
+ end
198
466
  ```
199
467
 
200
468
  - options for type casters:
@@ -218,23 +486,52 @@ SmartCore::Types::Value::Method
218
486
  SmartCore::Types::Value::UnboundMethod
219
487
  SmartCore::Types::Value::Enumerable
220
488
  SmartCore::Types::Value::Comparable
489
+ SmartCore::Types::Value::Enumerator
490
+ SmartCore::Types::Value::EnumeratorChain
491
+ SmartCore::Types::Value::Range
492
+ SmartCore::Types::Value::Rational
493
+ SmartCore::Types::Value::SortedSet
494
+ SmartCore::Types::Value::IO
495
+ SmartCore::Types::Value::StringIO
496
+ SmartCore::Types::Value::BasicObject
221
497
  SmartCore::Types::Struct::Schema
498
+ SmartCore::Types::Struct::JSONSchema
222
499
  SmartCore::Types::Struct::StrictArray
223
500
  SmartCore::Types::Struct::StrictHash
224
501
  SmartCore::Types::Struct::Map
225
- SmartCore::Types::Variative::Enum
226
- SmartCore::Types::Variative::Variant
227
- SmartCore::Types::Protocol::InstanceOf
228
502
  SmartCore::Types::Protocol::Interface
229
503
  SmartCore::Types::Protocol::Ancestors
230
504
  SmartCore::Types::Protocol::Enumerable
231
505
  SmartCore::Types::Protocol::Comparable
232
506
  SmartCore::Types::Protocol::Forwardable
507
+ SmartCore::Types::Protocol::Callable
233
508
  ```
234
509
 
235
- - constrained types;
510
+ - `#sum` alias for `|` and `#mult` alias for `&` (with a support for type name definition and other API);
236
511
 
237
- - module-based integration;
512
+ - type category in invariant error codes:
513
+ ```ruby
514
+ # before:
515
+ 'String.password.should_contain_numbers' # `String` type from `Value` category
516
+
517
+ # after:
518
+ 'Value.String.password.should_contain_numbers' # `Value::String`
519
+ ```
520
+
521
+ - support for type of empty non-defined type (`SmartCore::Types::Primitive::Undefined`);
522
+ - constrained types;
523
+ - moudle-based type system integration;
524
+ - constructor implementation and support;
525
+ - support for invariant checking (and custom definitioning) in sum-types;
526
+ - to provide a type comparability and compatability between all passed types
527
+ you should provide `type.reconcilable { |value, *types| .... }` setting;
528
+ - `type.reconcilable` should be accesible for type sum and type mult definitions;
529
+ - (**preliminarily**) invariants of the concrete passed type should be valid for sucessful invariant check;
530
+ - support for invariant checking (and definitioning) in mult-types;
531
+ - to provide a type comparability and compatability between all passed types
532
+ you should provide `type.reconcilable { |value, *types| .... }` setting;
533
+ - `type.reconcilable` should be accesible for type sum and type mult definitions;
534
+ - (**preliminarily**) all invariants of all types should be valid for sucessful invariant check;
238
535
 
239
536
  ## Contributing
240
537
 
@@ -244,10 +541,42 @@ SmartCore::Types::Protocol::Forwardable
244
541
  - Push to the branch (`git push origin feature/my-new-feature`)
245
542
  - Create new Pull Request
246
543
 
544
+ ## Build
545
+
546
+ - run tests:
547
+
548
+ ```shell
549
+ bundle exec rake rspec
550
+ # --- or ---
551
+ bundle exec rspec
552
+ ```
553
+
554
+ - run code stye linting:
555
+
556
+ ```shell
557
+ bundle exec rake rubocop
558
+ # --- or ---
559
+ bundle exec rubocop
560
+ ```
561
+
562
+ - run code style linting with auto-correction:
563
+
564
+ ```shell
565
+ bundle exec rake rubcoop -A
566
+ # --- or ---
567
+ bundle exec rubocop -A
568
+ ```
569
+
247
570
  ## License
248
571
 
249
572
  Released under MIT License.
250
573
 
574
+ ## Supporting
575
+
576
+ <a href="https://github.com/Cado-Labs">
577
+ <img src="https://github.com/Cado-Labs/cado-labs-logos/blob/main/cado_labs_logo.png" alt="Supported by Cado Labs" />
578
+ </a>
579
+
251
580
  ## Authors
252
581
 
253
582
  [Rustam Ibragimov](https://github.com/0exp)