nrser 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
- data/lib/nrser/char.rb +0 -6
- data/lib/nrser/core_ext/array.rb +120 -0
- data/lib/nrser/core_ext/binding.rb +44 -0
- data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
- data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
- data/lib/nrser/core_ext/exception.rb +30 -0
- data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
- data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
- data/lib/nrser/core_ext/hash.rb +50 -0
- data/lib/nrser/core_ext/module/method_objects.rb +96 -0
- data/lib/nrser/core_ext/module/names.rb +69 -0
- data/lib/nrser/core_ext/module/source_locations.rb +214 -0
- data/lib/nrser/core_ext/module.rb +2 -0
- data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
- data/lib/nrser/core_ext/object.rb +46 -0
- data/lib/nrser/core_ext/open_struct.rb +6 -0
- data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
- data/lib/nrser/{ext → core_ext}/string.rb +6 -12
- data/lib/nrser/core_ext/symbol.rb +13 -0
- data/lib/nrser/core_ext/time.rb +46 -0
- data/lib/nrser/core_ext.rb +13 -0
- data/lib/nrser/errors/abstract_method_error.rb +150 -0
- data/lib/nrser/errors/argument_error.rb +42 -0
- data/lib/nrser/errors/nicer_error.rb +298 -72
- data/lib/nrser/errors/type_error.rb +46 -0
- data/lib/nrser/errors.rb +4 -53
- data/lib/nrser/ext/tree.rb +3 -0
- data/lib/nrser/functions/enumerable/associate.rb +6 -9
- data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
- data/lib/nrser/functions/enumerable.rb +1 -3
- data/lib/nrser/functions/exception.rb +1 -1
- data/lib/nrser/functions/hash.rb +0 -6
- data/lib/nrser/functions/merge_by.rb +2 -2
- data/lib/nrser/functions/module/method_objects.rb +77 -0
- data/lib/nrser/functions/module.rb +1 -2
- data/lib/nrser/functions/open_struct.rb +25 -35
- data/lib/nrser/functions/proc.rb +1 -6
- data/lib/nrser/functions/string/looks_like.rb +32 -1
- data/lib/nrser/functions/string.rb +1 -40
- data/lib/nrser/functions/text/lines.rb +2 -1
- data/lib/nrser/functions.rb +0 -1
- data/lib/nrser/graph/tsorter.rb +41 -0
- data/lib/nrser/labs/core_ext/binding.rb +37 -0
- data/lib/nrser/labs/stash.rb +372 -0
- data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
- data/lib/nrser/log/appender.rb +3 -0
- data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
- data/lib/nrser/log/formatters/mixin.rb +270 -0
- data/lib/nrser/{logging → log}/formatters.rb +0 -0
- data/lib/nrser/log/logger.rb +229 -0
- data/lib/nrser/log/mixin.rb +56 -0
- data/lib/nrser/log.rb +723 -0
- data/lib/nrser/message.rb +24 -3
- data/lib/nrser/meta/source/location.rb +158 -0
- data/lib/nrser/meta.rb +1 -1
- data/lib/nrser/props/class_methods.rb +118 -0
- data/lib/nrser/props/immutable/hash.rb +111 -0
- data/lib/nrser/props/immutable/hash_variable.rb +82 -0
- data/lib/nrser/props/immutable/instance_variables.rb +48 -0
- data/lib/nrser/props/immutable/vector.rb +107 -0
- data/lib/nrser/props/instance_methods.rb +184 -0
- data/lib/nrser/props/metadata.rb +359 -0
- data/lib/nrser/props/mutable/instance_variables.rb +60 -0
- data/lib/nrser/props/mutable/stash.rb +199 -0
- data/lib/nrser/{meta/props → props}/prop.rb +217 -112
- data/lib/nrser/props/storage/instance_variable.rb +85 -0
- data/lib/nrser/props/storage/instance_variables.rb +67 -0
- data/lib/nrser/props/storage/key.rb +88 -0
- data/lib/nrser/props.rb +9 -0
- data/lib/nrser/refinements/sugar.rb +41 -0
- data/lib/nrser/refinements/types.rb +2 -2
- data/lib/nrser/refinements.rb +14 -16
- data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
- data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
- data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
- data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
- data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
- data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
- data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
- data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
- data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
- data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
- data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
- data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
- data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
- data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
- data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
- data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
- data/lib/nrser/rspex/example_group/overrides.rb +66 -0
- data/lib/nrser/rspex/example_group.rb +20 -252
- data/lib/nrser/rspex/format.rb +83 -17
- data/lib/nrser/rspex.rb +4 -34
- data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
- data/lib/nrser/{env → sys/env}/path.rb +1 -2
- data/lib/nrser/{env.rb → sys/env.rb} +2 -1
- data/lib/nrser/sys.rb +5 -0
- data/lib/nrser/types/any.rb +36 -7
- data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
- data/lib/nrser/types/attrs.rb +68 -15
- data/lib/nrser/types/booleans.rb +95 -34
- data/lib/nrser/types/bounded.rb +12 -10
- data/lib/nrser/types/combinators.rb +74 -37
- data/lib/nrser/types/errors/check_error.rb +86 -0
- data/lib/nrser/types/errors/from_string_error.rb +82 -0
- data/lib/nrser/types/factory.rb +91 -0
- data/lib/nrser/types/hashes.rb +171 -26
- data/lib/nrser/types/in.rb +25 -12
- data/lib/nrser/types/is.rb +50 -18
- data/lib/nrser/types/is_a.rb +52 -33
- data/lib/nrser/types/labels.rb +6 -33
- data/lib/nrser/types/maybe.rb +12 -4
- data/lib/nrser/types/nil.rb +24 -4
- data/lib/nrser/types/not.rb +6 -16
- data/lib/nrser/types/numbers.rb +94 -57
- data/lib/nrser/types/pairs.rb +57 -57
- data/lib/nrser/types/paths.rb +112 -133
- data/lib/nrser/types/responds.rb +64 -74
- data/lib/nrser/types/shape.rb +29 -24
- data/lib/nrser/types/strings.rb +25 -17
- data/lib/nrser/types/symbols.rb +19 -17
- data/lib/nrser/types/trees.rb +18 -70
- data/lib/nrser/types/tuples.rb +36 -40
- data/lib/nrser/types/type.rb +342 -91
- data/lib/nrser/types/when.rb +40 -18
- data/lib/nrser/types/where.rb +94 -9
- data/lib/nrser/types.rb +72 -63
- data/lib/nrser/version.rb +1 -1
- data/lib/nrser.rb +18 -18
- data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
- data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
- data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
- data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
- data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
- data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
- data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
- data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
- data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
- data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
- data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
- data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
- data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
- data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
- data/spec/lib/nrser/refinements/array_spec.rb +2 -15
- data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
- data/spec/lib/nrser/refinements/set_spec.rb +2 -15
- data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
- data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
- data/spec/lib/nrser/types/array_spec.rb +8 -8
- data/spec/lib/nrser/types/paths_spec.rb +15 -18
- data/spec/spec_helper.rb +4 -0
- metadata +109 -69
- data/lib/nrser/ext/binding.rb +0 -36
- data/lib/nrser/ext/module.rb +0 -62
- data/lib/nrser/ext.rb +0 -8
- data/lib/nrser/functions/binding.rb +0 -76
- data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
- data/lib/nrser/functions/enumerable/map_values.rb +0 -94
- data/lib/nrser/functions/hash/deep_merge.rb +0 -57
- data/lib/nrser/functions/hash/except_keys.rb +0 -44
- data/lib/nrser/functions/hash/slice_keys.rb +0 -43
- data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
- data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
- data/lib/nrser/functions/hash/transform_keys.rb +0 -140
- data/lib/nrser/functions/module/methods.rb +0 -206
- data/lib/nrser/functions/module/source_locations.rb +0 -213
- data/lib/nrser/logging/appender.rb +0 -3
- data/lib/nrser/logging.rb +0 -353
- data/lib/nrser/meta/props/base.rb +0 -31
- data/lib/nrser/meta/props.rb +0 -357
- data/lib/nrser/refinements/array.rb +0 -133
- data/lib/nrser/refinements/binding.rb +0 -6
- data/lib/nrser/refinements/enumerator.rb +0 -5
- data/lib/nrser/refinements/exception.rb +0 -35
- data/lib/nrser/refinements/hash.rb +0 -150
- data/lib/nrser/refinements/module.rb +0 -5
- data/lib/nrser/refinements/object.rb +0 -42
- data/lib/nrser/refinements/open_struct.rb +0 -28
- data/lib/nrser/refinements/pathname.rb +0 -5
- data/lib/nrser/refinements/set.rb +0 -5
- data/lib/nrser/refinements/string.rb +0 -5
- data/lib/nrser/refinements/symbol.rb +0 -20
- data/lib/nrser/rspex/described.rb +0 -99
- data/spec/design/mapping_spec.rb +0 -42
- data/spec/lib/nrser/functions/hash_spec.rb +0 -41
- data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
- data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -1,29 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
# Requirements
|
2
5
|
# =======================================================================
|
3
6
|
|
4
|
-
# Stdlib
|
5
|
-
# -----------------------------------------------------------------------
|
6
|
-
|
7
|
-
# Deps
|
8
|
-
# -----------------------------------------------------------------------
|
9
|
-
|
10
7
|
# Project / Package
|
11
8
|
# -----------------------------------------------------------------------
|
12
|
-
require 'nrser/types/type'
|
13
|
-
require 'nrser/types/is_a'
|
14
|
-
|
15
|
-
|
16
|
-
# Refinements
|
17
|
-
# =======================================================================
|
18
|
-
|
19
|
-
require 'nrser/refinements'
|
20
|
-
using NRSER
|
21
9
|
|
22
|
-
|
23
|
-
# Declarations
|
24
|
-
# =======================================================================
|
25
|
-
|
26
|
-
module NRSER; end
|
10
|
+
require_relative './is_a'
|
27
11
|
|
28
12
|
|
29
13
|
# Definitions
|
@@ -36,25 +20,16 @@ module NRSER::Types
|
|
36
20
|
# does is not recognized as an encoding format (as of writing, JSON is
|
37
21
|
# the only format we attempt to detect).
|
38
22
|
#
|
39
|
-
# Splits
|
23
|
+
# Splits
|
40
24
|
DEFAULT_SPLIT_WITH = /\,\s*/m
|
41
25
|
|
42
|
-
attr_reader :item_type
|
43
|
-
|
44
26
|
def initialize split_with: DEFAULT_SPLIT_WITH, **options
|
45
27
|
super ::Array, **options
|
46
28
|
@split_with = split_with
|
47
29
|
end
|
48
30
|
|
49
31
|
|
50
|
-
def
|
51
|
-
self.class.short_name
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def item_type
|
56
|
-
NRSER::Types.any
|
57
|
-
end
|
32
|
+
def item_type; NRSER::Types.any; end
|
58
33
|
|
59
34
|
|
60
35
|
# Called on an array of string items that have been split
|
@@ -73,40 +48,29 @@ module NRSER::Types
|
|
73
48
|
end
|
74
49
|
|
75
50
|
|
76
|
-
def
|
77
|
-
# Use custom {@from_s} if we have one.
|
78
|
-
return check( @from_s.call s ) unless @from_s.nil?
|
79
|
-
|
51
|
+
def custom_from_s string
|
80
52
|
# Does it looks like a JSON array?
|
81
|
-
if NRSER.looks_like_json_array?
|
53
|
+
if NRSER.looks_like_json_array? string
|
82
54
|
# It does! Load it
|
83
55
|
begin
|
84
|
-
|
56
|
+
return JSON.load( string )
|
85
57
|
rescue
|
86
58
|
# pass - if we failed to load as JSON, it may just not be JSON, and
|
87
59
|
# we can try the split approach below.
|
88
|
-
else
|
89
|
-
# Check value and return. If we fail the check here let the error
|
90
|
-
# bubble up
|
91
|
-
return check array
|
92
60
|
end
|
93
61
|
end
|
94
62
|
|
95
63
|
# Split it with the splitter and check that
|
96
|
-
|
64
|
+
items_from_strings( string.split( @split_with ) )
|
97
65
|
end
|
98
66
|
|
99
67
|
end # ArrayType
|
100
68
|
|
101
69
|
|
102
|
-
# Static instance that is satisfied by anything that is an {Array}.
|
103
|
-
ARRAY = ArrayType.new.freeze
|
104
|
-
|
105
|
-
|
106
70
|
# Type for arrays where every entry satisfies a specific type.
|
107
71
|
#
|
108
72
|
# Broken out from {ArrayType} so that {TupleType} can inherit from
|
109
|
-
# {ArrayType} and get share it's string handling functionality without
|
73
|
+
# {ArrayType} and get share it's string handling functionality without
|
110
74
|
# receiving the entry type stuff (which it handles differently).
|
111
75
|
#
|
112
76
|
class ArrayOfType < ArrayType
|
@@ -135,12 +99,12 @@ module NRSER::Types
|
|
135
99
|
# Instance Methods
|
136
100
|
# ======================================================================
|
137
101
|
|
138
|
-
def
|
139
|
-
"#{ super() }<#{
|
102
|
+
def explain
|
103
|
+
"#{ super() }<#{ item_type.explain }>"
|
140
104
|
end
|
141
105
|
|
142
106
|
|
143
|
-
def test value
|
107
|
+
def test? value
|
144
108
|
# Check the super method first, which will test if `value` is an Array
|
145
109
|
# instance, and return `false` if it's not.
|
146
110
|
return false unless super( value )
|
@@ -156,7 +120,7 @@ module NRSER::Types
|
|
156
120
|
# @return [Boolean]
|
157
121
|
#
|
158
122
|
def has_from_s?
|
159
|
-
@item_type.has_from_s?
|
123
|
+
@from_s || @item_type.has_from_s?
|
160
124
|
end
|
161
125
|
|
162
126
|
|
@@ -168,7 +132,7 @@ module NRSER::Types
|
|
168
132
|
# @todo
|
169
133
|
# I'm not even sure why this is implemented... was it used somewhere?
|
170
134
|
#
|
171
|
-
# It doesn't seems too well thought out... seems like the reality of
|
135
|
+
# It doesn't seems too well thought out... seems like the reality of
|
172
136
|
# comparing types is much more complicated?
|
173
137
|
#
|
174
138
|
def == other
|
@@ -180,35 +144,22 @@ module NRSER::Types
|
|
180
144
|
end # class ArrayOfType
|
181
145
|
|
182
146
|
|
183
|
-
#
|
184
|
-
# ========================================================================
|
147
|
+
# {NRSER::Types::ArrayType} / {NRSER::Types::ArrayOfType} factory function.
|
185
148
|
#
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
else
|
202
|
-
ArrayType.new **options
|
203
|
-
end
|
204
|
-
else
|
205
|
-
ArrayOfType.new item_type, **options
|
206
|
-
end
|
207
|
-
end # #array
|
208
|
-
|
209
|
-
alias_method :list, :array
|
210
|
-
|
211
|
-
end # class << self (Eigenclass)
|
212
|
-
|
149
|
+
# @param [Type | Object] item_type
|
150
|
+
# Optional type of items.
|
151
|
+
#
|
152
|
+
# @return [NRSER::Types::Type]
|
153
|
+
#
|
154
|
+
def_factory(
|
155
|
+
:array,
|
156
|
+
aliases: [:list],
|
157
|
+
) do |item_type = any, **options|
|
158
|
+
if item_type == any
|
159
|
+
ArrayType.new **options
|
160
|
+
else
|
161
|
+
ArrayOfType.new item_type, **options
|
162
|
+
end
|
163
|
+
end # #array
|
213
164
|
|
214
165
|
end # NRSER::Types
|
data/lib/nrser/types/attrs.rb
CHANGED
@@ -1,11 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'nrser/types/combinators'
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
4
3
|
|
5
|
-
|
4
|
+
|
5
|
+
# Requirements
|
6
|
+
# ========================================================================
|
7
|
+
|
8
|
+
# Project / Package
|
9
|
+
# ------------------------------------------------------------------------
|
10
|
+
|
11
|
+
require 'nrser/core_ext/hash'
|
12
|
+
|
13
|
+
require_relative './type'
|
14
|
+
require_relative './combinators'
|
15
|
+
require_relative './is'
|
16
|
+
|
17
|
+
|
18
|
+
# Definitions
|
19
|
+
# ========================================================================
|
6
20
|
|
7
21
|
module NRSER::Types
|
8
|
-
|
22
|
+
|
23
|
+
# Specify types for value attributes.
|
24
|
+
#
|
25
|
+
class AttrsType < NRSER::Types::Type
|
26
|
+
|
27
|
+
# Construct an `AttrsType`.
|
28
|
+
#
|
29
|
+
# @param [Hash<Symbol, TYPE>] attrs
|
30
|
+
# Map of attribute names to their types (`TYPE` values will be passed
|
31
|
+
# through {NRSER::Types.make} to get a type instance).
|
32
|
+
#
|
33
|
+
# May not be empty.
|
34
|
+
#
|
9
35
|
def initialize attrs, **options
|
10
36
|
super **options
|
11
37
|
|
@@ -14,12 +40,15 @@ module NRSER::Types
|
|
14
40
|
"Must provide at least one attribute name/type pair"
|
15
41
|
end
|
16
42
|
|
17
|
-
@attrs = NRSER.
|
18
|
-
NRSER::Types.make type
|
19
|
-
}
|
43
|
+
@attrs = attrs.transform_values &NRSER::Types.maker
|
20
44
|
end
|
21
45
|
|
22
|
-
|
46
|
+
|
47
|
+
# @see NRSER::Types::Type#explain
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
#
|
51
|
+
def explain
|
23
52
|
attrs_str = @attrs.map { |name, type|
|
24
53
|
"##{ name }#{ RESPONDS_WITH }#{ type.name }"
|
25
54
|
}.join(', ')
|
@@ -31,12 +60,19 @@ module NRSER::Types
|
|
31
60
|
end
|
32
61
|
end
|
33
62
|
|
34
|
-
|
63
|
+
|
64
|
+
# @see NRSER::Types::Type#test
|
65
|
+
#
|
66
|
+
# @return [Boolean]
|
67
|
+
#
|
68
|
+
def test? value
|
35
69
|
@attrs.all? { |name, type|
|
36
|
-
value.respond_to?(name) &&
|
70
|
+
value.respond_to?( name ) &&
|
71
|
+
type.test?( value.method( name ).call )
|
37
72
|
}
|
38
73
|
end
|
39
|
-
|
74
|
+
|
75
|
+
end # AttrsType
|
40
76
|
|
41
77
|
|
42
78
|
# @!group Type Factory Functions
|
@@ -46,8 +82,20 @@ module NRSER::Types
|
|
46
82
|
# @example Type where first element of an Enumerable is a String
|
47
83
|
# string_first = intersection Enumerable, attrs(first: String)
|
48
84
|
#
|
49
|
-
def_factory :attrs do |
|
50
|
-
|
85
|
+
def_factory :attrs do |*args|
|
86
|
+
case args.length
|
87
|
+
when 0
|
88
|
+
raise NRSER::ArgumentError.new \
|
89
|
+
"requires at least one argument"
|
90
|
+
when 1
|
91
|
+
attrs = args[0]
|
92
|
+
options = {}
|
93
|
+
when 2
|
94
|
+
attrs = args[0]
|
95
|
+
options = args[1]
|
96
|
+
end
|
97
|
+
|
98
|
+
AttrsType.new attrs, **options
|
51
99
|
end
|
52
100
|
|
53
101
|
|
@@ -114,11 +162,16 @@ module NRSER::Types
|
|
114
162
|
case args[0]
|
115
163
|
when ::Integer
|
116
164
|
# It's just a length
|
165
|
+
return attrs(
|
166
|
+
{ length: is( non_neg_int.check!( args[0] ) ) },
|
167
|
+
**options
|
168
|
+
)
|
169
|
+
|
117
170
|
bounds[:min] = bounds[:max] = non_neg_int.check args[0]
|
118
171
|
|
119
172
|
when ::Hash
|
120
173
|
# It's keyword args
|
121
|
-
kwds =
|
174
|
+
kwds = args[0].sym_keys
|
122
175
|
|
123
176
|
# Pull any :min and :max in the keywords
|
124
177
|
bounds[:min] = kwds.delete :min
|
data/lib/nrser/types/booleans.rb
CHANGED
@@ -1,47 +1,108 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Need truthy and falsy parse values
|
5
|
+
require 'nrser/functions/object/truthy'
|
6
|
+
|
7
|
+
require_relative './type'
|
8
|
+
require_relative './is'
|
9
|
+
require_relative './combinators'
|
5
10
|
|
6
|
-
using NRSER
|
7
11
|
|
8
12
|
module NRSER::Types
|
9
|
-
# booleans
|
10
|
-
# ========
|
11
|
-
|
12
|
-
TRUE = is true, name: 'true', from_s: ->(string) {
|
13
|
-
if ['true', 't', '1', 'yes', 'y', 'on'].include? string.downcase
|
14
|
-
true
|
15
|
-
else
|
16
|
-
raise TypeError, "can not convert to true: #{ string.inspect }"
|
17
|
-
end
|
18
|
-
}
|
19
|
-
|
20
|
-
def self.true
|
21
|
-
TRUE
|
22
|
-
end
|
23
13
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
14
|
+
# Abstract base class for {TrueType} and {FalseType}.
|
15
|
+
#
|
16
|
+
class BooleanType < Is
|
17
|
+
|
18
|
+
# Instantiate a new `BooleanType`.
|
19
|
+
#
|
20
|
+
def initialize value, **options
|
21
|
+
# Check it's a boolean
|
22
|
+
unless true.equal?( value ) || false.equal?( value )
|
23
|
+
raise ArgumentError.new \
|
24
|
+
"`value` arg must be `true` or `false`, found #{ value.inspect }"
|
25
|
+
end
|
26
|
+
|
27
|
+
super value, **options
|
28
|
+
end # #initialize
|
29
|
+
|
30
|
+
|
31
|
+
protected
|
32
|
+
# ========================================================================
|
33
|
+
|
34
|
+
def custom_from_s string
|
35
|
+
return value if self::STRINGS.include?( string.downcase )
|
36
|
+
|
37
|
+
raise NRSER::Types::FromStringError.new \
|
38
|
+
type: self,
|
39
|
+
string: string,
|
40
|
+
binding: binding,
|
41
|
+
details: -> {
|
42
|
+
<<~END
|
43
|
+
Down-cased `string` must be one of:
|
44
|
+
|
45
|
+
<%= self::STRINGS.to_a %>
|
46
|
+
END
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
public # end protected *****************************************************
|
51
|
+
|
52
|
+
end # class TrueType
|
53
|
+
|
54
|
+
|
55
|
+
# A type for only the `true`.
|
56
|
+
#
|
57
|
+
# Provides a {#custom_from_s} to load from CLI options and ENV var-like
|
58
|
+
# string values.
|
59
|
+
#
|
60
|
+
class TrueType < BooleanType
|
61
|
+
|
62
|
+
STRINGS = NRSER::TRUTHY_STRINGS
|
63
|
+
|
64
|
+
# Instantiate a new `TrueType`.
|
65
|
+
#
|
66
|
+
def initialize **options
|
67
|
+
super true, **options
|
68
|
+
end # #initialize
|
69
|
+
|
70
|
+
end # class TrueType
|
31
71
|
|
32
|
-
|
33
|
-
|
72
|
+
|
73
|
+
# A type for only `false`.
|
74
|
+
#
|
75
|
+
# Provides a {#custom_from_s} to load from CLI options and ENV var-like
|
76
|
+
# string values.
|
77
|
+
#
|
78
|
+
class FalseType < BooleanType
|
79
|
+
|
80
|
+
STRINGS = NRSER::FALSY_STRINGS
|
81
|
+
|
82
|
+
# Instantiate a new `TrueType`.
|
83
|
+
#
|
84
|
+
def initialize **options
|
85
|
+
super false, **options
|
86
|
+
end # #initialize
|
87
|
+
|
88
|
+
end # class FalseType
|
89
|
+
|
90
|
+
|
91
|
+
def_factory :true do |**options|
|
92
|
+
TrueType.new **options
|
34
93
|
end
|
35
94
|
|
36
|
-
BOOL = union TRUE, FALSE
|
37
95
|
|
38
|
-
|
39
|
-
|
40
|
-
BOOL
|
96
|
+
def_factory :false do |**options|
|
97
|
+
FalseType.new **options
|
41
98
|
end
|
42
99
|
|
43
|
-
|
44
|
-
|
100
|
+
|
101
|
+
def_factory(
|
102
|
+
:bool,
|
103
|
+
aliases: [ :boolean ],
|
104
|
+
) do |**options|
|
105
|
+
union self.true, self.false, **options
|
45
106
|
end
|
46
107
|
|
47
108
|
end # NRSER::Types
|
data/lib/nrser/types/bounded.rb
CHANGED
@@ -6,15 +6,17 @@ using NRSER
|
|
6
6
|
module NRSER::Types
|
7
7
|
class Bounded < NRSER::Types::Type
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# Minimum value.
|
10
|
+
#
|
11
|
+
# @return [Number]
|
12
|
+
#
|
12
13
|
attr_reader :min
|
13
14
|
|
14
15
|
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
16
|
+
# Minimum value.
|
17
|
+
#
|
18
|
+
# @return [Number]
|
19
|
+
#
|
18
20
|
attr_reader :max
|
19
21
|
|
20
22
|
|
@@ -27,13 +29,13 @@ module NRSER::Types
|
|
27
29
|
@max = max
|
28
30
|
end
|
29
31
|
|
30
|
-
def test value
|
32
|
+
def test? value
|
31
33
|
return false if @min && value < @min
|
32
34
|
return false if @max && value > @max
|
33
35
|
true
|
34
36
|
end
|
35
37
|
|
36
|
-
def
|
38
|
+
def explain
|
37
39
|
attrs_str = ['min', 'max'].map {|name|
|
38
40
|
[name, instance_variable_get("@#{ name }")]
|
39
41
|
}.reject {|name, value|
|
@@ -42,12 +44,12 @@ module NRSER::Types
|
|
42
44
|
"#{ name }=#{ value }"
|
43
45
|
}.join(', ')
|
44
46
|
|
45
|
-
"#{ self.class.
|
47
|
+
"#{ self.class.demod_name }<#{ attrs_str }>"
|
46
48
|
end
|
47
49
|
|
48
50
|
end # Bounded
|
49
51
|
|
50
|
-
|
52
|
+
def_factory :bounded do |**options|
|
51
53
|
Bounded.new **options
|
52
54
|
end
|
53
55
|
|
@@ -1,31 +1,37 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require 'nrser/refinements'
|
5
4
|
require 'nrser/types/type'
|
6
5
|
|
7
|
-
using NRSER
|
8
|
-
|
9
6
|
# base class for Union and Intersection which combine over a set of types.
|
10
7
|
module NRSER::Types
|
8
|
+
|
9
|
+
# Abstract base class for logically combining types to create new ones.
|
10
|
+
#
|
11
11
|
class Combinator < NRSER::Types::Type
|
12
|
+
|
13
|
+
# The parametrized types, in the order they will be tested.
|
14
|
+
#
|
15
|
+
# @return [Array<NRSER::Types::Type>]
|
16
|
+
#
|
12
17
|
attr_reader :types
|
13
18
|
|
14
19
|
|
15
20
|
def initialize *types, **options
|
16
21
|
super **options
|
17
|
-
@types = types.map {|type| NRSER::Types.make type}
|
22
|
+
@types = types.map { |type| NRSER::Types.make type }
|
18
23
|
end
|
19
24
|
|
20
25
|
|
21
|
-
def
|
26
|
+
def explain
|
22
27
|
if self.class::JOIN_SYMBOL
|
23
|
-
NRSER::Types::L_PAREN +
|
24
|
-
@types.map { |type| type.
|
28
|
+
NRSER::Types::L_PAREN + # ' ' +
|
29
|
+
@types.map { |type| type.explain }.join( self.class::JOIN_SYMBOL ) +
|
30
|
+
# ' ' +
|
25
31
|
NRSER::Types::R_PAREN
|
26
32
|
else
|
27
|
-
"#{ self.class.
|
28
|
-
|
33
|
+
"#{ self.class.demod_name }<" +
|
34
|
+
@types.map { |type| type.explain }.join( ',' ) +
|
29
35
|
">"
|
30
36
|
end
|
31
37
|
end
|
@@ -59,7 +65,7 @@ module NRSER::Types
|
|
59
65
|
# @raise [TypeError]
|
60
66
|
# See write up above.
|
61
67
|
#
|
62
|
-
def
|
68
|
+
def custom_from_s s
|
63
69
|
unless @from_s.nil?
|
64
70
|
return check @from_s.call( s )
|
65
71
|
end
|
@@ -92,10 +98,39 @@ module NRSER::Types
|
|
92
98
|
# @return [Boolean]
|
93
99
|
#
|
94
100
|
def has_from_s?
|
95
|
-
|
101
|
+
!@from_s.nil? || @types.any? { |type| type.has_from_s? }
|
96
102
|
end # has_from_s
|
97
103
|
|
98
104
|
|
105
|
+
def has_from_data?
|
106
|
+
@types.any? { |type| type.has_from_data? }
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Overridden to
|
111
|
+
def from_data data
|
112
|
+
unless has_from_data?
|
113
|
+
raise NoMethodError, "#from_data not defined"
|
114
|
+
end
|
115
|
+
|
116
|
+
errors = []
|
117
|
+
|
118
|
+
types.each do |type|
|
119
|
+
if type.has_from_data?
|
120
|
+
begin
|
121
|
+
return check!( type.from_data data )
|
122
|
+
rescue Exception => error
|
123
|
+
errors << error
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
raise NRSER::MultipleErrors.new \
|
129
|
+
errors,
|
130
|
+
headline: "No type successfully loaded data"
|
131
|
+
end
|
132
|
+
|
133
|
+
|
99
134
|
# Overridden to delegate functionality to the combined types:
|
100
135
|
#
|
101
136
|
# A combinator can convert a value to data if *any* of it's types can.
|
@@ -120,7 +155,7 @@ module NRSER::Types
|
|
120
155
|
#
|
121
156
|
def to_data value
|
122
157
|
@types.each { |type|
|
123
|
-
if type.
|
158
|
+
if type.has_to_data?
|
124
159
|
return type.to_data value
|
125
160
|
end
|
126
161
|
}
|
@@ -134,57 +169,59 @@ module NRSER::Types
|
|
134
169
|
other.class == self.class && other.types == @types
|
135
170
|
)
|
136
171
|
end
|
137
|
-
|
172
|
+
|
173
|
+
end # class Combinator
|
174
|
+
|
138
175
|
|
139
176
|
class Union < Combinator
|
140
|
-
JOIN_SYMBOL = ' ⋁ '
|
177
|
+
JOIN_SYMBOL = ' | ' # ' ⋁ '
|
141
178
|
|
142
|
-
def test value
|
143
|
-
@types.any? {|type| type.test value}
|
179
|
+
def test? value
|
180
|
+
@types.any? { |type| type.test value }
|
144
181
|
end
|
145
|
-
end # Union
|
182
|
+
end # class Union
|
183
|
+
|
146
184
|
|
147
185
|
# match any of the types
|
148
|
-
|
149
|
-
|
186
|
+
def_factory(
|
187
|
+
:union,
|
188
|
+
aliases: [:one_of, :or],
|
189
|
+
) do |*types, **options|
|
190
|
+
Union.new *types, **options
|
150
191
|
end
|
151
192
|
|
152
|
-
singleton_class.send :alias_method, :one_of, :union
|
153
|
-
singleton_class.send :alias_method, :or, :union
|
154
193
|
|
155
194
|
class Intersection < Combinator
|
156
|
-
|
157
|
-
JOIN_SYMBOL = ' ⋀ '
|
195
|
+
JOIN_SYMBOL = ' & ' # ' ⋀ '
|
158
196
|
|
159
|
-
def test value
|
160
|
-
@types.all? { |type| type.test value}
|
197
|
+
def test? value
|
198
|
+
@types.all? { |type| type.test? value }
|
161
199
|
end
|
162
|
-
end
|
200
|
+
end # class Intersection
|
201
|
+
|
163
202
|
|
164
203
|
# match all of the types
|
165
|
-
|
204
|
+
def_factory(
|
205
|
+
:intersection,
|
206
|
+
aliases: [:all_of, :and],
|
207
|
+
) do |*types, **options|
|
166
208
|
Intersection.new *types, **options
|
167
209
|
end
|
168
210
|
|
169
|
-
singleton_class.send :alias_method, :all_of, :intersection
|
170
|
-
singleton_class.send :alias_method, :and, :intersection
|
171
|
-
|
172
211
|
|
173
212
|
class XOR < Combinator
|
174
213
|
JOIN_SYMBOL = ' ⊕ '
|
175
214
|
|
176
|
-
def test value
|
215
|
+
def test? value
|
177
216
|
@types.count { |type| type === value } == 1
|
178
217
|
end
|
179
|
-
|
180
|
-
# def default_name
|
181
|
-
# '⊕'
|
182
|
-
# "( #{ @types.map { |t| t.name }.join ' ⊕ ' } )"
|
183
|
-
# end
|
184
218
|
end
|
185
219
|
|
186
220
|
|
187
|
-
|
221
|
+
def_factory(
|
222
|
+
:xor,
|
223
|
+
aliases: [ :exclusive_or, :only_one_of ],
|
224
|
+
) do |*types, **options|
|
188
225
|
XOR.new *types, **options
|
189
226
|
end
|
190
227
|
|