nrser 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +1 -2
  3. data/lib/nrser/char.rb +0 -6
  4. data/lib/nrser/core_ext/array.rb +120 -0
  5. data/lib/nrser/core_ext/binding.rb +44 -0
  6. data/lib/nrser/{functions → core_ext}/enumerable/find_map.rb +18 -15
  7. data/lib/nrser/{ext → core_ext}/enumerable.rb +10 -24
  8. data/lib/nrser/core_ext/exception.rb +30 -0
  9. data/lib/nrser/core_ext/hash/extract_values_at.rb +49 -0
  10. data/lib/nrser/core_ext/hash/transform_values_with_keys.rb +24 -0
  11. data/lib/nrser/core_ext/hash.rb +50 -0
  12. data/lib/nrser/core_ext/module/method_objects.rb +96 -0
  13. data/lib/nrser/core_ext/module/names.rb +69 -0
  14. data/lib/nrser/core_ext/module/source_locations.rb +214 -0
  15. data/lib/nrser/core_ext/module.rb +2 -0
  16. data/lib/nrser/core_ext/object/lazy_var.rb +31 -0
  17. data/lib/nrser/core_ext/object.rb +46 -0
  18. data/lib/nrser/core_ext/open_struct.rb +6 -0
  19. data/lib/nrser/{ext → core_ext}/pathname.rb +8 -5
  20. data/lib/nrser/{ext → core_ext}/string.rb +6 -12
  21. data/lib/nrser/core_ext/symbol.rb +13 -0
  22. data/lib/nrser/core_ext/time.rb +46 -0
  23. data/lib/nrser/core_ext.rb +13 -0
  24. data/lib/nrser/errors/abstract_method_error.rb +150 -0
  25. data/lib/nrser/errors/argument_error.rb +42 -0
  26. data/lib/nrser/errors/nicer_error.rb +298 -72
  27. data/lib/nrser/errors/type_error.rb +46 -0
  28. data/lib/nrser/errors.rb +4 -53
  29. data/lib/nrser/ext/tree.rb +3 -0
  30. data/lib/nrser/functions/enumerable/associate.rb +6 -9
  31. data/lib/nrser/functions/enumerable/include_slice.rb +2 -3
  32. data/lib/nrser/functions/enumerable.rb +1 -3
  33. data/lib/nrser/functions/exception.rb +1 -1
  34. data/lib/nrser/functions/hash.rb +0 -6
  35. data/lib/nrser/functions/merge_by.rb +2 -2
  36. data/lib/nrser/functions/module/method_objects.rb +77 -0
  37. data/lib/nrser/functions/module.rb +1 -2
  38. data/lib/nrser/functions/open_struct.rb +25 -35
  39. data/lib/nrser/functions/proc.rb +1 -6
  40. data/lib/nrser/functions/string/looks_like.rb +32 -1
  41. data/lib/nrser/functions/string.rb +1 -40
  42. data/lib/nrser/functions/text/lines.rb +2 -1
  43. data/lib/nrser/functions.rb +0 -1
  44. data/lib/nrser/graph/tsorter.rb +41 -0
  45. data/lib/nrser/labs/core_ext/binding.rb +37 -0
  46. data/lib/nrser/labs/stash.rb +372 -0
  47. data/lib/nrser/{logging → log}/appender/sync.rb +3 -3
  48. data/lib/nrser/log/appender.rb +3 -0
  49. data/lib/nrser/{logging → log}/formatters/color.rb +47 -20
  50. data/lib/nrser/log/formatters/mixin.rb +270 -0
  51. data/lib/nrser/{logging → log}/formatters.rb +0 -0
  52. data/lib/nrser/log/logger.rb +229 -0
  53. data/lib/nrser/log/mixin.rb +56 -0
  54. data/lib/nrser/log.rb +723 -0
  55. data/lib/nrser/message.rb +24 -3
  56. data/lib/nrser/meta/source/location.rb +158 -0
  57. data/lib/nrser/meta.rb +1 -1
  58. data/lib/nrser/props/class_methods.rb +118 -0
  59. data/lib/nrser/props/immutable/hash.rb +111 -0
  60. data/lib/nrser/props/immutable/hash_variable.rb +82 -0
  61. data/lib/nrser/props/immutable/instance_variables.rb +48 -0
  62. data/lib/nrser/props/immutable/vector.rb +107 -0
  63. data/lib/nrser/props/instance_methods.rb +184 -0
  64. data/lib/nrser/props/metadata.rb +359 -0
  65. data/lib/nrser/props/mutable/instance_variables.rb +60 -0
  66. data/lib/nrser/props/mutable/stash.rb +199 -0
  67. data/lib/nrser/{meta/props → props}/prop.rb +217 -112
  68. data/lib/nrser/props/storage/instance_variable.rb +85 -0
  69. data/lib/nrser/props/storage/instance_variables.rb +67 -0
  70. data/lib/nrser/props/storage/key.rb +88 -0
  71. data/lib/nrser/props.rb +9 -0
  72. data/lib/nrser/refinements/sugar.rb +41 -0
  73. data/lib/nrser/refinements/types.rb +2 -2
  74. data/lib/nrser/refinements.rb +14 -16
  75. data/lib/nrser/rspex/example_group/describe_attribute.rb +24 -0
  76. data/lib/nrser/rspex/example_group/describe_called_with.rb +1 -6
  77. data/lib/nrser/rspex/example_group/{describe_use_case.rb → describe_case.rb} +6 -3
  78. data/lib/nrser/rspex/example_group/describe_class.rb +1 -0
  79. data/lib/nrser/rspex/example_group/describe_group.rb +29 -0
  80. data/lib/nrser/rspex/example_group/describe_instance_method.rb +2 -2
  81. data/lib/nrser/rspex/example_group/describe_message.rb +35 -0
  82. data/lib/nrser/rspex/example_group/describe_method.rb +23 -2
  83. data/lib/nrser/rspex/example_group/describe_module.rb +19 -0
  84. data/lib/nrser/rspex/example_group/describe_response_to.rb +32 -0
  85. data/lib/nrser/rspex/example_group/describe_section.rb +38 -0
  86. data/lib/nrser/rspex/example_group/describe_sent_to.rb +52 -0
  87. data/lib/nrser/rspex/example_group/describe_source_file.rb +49 -0
  88. data/lib/nrser/rspex/example_group/describe_spec_file.rb +41 -108
  89. data/lib/nrser/rspex/example_group/describe_when.rb +14 -7
  90. data/lib/nrser/rspex/example_group/describe_x.rb +39 -12
  91. data/lib/nrser/rspex/example_group/overrides.rb +66 -0
  92. data/lib/nrser/rspex/example_group.rb +20 -252
  93. data/lib/nrser/rspex/format.rb +83 -17
  94. data/lib/nrser/rspex.rb +4 -34
  95. data/lib/nrser/sugar/method_missing_forwarder.rb +50 -0
  96. data/lib/nrser/{env → sys/env}/path.rb +1 -2
  97. data/lib/nrser/{env.rb → sys/env.rb} +2 -1
  98. data/lib/nrser/sys.rb +5 -0
  99. data/lib/nrser/types/any.rb +36 -7
  100. data/lib/nrser/types/{array.rb → arrays.rb} +32 -81
  101. data/lib/nrser/types/attrs.rb +68 -15
  102. data/lib/nrser/types/booleans.rb +95 -34
  103. data/lib/nrser/types/bounded.rb +12 -10
  104. data/lib/nrser/types/combinators.rb +74 -37
  105. data/lib/nrser/types/errors/check_error.rb +86 -0
  106. data/lib/nrser/types/errors/from_string_error.rb +82 -0
  107. data/lib/nrser/types/factory.rb +91 -0
  108. data/lib/nrser/types/hashes.rb +171 -26
  109. data/lib/nrser/types/in.rb +25 -12
  110. data/lib/nrser/types/is.rb +50 -18
  111. data/lib/nrser/types/is_a.rb +52 -33
  112. data/lib/nrser/types/labels.rb +6 -33
  113. data/lib/nrser/types/maybe.rb +12 -4
  114. data/lib/nrser/types/nil.rb +24 -4
  115. data/lib/nrser/types/not.rb +6 -16
  116. data/lib/nrser/types/numbers.rb +94 -57
  117. data/lib/nrser/types/pairs.rb +57 -57
  118. data/lib/nrser/types/paths.rb +112 -133
  119. data/lib/nrser/types/responds.rb +64 -74
  120. data/lib/nrser/types/shape.rb +29 -24
  121. data/lib/nrser/types/strings.rb +25 -17
  122. data/lib/nrser/types/symbols.rb +19 -17
  123. data/lib/nrser/types/trees.rb +18 -70
  124. data/lib/nrser/types/tuples.rb +36 -40
  125. data/lib/nrser/types/type.rb +342 -91
  126. data/lib/nrser/types/when.rb +40 -18
  127. data/lib/nrser/types/where.rb +94 -9
  128. data/lib/nrser/types.rb +72 -63
  129. data/lib/nrser/version.rb +1 -1
  130. data/lib/nrser.rb +18 -18
  131. data/spec/lib/nrser/{functions/binding/template_spec.rb → core_ext/binding/erb_spec.rb} +5 -5
  132. data/spec/lib/nrser/{functions → core_ext}/enumerable/find_map_spec.rb +8 -6
  133. data/spec/lib/nrser/{refinements → core_ext}/hash_spec.rb +9 -22
  134. data/spec/lib/nrser/errors/abstract_method_error_spec.rb +12 -5
  135. data/spec/lib/nrser/functions/enumerable/{to_h_by_spec.rb → associate_spec.rb} +1 -1
  136. data/spec/lib/nrser/functions/merge_by_spec.rb +1 -1
  137. data/spec/lib/nrser/functions/tree/each_branch_spec.rb +3 -3
  138. data/spec/lib/nrser/functions/tree/transform_spec.rb +14 -15
  139. data/spec/lib/nrser/gem_ext/hamster/json_spec.rb +4 -0
  140. data/spec/lib/nrser/meta/source/location_spec.rb +86 -0
  141. data/spec/lib/nrser/props/immutable/hash_spec.rb +297 -0
  142. data/spec/lib/nrser/props/immutable/vector_spec.rb +296 -0
  143. data/spec/lib/nrser/{meta/props_spec.rb → props/original_props_spec.rb} +11 -16
  144. data/spec/lib/nrser/{meta/props → props}/to_and_from_data_spec.rb +10 -8
  145. data/spec/lib/nrser/refinements/array_spec.rb +2 -15
  146. data/spec/lib/nrser/refinements/erb_spec.rb +5 -7
  147. data/spec/lib/nrser/refinements/set_spec.rb +2 -15
  148. data/spec/lib/nrser/{env → sys/env}/path/insert_spec.rb +4 -2
  149. data/spec/lib/nrser/{env → sys/env}/path_spec.rb +4 -2
  150. data/spec/lib/nrser/types/array_spec.rb +8 -8
  151. data/spec/lib/nrser/types/paths_spec.rb +15 -18
  152. data/spec/spec_helper.rb +4 -0
  153. metadata +109 -69
  154. data/lib/nrser/ext/binding.rb +0 -36
  155. data/lib/nrser/ext/module.rb +0 -62
  156. data/lib/nrser/ext.rb +0 -8
  157. data/lib/nrser/functions/binding.rb +0 -76
  158. data/lib/nrser/functions/enumerable/map_keys.rb +0 -0
  159. data/lib/nrser/functions/enumerable/map_values.rb +0 -94
  160. data/lib/nrser/functions/hash/deep_merge.rb +0 -57
  161. data/lib/nrser/functions/hash/except_keys.rb +0 -44
  162. data/lib/nrser/functions/hash/slice_keys.rb +0 -43
  163. data/lib/nrser/functions/hash/stringify_keys.rb +0 -55
  164. data/lib/nrser/functions/hash/symbolize_keys.rb +0 -57
  165. data/lib/nrser/functions/hash/transform_keys.rb +0 -140
  166. data/lib/nrser/functions/module/methods.rb +0 -206
  167. data/lib/nrser/functions/module/source_locations.rb +0 -213
  168. data/lib/nrser/logging/appender.rb +0 -3
  169. data/lib/nrser/logging.rb +0 -353
  170. data/lib/nrser/meta/props/base.rb +0 -31
  171. data/lib/nrser/meta/props.rb +0 -357
  172. data/lib/nrser/refinements/array.rb +0 -133
  173. data/lib/nrser/refinements/binding.rb +0 -6
  174. data/lib/nrser/refinements/enumerator.rb +0 -5
  175. data/lib/nrser/refinements/exception.rb +0 -35
  176. data/lib/nrser/refinements/hash.rb +0 -150
  177. data/lib/nrser/refinements/module.rb +0 -5
  178. data/lib/nrser/refinements/object.rb +0 -42
  179. data/lib/nrser/refinements/open_struct.rb +0 -28
  180. data/lib/nrser/refinements/pathname.rb +0 -5
  181. data/lib/nrser/refinements/set.rb +0 -5
  182. data/lib/nrser/refinements/string.rb +0 -5
  183. data/lib/nrser/refinements/symbol.rb +0 -20
  184. data/lib/nrser/rspex/described.rb +0 -99
  185. data/spec/design/mapping_spec.rb +0 -42
  186. data/spec/lib/nrser/functions/hash_spec.rb +0 -41
  187. data/spec/lib/nrser/functions/string/truncate_spec.rb +0 -11
  188. data/spec/lib/nrser/refinements/truncate_spec.rb +0 -10
@@ -0,0 +1,86 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Project / Package
8
+ # -----------------------------------------------------------------------
9
+ require 'nrser/errors/nicer_error'
10
+
11
+
12
+ # Definitions
13
+ # =======================================================================
14
+
15
+ # This error (or a subclass) is thrown when types fail to
16
+ # {NRSER::Types::Type.check!}.
17
+ #
18
+ class NRSER::Types::CheckError < ::TypeError
19
+
20
+ # Mixins
21
+ # ==========================================================================
22
+
23
+ include NRSER::NicerError
24
+
25
+
26
+ # Attributes
27
+ # ========================================================================
28
+
29
+ # The type that was checked against.
30
+ #
31
+ # @return [NRSER::Types::Type]
32
+ #
33
+ attr_reader :type
34
+
35
+
36
+ # The value that failed the type check.
37
+ #
38
+ # @return [*]
39
+ #
40
+ attr_reader :value
41
+
42
+
43
+ # Constructor
44
+ # ========================================================================
45
+
46
+ # Construct a `NicerError`.
47
+ #
48
+ # @param [*] value:
49
+ # The {#value} that failed the check.
50
+ #
51
+ # @param [NRSER::Types::Type] type:
52
+ # The type that was checked.
53
+ #
54
+ # @param details: (see NRSER::NicerError#initialize)
55
+ #
56
+ # @param **kwds
57
+ # See {NRSER::NicerError#initialize}
58
+ #
59
+ def initialize *message, value:, type:, details: nil, **kwds
60
+ @value = value
61
+ @type = type
62
+
63
+ if details.is_a?( Proc ) && details.arity != 0
64
+ orig_details = details
65
+ details = -> { orig_details.call type: type, value: value }
66
+ end
67
+
68
+ super \
69
+ *message,
70
+ type: type,
71
+ value: value,
72
+ details: details,
73
+ **kwds
74
+ end
75
+
76
+
77
+ # Build default message when none provided.
78
+ #
79
+ # @return [String]
80
+ #
81
+ def default_message
82
+ ["Value", value.inspect, "failed check for type", type.name]
83
+ end # #default_message
84
+
85
+
86
+ end # class NRSER::Types::TypeError
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Project / Package
8
+ # -----------------------------------------------------------------------
9
+ require 'nrser/errors/nicer_error'
10
+
11
+
12
+ # Definitions
13
+ # =======================================================================
14
+
15
+ # Raised when a {NRSER::Types::Type} fails to load a value from a {String}
16
+ # (via it's `#from_s` method).
17
+ #
18
+ # This is a {NRSER::NicerError}.
19
+ #
20
+ class NRSER::Types::FromStringError < ::ArgumentError
21
+
22
+ # Mixins
23
+ # ==========================================================================
24
+
25
+ # Make life better.
26
+ include NRSER::NicerError
27
+
28
+
29
+ # Attributes
30
+ # ========================================================================
31
+
32
+ # The type that was checked against.
33
+ #
34
+ # @return [NRSER::Types::Type]
35
+ #
36
+ attr_reader :type
37
+
38
+
39
+ # The string we were trying to load from.
40
+ #
41
+ # @return [String]
42
+ #
43
+ attr_reader :string
44
+
45
+
46
+ # Constructor
47
+ # ========================================================================
48
+
49
+ # Construct a `FromStringError`.
50
+ #
51
+ # @param *message (see NRSER::NicerError#initialize)
52
+ #
53
+ # @param [String] string:
54
+ # The string the type was trying to load a value from.
55
+ #
56
+ # @param [NRSER::Types::Type] type:
57
+ # The type that was trying to load.
58
+ #
59
+ # @param **kwds
60
+ # See {NRSER::NicerError#initialize}
61
+ #
62
+ def initialize *message, string:, type:, **kwds
63
+ @string = string
64
+ @type = type
65
+
66
+ super \
67
+ *message,
68
+ type: type,
69
+ string: string,
70
+ **kwds
71
+ end
72
+
73
+
74
+ # Main message to use when none provided to {#initialize}.
75
+ #
76
+ # @return [String]
77
+ #
78
+ def default_message
79
+ ["Failed to load type", type.name, "from string", string.inspect]
80
+ end
81
+
82
+ end # class NRSER::Types::TypeError
@@ -0,0 +1,91 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Stdlib
8
+ # -----------------------------------------------------------------------
9
+
10
+ # Deps
11
+ # -----------------------------------------------------------------------
12
+
13
+ # Project / Package
14
+ # -----------------------------------------------------------------------
15
+
16
+
17
+ # Refinements
18
+ # =======================================================================
19
+
20
+
21
+ # Declarations
22
+ # =======================================================================
23
+
24
+
25
+ # Definitions
26
+ # =======================================================================
27
+
28
+
29
+ # @todo document NRSER::Types::Factory module.
30
+ module NRSER::Types::Factory
31
+
32
+ # Define a type factory.
33
+ #
34
+ # @!macro [attach] factory
35
+ # @param [Hash] **options
36
+ # Common type construction options, see {Type#initialize}.
37
+ #
38
+ # @return [NRSER::Types::Type]
39
+ # The type.
40
+ #
41
+ def def_factory name, maybe: true, aliases: [], &body
42
+ define_singleton_method name, &body
43
+
44
+ aliases.each do |alias_name|
45
+ if self.respond_to? alias_name
46
+ alias_name = alias_name + '_'
47
+ end
48
+
49
+ singleton_class.send :alias_method, alias_name, name
50
+ end
51
+
52
+ if maybe && !name.to_s.end_with?( '?' )
53
+ maybe_name = "#{ name }?".to_sym
54
+
55
+ if self.respond_to? maybe_name
56
+ maybe_name = "#{ name }_?".to_sym
57
+ end
58
+
59
+ # HACK Ugh maybe I wrote this quick to fix it, not sure if it's a decent
60
+ # idea.. basically, need to figure out what `options` keys go
61
+ # to {.maybe} and which ones go to the regular factory... matters
62
+ # for shit like {.attrs} and {.hash_type} 'cause they use option
63
+ # keys (whether they *should* is something I've debated... sigh,
64
+ # it is what it is for now).
65
+ #
66
+ # So they options that go to {.maybe} just go strait through to
67
+ # {Type#initialize}, so just grab that method, see what keys it
68
+ # takes, and then can slice and dice off that...
69
+ #
70
+ maybe_option_keys = Set.new \
71
+ NRSER::Types::Type.
72
+ instance_method( :initialize ).
73
+ parameters.
74
+ select { |param_type, name| param_type == :key }.
75
+ map { |param_type, name| name }
76
+
77
+ define_singleton_method maybe_name do |*args, **options|
78
+ maybe_options = options.slice *maybe_option_keys
79
+ factory_options = options.except *maybe_option_keys
80
+
81
+ maybe public_send( name, *args, **factory_options ), **maybe_options
82
+ end
83
+
84
+ aliases.each do |alias_name|
85
+ singleton_class.send :alias_method, "#{ alias_name }?", maybe_name
86
+ end
87
+
88
+ end
89
+ end
90
+
91
+ end # module NRSER::Types::Factory
@@ -1,41 +1,185 @@
1
- require 'nrser/refinements'
2
- require 'nrser/types/type'
3
-
4
- using NRSER
1
+ require_relative './type'
5
2
 
6
3
  module NRSER::Types
7
-
4
+
5
+ # A type who's members simply are {Hash} instances.
6
+ #
7
+ # Implements {#from_s} to provide JSON/YAML detection, as well as "simple"
8
+ # loading aimed at CLI option values.
9
+ #
8
10
  class HashType < IsA
9
- attr_reader :keys, :values #, :including, :exactly, :min, :max
11
+
12
+ # Constructor
13
+ # ========================================================================
10
14
 
11
- def initialize keys: NRSER::Types::ANY,
12
- values: NRSER::Types::ANY,
13
- **options
15
+ # Instantiate a new `HashType`.
16
+ def initialize **options
14
17
  super ::Hash, **options
18
+ end # #initialize
19
+
20
+
21
+ # Instance Methods
22
+ # ========================================================================
23
+
24
+ # In order to provide the same interface as {HashOfType}, this method
25
+ # always returns {NRSER::Types.any}.
26
+ #
27
+ # @return [NRSER::Types::Type]
28
+ #
29
+ def keys; NRSER::Types.any; end
30
+
31
+
32
+ # In order to provide the same interface as {HashOfType}, this method
33
+ # always returns {NRSER::Types.any}.
34
+ #
35
+ # @return [NRSER::Types::Type]
36
+ #
37
+ def values; NRSER::Types.any; end
38
+
39
+
40
+ protected
41
+ # ========================================================================
42
+
43
+ # Hook to provide custom loading from strings, which will be called by
44
+ # {NRSER::Types::Type#from_s}, unless a `@from_s`
45
+ #
46
+ def custom_from_s string
47
+ # Does it looks like a JSON / inline-YAML object?
48
+ if NRSER.looks_like_json_object? string
49
+ # It does! Load it
50
+ begin
51
+ return YAML.load string
52
+ rescue
53
+ # pass - if we failed to load as JSON, it may just not be JSON, and
54
+ # we can try the split approach below.
55
+ end
56
+ end
57
+
58
+ # Try parsing as a "simple string", aimed at CLI option values.
59
+ from_simple_s string
60
+ end
61
+
62
+
63
+ def from_simple_s string
64
+ hash = {}
65
+
66
+ pair_strs = string.split NRSER::Types::ArrayType::DEFAULT_SPLIT_WITH
67
+
68
+ pair_strs.each do |pair_str|
69
+ key_str, match, value_str = pair_str.rpartition /\:\s*/m
70
+
71
+ if match.empty?
72
+ raise NRSER::Types::FromStringError.new(
73
+ "Could not split pair string", pair_str,
74
+ type: self,
75
+ string: string,
76
+ pair_str: pair_str,
77
+ ) do
78
+ <<~END
79
+ Trying to parse a {Hash} out of a string using the "simple"
80
+ approach, which splits
81
+
82
+ 1. First by `,` (followed by any amount of whitespace)
83
+ 2. Then by the last `:` in each of those splits (also followed)
84
+ by any amount of whitespace)
85
+ END
86
+ end
87
+ end
88
+
89
+ key = if keys == NRSER::Types.any
90
+ key_str
91
+ else
92
+ keys.from_s key_str
93
+ end
94
+
95
+ value = if values == NRSER::Types.any
96
+ value_str
97
+ else
98
+ values.from_s value_str
99
+ end
100
+
101
+ hash[key] = value
102
+ end
103
+
104
+ hash
105
+ end # #from_simple_s
106
+
107
+ public # end protected *****************************************************
108
+
109
+ end # class HashType
110
+
111
+
112
+ # A {Hash} type with typed keys and/or values.
113
+ #
114
+ class HashOfType < HashType
115
+
116
+ # Attributes
117
+ # ========================================================================
118
+
119
+ # The type of the hash keys.
120
+ #
121
+ # @return [NRSER::Types::Type]
122
+ #
123
+ attr_reader :keys
124
+
125
+
126
+ # The type of the hash values.
127
+ #
128
+ # @return [NRSER::Types::Type]
129
+ #
130
+ attr_reader :values
131
+
132
+
133
+ # Constructor
134
+ # ========================================================================
135
+
136
+ def initialize keys: NRSER::Types.any,
137
+ values: NRSER::Types.any,
138
+ **options
139
+ super **options
15
140
 
16
141
  @keys = NRSER::Types.make keys
17
142
  @values = NRSER::Types.make values
18
143
  end
19
144
 
20
- def test value
21
- return false unless super(value)
22
-
23
- if keys == NRSER::Types::ANY && values == NRSER::Types::ANY
24
- return true
25
- end
145
+
146
+ # Instance Methods
147
+ # ========================================================================
148
+
149
+ # Overridden to check that both the {#keys} and {#values} types can
150
+ # load from a string.
151
+ #
152
+ # @see NRSER::Types::Type#has_from_s?
153
+ #
154
+ def has_from_s?
155
+ !@from_s.nil? || [keys, values].all?( &:has_from_s )
156
+ end
157
+
158
+
159
+ # @see NRSER::Types::Type#test
160
+ #
161
+ # @return [Boolean]
162
+ #
163
+ def test? value
164
+ return false unless super( value )
26
165
 
27
166
  value.all? { |k, v|
28
- keys.test(k) && values.test(v)
167
+ keys.test( k ) && values.test( v )
29
168
  }
30
169
  end
31
170
 
32
- def default_name
33
- "Hash{#{ @keys.name }=>#{ @values.name }}"
171
+
172
+ # @see NRSER::Types::Type#explain
173
+ #
174
+ # @return [String]
175
+ #
176
+ def explain
177
+ "Hash<#{ keys.explain }, #{ values.explain }>"
34
178
  end
179
+
35
180
  end # HashType
181
+
36
182
 
37
-
38
-
39
183
  # Type satisfied by {Hash} instances.
40
184
  #
41
185
  # @param [Array] *args
@@ -47,14 +191,15 @@ module NRSER::Types
47
191
  # @return [NRSER::Types::Type]
48
192
  # Newly constructed hash type from `args`.
49
193
  #
50
- def_factory :hash_type, aliases: [:dict, :hash_] do |*args|
51
- if args.empty?
52
- HASH
194
+ def_factory(
195
+ :hash_type,
196
+ aliases: [ :dict, :hash_ ]
197
+ ) do |**kwds|
198
+ if kwds.key?( :keys ) || kwds.key?( :values )
199
+ HashOfType.new **kwds
53
200
  else
54
- HashType.new *args
201
+ HashType.new **kwds
55
202
  end
56
203
  end
57
204
 
58
- HASH = HashType.new.freeze
59
-
60
205
  end
@@ -1,26 +1,39 @@
1
- # Refinements
2
- # =======================================================================
3
-
4
- using NRSER
5
-
6
-
7
- # Definitions
8
- # =======================================================================
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
9
3
 
10
4
  module NRSER::Types
11
5
 
12
6
  # Type that tests value for membership in a group object via that object's
13
7
  # `#include?` method.
14
8
  #
9
+ # @todo
10
+ # I think I want to get rid of {.where}... which would elevate this to
11
+ # it's own class as a "fundamental" concept (I guess)... not so sure,
12
+ # really. The idea of membership is pretty wide-spread and important,
13
+ # but it's a bit a vague and inconsistently implemented things.
14
+ #
15
15
  # @param [#include?] group
16
16
  # `#include?` will be called on this value to determine type membership.
17
17
  #
18
18
  # @return [NRSER::Types::Type]
19
19
  #
20
- def self.in group, **options
21
- where( name: "In(#{ group })", **options ) { |value|
22
- group.include? value
23
- }
20
+ def_factory(
21
+ :in,
22
+ aliases: [ :member_of ],
23
+ ) do |group, **options|
24
+ unless group.respond_to? :include?
25
+ raise NRSER::ArgumentError,
26
+ "In `group` must respond to `:include?`",
27
+ group: group
28
+ end
29
+
30
+ # Provide a some-what useful default name
31
+ options[:name] ||= "In<#{ NRSER.smart_ellipsis group.inspect, 64 }>"
32
+
33
+ # Unless a `from_s` is provided, just use the identity
34
+ options[:from_s] ||= ->( s ) { s }
35
+
36
+ where( **options ) { |value| group.include? value }
24
37
  end # .in
25
38
 
26
39
  end # module NRSER::Types
@@ -1,22 +1,58 @@
1
- require 'nrser/refinements'
2
- require 'nrser/types/type'
3
- using NRSER
1
+
2
+ # Requirements
3
+ # ========================================================================
4
+
5
+ # Stdlib
6
+ # ------------------------------------------------------------------------
7
+
8
+ # Deps
9
+ # ------------------------------------------------------------------------
10
+
11
+ # Need {Module#anonymous?}
12
+ require 'active_support/core_ext/module/anonymous'
13
+
14
+
15
+ # Project / Package
16
+ # ------------------------------------------------------------------------
17
+
18
+ require_relative './type'
19
+
4
20
 
5
21
  module NRSER::Types
22
+
23
+ # Type satisfied only by it's exact {#value} object (identity comparison
24
+ # via `#equal?`).
25
+ #
6
26
  class Is < NRSER::Types::Type
27
+
28
+ # Attributes
29
+ # ========================================================================
30
+
7
31
  attr_reader :value
8
32
 
9
33
  def initialize value, **options
10
34
  super **options
11
-
12
35
  @value = value
13
36
  end
14
37
 
15
- def default_name
16
- "Is(#{ @value.inspect })"
38
+ def explain
39
+ case value
40
+ when Module
41
+ module_type = if value.is_a?( Class ) then 'Class' else 'Module' end
42
+
43
+ name = if value.anonymous?
44
+ value.to_s.split( ':' ).last[0...-1]
45
+ else
46
+ value.name
47
+ end
48
+
49
+ "#{ module_type }<#{ name }>"
50
+ else
51
+ value.inspect
52
+ end
17
53
  end
18
54
 
19
- def test value
55
+ def test? value
20
56
  @value.equal? value
21
57
  end
22
58
 
@@ -26,19 +62,15 @@ module NRSER::Types
26
62
  @value == other.value )
27
63
  end
28
64
 
29
- # @return [String]
30
- # a brief string description of the type - just it's {#name} surrounded
31
- # by some back-ticks to make it easy to see where it starts and stops.
32
- #
33
- def to_s
34
- "{ x ≡ #{ @value.inspect } }"
35
- end
36
-
37
- alias_method :inspect, :to_s
38
65
  end # Is
39
66
 
40
- # an exact value (using ===)
41
- def self.is value, **options
67
+
68
+ # Satisfied by the exact value only (identity comparison via
69
+ # `#equal?`).
70
+ #
71
+ # Useful for things like {Module}, {Class}, {Fixnum}, {Symbol}, `true`, etc.
72
+ #
73
+ def_factory :is do |value, **options|
42
74
  Is.new value, **options
43
75
  end
44
76