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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +57 -0
- data/Gemfile.lock +71 -58
- data/LICENSE.txt +1 -1
- data/README.md +363 -34
- data/Rakefile +0 -1
- data/bin/console +2 -2
- data/lib/smart_core/types/errors.rb +12 -0
- data/lib/smart_core/types/primitive/caster.rb +5 -2
- data/lib/smart_core/types/primitive/checker.rb +5 -2
- data/lib/smart_core/types/primitive/factory/definition_context.rb +140 -4
- data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
- data/lib/smart_core/types/primitive/factory.rb +104 -7
- data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
- data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
- data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
- data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
- data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
- data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
- data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
- data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
- data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +26 -2
- data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
- data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
- data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
- data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
- data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
- data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
- data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
- data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +25 -1
- data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
- data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
- data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
- data/lib/smart_core/types/primitive/undefined_caster.rb +4 -1
- data/lib/smart_core/types/primitive/validator/result.rb +78 -0
- data/lib/smart_core/types/primitive/validator.rb +93 -0
- data/lib/smart_core/types/primitive.rb +99 -15
- data/lib/smart_core/types/protocol/instance_of.rb +19 -0
- data/lib/smart_core/types/protocol.rb +7 -0
- data/lib/smart_core/types/value/array.rb +3 -0
- data/lib/smart_core/types/value/big_decimal.rb +4 -1
- data/lib/smart_core/types/value/boolean.rb +3 -0
- data/lib/smart_core/types/value/class.rb +3 -0
- data/lib/smart_core/types/value/date.rb +3 -0
- data/lib/smart_core/types/value/date_time.rb +3 -0
- data/lib/smart_core/types/value/enumerable.rb +1 -1
- data/lib/smart_core/types/value/enumerator.rb +13 -0
- data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
- data/lib/smart_core/types/value/float.rb +3 -0
- data/lib/smart_core/types/value/hash.rb +3 -0
- data/lib/smart_core/types/value/integer.rb +3 -0
- data/lib/smart_core/types/value/io.rb +13 -0
- data/lib/smart_core/types/value/method.rb +9 -0
- data/lib/smart_core/types/value/module.rb +3 -0
- data/lib/smart_core/types/value/nil.rb +0 -2
- data/lib/smart_core/types/value/numeric.rb +3 -0
- data/lib/smart_core/types/value/proc.rb +3 -0
- data/lib/smart_core/types/value/range.rb +9 -0
- data/lib/smart_core/types/value/rational.rb +13 -0
- data/lib/smart_core/types/value/set.rb +21 -0
- data/lib/smart_core/types/value/string.rb +3 -0
- data/lib/smart_core/types/value/string_io.rb +15 -0
- data/lib/smart_core/types/value/symbol.rb +3 -0
- data/lib/smart_core/types/value/text.rb +6 -4
- data/lib/smart_core/types/value/time.rb +3 -0
- data/lib/smart_core/types/value/time_based.rb +8 -5
- data/lib/smart_core/types/value/unbound_method.rb +9 -0
- data/lib/smart_core/types/value.rb +9 -0
- data/lib/smart_core/types/variadic/array_of.rb +23 -0
- data/lib/smart_core/types/variadic/enum.rb +11 -0
- data/lib/smart_core/types/variadic/tuple.rb +23 -0
- data/lib/smart_core/types/variadic.rb +10 -0
- data/lib/smart_core/types/version.rb +2 -1
- data/lib/smart_core/types.rb +2 -0
- data/smart_types.gemspec +5 -4
- metadata +61 -18
- data/.travis.yml +0 -21
- data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
- data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d46db58ce368955b324f4acb5fbfa74100789abe263c8e83fa8a73c482b6dd4
|
4
|
+
data.tar.gz: f5377e4cc8693855b885d197f1d5b8429ba78efc30b781703a2ba95230d58d2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
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.
|
5
|
-
smart_engine (~> 0.
|
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.
|
10
|
+
activesupport (6.1.1)
|
11
11
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
-
i18n (>=
|
13
|
-
minitest (
|
14
|
-
tzinfo (~>
|
15
|
-
zeitwerk (~> 2.
|
16
|
-
armitage-rubocop (
|
17
|
-
rubocop (=
|
18
|
-
rubocop-performance (= 1.
|
19
|
-
rubocop-rails (= 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.
|
22
|
-
ast (2.4.
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
minitest (5.14.
|
30
|
-
parallel (1.
|
31
|
-
parser (
|
32
|
-
ast (~> 2.4.
|
33
|
-
|
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.
|
39
|
+
rake (13.0.3)
|
40
|
+
regexp_parser (2.0.3)
|
36
41
|
rexml (3.2.4)
|
37
|
-
rspec (3.
|
38
|
-
rspec-core (~> 3.
|
39
|
-
rspec-expectations (~> 3.
|
40
|
-
rspec-mocks (~> 3.
|
41
|
-
rspec-core (3.
|
42
|
-
rspec-support (~> 3.
|
43
|
-
rspec-expectations (3.
|
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.
|
46
|
-
rspec-mocks (3.
|
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.
|
49
|
-
rspec-support (3.
|
50
|
-
rubocop (
|
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.
|
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-
|
59
|
-
|
60
|
-
rubocop-
|
61
|
-
|
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
|
+
rubocop (>= 0.90.0, < 2.0)
|
64
73
|
rubocop-rake (0.5.1)
|
65
74
|
rubocop
|
66
|
-
rubocop-rspec (1.
|
67
|
-
rubocop (
|
68
|
-
|
69
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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.
|
89
|
+
zeitwerk (2.4.2)
|
79
90
|
|
80
91
|
PLATFORMS
|
81
|
-
|
92
|
+
x86_64-darwin-19
|
93
|
+
x86_64-darwin-20
|
82
94
|
|
83
95
|
DEPENDENCIES
|
84
|
-
armitage-rubocop (~>
|
96
|
+
armitage-rubocop (~> 1.7)
|
85
97
|
bundler (~> 2.1)
|
98
|
+
pry (~> 0.13)
|
86
99
|
rake (~> 13.0)
|
87
|
-
rspec (~> 3.
|
88
|
-
simplecov (~> 0.
|
100
|
+
rspec (~> 3.10)
|
101
|
+
simplecov (~> 0.21)
|
89
102
|
smart_types!
|
90
103
|
|
91
104
|
BUNDLED WITH
|
92
|
-
2.
|
105
|
+
2.2.3
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# SmartCore::Types · [](https://github.com/Cado-Labs/) · [](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
|
-
##
|
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
|
-
|
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
|
-
|
115
|
+
#### Protocols:
|
69
116
|
|
70
117
|
```ruby
|
71
|
-
SmartCore::Types::
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
SmartCore::Types::
|
76
|
-
SmartCore::Types::
|
77
|
-
SmartCore::Types::
|
78
|
-
SmartCore::Types::
|
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
|
-
|
130
|
+
#### Variadic:
|
95
131
|
|
96
132
|
```ruby
|
97
|
-
|
133
|
+
SmartCore::Types::Variadic::ArrayOf
|
134
|
+
SmartCore::Types::Variadic::Enum
|
135
|
+
SmartCore::Types::Variadic::Tuple
|
136
|
+
```
|
98
137
|
|
99
|
-
|
100
|
-
SmartCore::Types::
|
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::
|
103
|
-
SmartCore::Types::
|
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
|
-
-
|
510
|
+
- `#sum` alias for `|` and `#mult` alias for `&` (with a support for type name definition and other API);
|
236
511
|
|
237
|
-
-
|
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)
|