nrser 0.2.2 → 0.3.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 (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
@@ -3,73 +3,92 @@ require 'nrser/types/type'
3
3
  using NRSER
4
4
 
5
5
  module NRSER::Types
6
+ # Type satisfied by class membership (or mixin presence for modules).
7
+ #
8
+ # Tests via the subject value's `#is_a?` method.
9
+ #
6
10
  class IsA < NRSER::Types::Type
7
- attr_reader :klass
8
-
9
- def initialize klass, **options
10
- unless klass.is_a?( Class ) || klass.is_a?( Module )
11
- raise ArgumentError.new binding.erb <<-ERB
12
- `klass` argument must be a Class or Module, found:
13
-
14
- <%= klass.pretty_inspect %>
15
-
16
- ERB
11
+ attr_reader :mod
12
+
13
+ def initialize mod, init_from_data: false, **options
14
+ unless mod.is_a?( Module )
15
+ raise ArgumentError,
16
+ "`mod` argument must be a Module (inc. Class), " \
17
+ "received #{ mod.inspect }"
17
18
  end
18
19
 
19
20
  super **options
20
- @klass = klass
21
+
22
+ @init_from_data = !!init_from_data
23
+
24
+ @mod = mod
21
25
  end
22
26
 
23
27
 
24
- def default_name
25
- @klass.name
28
+ def explain
29
+ mod.safe_name
26
30
  end
27
31
 
28
32
 
29
- def test value
30
- value.is_a? @klass
33
+ def test? value
34
+ value.is_a? mod
31
35
  end
32
36
 
33
37
 
34
- # If {#klass} responds to `#from_data`, call that and check results.
38
+
39
+ # @todo Document init_from_data? method.
40
+ #
41
+ # @param [type] arg_name
42
+ # @todo Add name param description.
35
43
  #
36
- # Otherwise, forward up to {NRSER::Types::Type#from_data}.
44
+ # @return [return_type]
45
+ # @todo Document return value.
37
46
  #
38
- # @param [Object] data
39
- # Data to create the value from that will satisfy the type.
47
+ def init_from_data?
48
+ @init_from_data
49
+ end # #init_from_data?
50
+
51
+
52
+
53
+ # Forwards to `mod.from_data`.
40
54
  #
41
- # @return [Object]
42
- # Instance of {#klass}.
55
+ # @param data (see NRSER::Types::Type#from_data)
56
+ # @return (see NRSER::Types::Type#from_data)
57
+ # @raise (see NRSER::Types::Type#from_data)
43
58
  #
44
- def from_data data
45
- if @from_data.nil?
46
- if @klass.respond_to? :from_data
47
- check @klass.from_data( data )
48
- else
49
- super data
50
- end
59
+ def custom_from_data data
60
+ if init_from_data?
61
+ mod.new data
51
62
  else
52
- @from_data.call data
63
+ mod.from_data data
53
64
  end
54
65
  end
55
66
 
56
67
 
68
+ # Overrides {NRSER::Types::Type#has_from_data?} to respond `true` when
69
+ # there is a instance-specific `@from_data` or the {#mod} responds to
70
+ # `.from_data`.
71
+ #
72
+ # @return [Boolean]
73
+ #
57
74
  def has_from_data?
58
- @from_data || @klass.respond_to?( :from_data )
75
+ @from_data ||
76
+ init_from_data? ||
77
+ mod.respond_to?( :from_data )
59
78
  end
60
79
 
61
80
 
62
81
  def == other
63
82
  equal?( other ) ||
64
83
  ( self.class == other.class &&
65
- self.klass == other.klass )
84
+ self.mod == other.mod )
66
85
  end
67
86
 
68
87
  end # IsA
69
88
 
70
89
 
71
90
  # class membership
72
- def self.is_a klass, **options
73
- IsA.new klass, **options
91
+ def_factory :is_a do |mod, **options|
92
+ IsA.new mod, **options
74
93
  end
75
94
  end # NRSER::Types
@@ -1,28 +1,5 @@
1
- # Requirements
2
- # =======================================================================
3
-
4
- # Stdlib
5
- # -----------------------------------------------------------------------
6
-
7
- # Deps
8
- # -----------------------------------------------------------------------
9
-
10
- # Project / Package
11
- # -----------------------------------------------------------------------
12
-
13
-
14
- # Refinements
15
- # =======================================================================
16
-
17
- require 'nrser/refinements'
18
- using NRSER
19
-
20
-
21
- # Declarations
22
- # =======================================================================
23
-
24
- module NRSER; end
25
-
1
+ require_relative './combinators'
2
+ require_relative './strings'
26
3
 
27
4
  # Definitions
28
5
  # =======================================================================
@@ -36,14 +13,10 @@ module NRSER::Types
36
13
  #
37
14
  # @return [NRSER::Types::Type]
38
15
  #
39
- def self.label **options
40
- if options.empty?
41
- LABEL
42
- else
43
- union non_empty_str, non_empty_sym, **options
44
- end
16
+ def_factory(
17
+ :label,
18
+ ) do |name: 'Label', **options|
19
+ union non_empty_str, non_empty_sym, name: name, **options
45
20
  end # .label
46
21
 
47
- LABEL = label( name: 'LabelType' ).freeze
48
-
49
22
  end # module NRSER::Types
@@ -1,10 +1,18 @@
1
- require 'nrser/types/combinators'
1
+ require_relative './combinators'
2
+ require_relative './nil'
2
3
 
3
4
  module NRSER::Types
4
5
 
5
- # nil or the argument type
6
- def self.maybe type, **options
7
- union self.nil, type, name: "#{ type.name }?", **options
6
+ # Type satisfied by `nil` or the parametrized type.
7
+ #
8
+ def_factory(
9
+ :maybe,
10
+ ) do |type, **options|
11
+ union \
12
+ self.nil,
13
+ type,
14
+ name: (options[:name] || "#{ type.name }?"),
15
+ **options
8
16
  end
9
17
 
10
18
  end # NRSER::Types
@@ -1,8 +1,28 @@
1
- require 'nrser/types/is'
1
+ require_relative './is'
2
2
 
3
3
  module NRSER::Types
4
- # nothing
5
- def self.nil
6
- is nil, name: 'Nil'
4
+ # Type for `nil`, itself and only.
5
+ #
6
+ # @todo
7
+ # Should we have a `#from_s` that converts the empty string to `nil`?
8
+ #
9
+ # Kind-of seems like we would want that to be a different types so that
10
+ # you can have a Nil type that is distinct from the empty string in
11
+ # parsing, but also have a type that accepts the empty string and coverts
12
+ # it to `nil`?
13
+ #
14
+ # Something like:
15
+ #
16
+ # type = t.empty | t.non_empty_str
17
+ # type.from_s ''
18
+ # # => nil
19
+ # type.from_s 'blah'
20
+ # # => 'blah'
21
+ #
22
+ def_factory(
23
+ :nil,
24
+ aliases: [ :null ],
25
+ ) do |name: 'Nil', **options|
26
+ is nil, name: name, **options
7
27
  end
8
28
  end # NRSER::Types
@@ -22,31 +22,21 @@ module NRSER::Types
22
22
  # Instance Methods
23
23
  # ======================================================================
24
24
 
25
- def test value
25
+ def test? value
26
26
  ! @type.test( value )
27
27
  end
28
28
 
29
29
 
30
- def default_name
31
- "!#{ @type.name }"
30
+ def explain
31
+ "~#{ @type.name }"
32
32
  end
33
33
 
34
-
35
- # @return [String]
36
- # a brief string description of the type - just it's {#name} surrounded
37
- # by some back-ticks to make it easy to see where it starts and stops.
38
- #
39
- def to_s
40
- "{ x ∉ #{ @type.name } }"
41
- end
42
-
43
- alias_method :inspect, :to_s
44
-
45
-
46
34
  end # class Not
47
35
 
48
36
 
49
- def self.not type, **options
37
+ def_factory(
38
+ :not,
39
+ ) do |type, **options|
50
40
  Not.new type, **options
51
41
  end
52
42
 
@@ -15,8 +15,8 @@ module NRSER::Types
15
15
  # @return [Float]
16
16
  # If the string represents a decimal number.
17
17
  #
18
- def self.parse_number s
19
- float = Float s
18
+ def self.parse_number string
19
+ float = Float string
20
20
  int = float.to_i
21
21
  if float == int then int else float end
22
22
  end
@@ -25,48 +25,44 @@ module NRSER::Types
25
25
  # Zero
26
26
  # =====================================================================
27
27
 
28
- ZERO = is(
29
- 0,
30
- name: 'ZeroType',
31
- from_s: method( :parse_number )
32
- ).freeze
33
-
34
- def self.zero
35
- ZERO
28
+ def_factory(
29
+ :Zero,
30
+ aliases: [ :zero ],
31
+ ) do |from_s: method( :parse_number ), **options|
32
+ is \
33
+ 0,
34
+ from_s: from_s,
35
+ **options
36
36
  end
37
37
 
38
38
 
39
39
  # Number ({Numeric})
40
40
  # =====================================================================
41
41
 
42
- NUM = IsA.new(
43
- Numeric,
44
- name: 'NumType',
45
- from_s: method( :parse_number )
46
- ).freeze
47
-
48
- def self.num
49
- NUM
42
+ def_factory(
43
+ :Number,
44
+ aliases: [ :num, :number, :numeric, :Numeric ],
45
+ ) do |name: 'Number', from_s: method( :parse_number ), **options|
46
+ IsA.new \
47
+ Numeric,
48
+ from_s: from_s,
49
+ **options
50
50
  end
51
51
 
52
- singleton_class.send :alias_method, :number, :num
53
-
54
52
 
55
53
  # Integers
56
54
  # =====================================================================
57
55
 
58
- INT = IsA.new(
59
- Integer,
60
- name: 'IntType',
61
- from_s: method( :parse_number )
62
- ).freeze
63
-
64
- def self.int
65
- INT
56
+ def_factory(
57
+ :Integer,
58
+ aliases: [ :int, :integer, :signed ],
59
+ ) do |name: 'ℤ', from_s: method( :parse_number ), **options|
60
+ IsA.new \
61
+ Integer,
62
+ from_s: from_s,
63
+ **options
66
64
  end
67
65
 
68
- singleton_class.send :alias_method, :integer, :int
69
-
70
66
 
71
67
  # Bounded Integers
72
68
  # ---------------------------------------------------------------------
@@ -77,12 +73,15 @@ module NRSER::Types
77
73
  # Integer greater than zero.
78
74
  #
79
75
 
80
- def self.pos_int
81
- intersection(
82
- INT,
83
- bounded(min: 1),
84
- name: 'ℤ⁺'
85
- ).freeze
76
+ def_factory(
77
+ :PositiveInteger,
78
+ aliases: [ :pos_int, :positive_int, :positive_integer ]
79
+ ) do |name: 'ℤ⁺', **options|
80
+ intersection \
81
+ int,
82
+ bounded( min: 1 ),
83
+ name: name,
84
+ **options
86
85
  end
87
86
 
88
87
  # Ugh sometimes the naturals have 0, so omit it...
@@ -95,12 +94,15 @@ module NRSER::Types
95
94
  # Integer less than zero.
96
95
  #
97
96
 
98
- def self.neg_int
99
- intersection(
100
- INT,
101
- bounded(max: -1),
102
- name: 'ℤ⁻'
103
- ).freeze
97
+ def_factory(
98
+ :NegativeInteger,
99
+ aliases: [ :neg_int, :negative_int, :negative_integer ],
100
+ ) do |name: 'ℤ⁻', **options|
101
+ intersection \
102
+ int,
103
+ bounded( max: -1 ),
104
+ name: name,
105
+ **options
104
106
  end
105
107
 
106
108
 
@@ -111,20 +113,23 @@ module NRSER::Types
111
113
  # as bounded instead of a union.
112
114
  #
113
115
 
114
- def self.non_neg_int **options
115
- # Alternative symbol: 'ℤ⋆'
116
- intersection INT, bounded(min: 0), name: '{0}∪ℤ⁺', **options
117
- end
118
-
119
- singleton_class.send :alias_method, :unsigned, :non_neg_int
120
-
121
-
122
- def self.non_neg_int? **options
123
- maybe non_neg_int, **options
116
+ def_factory(
117
+ :NonNegativeInteger,
118
+ aliases: [
119
+ :non_neg_int,
120
+ :unsigned,
121
+ :index,
122
+ :non_negative_int,
123
+ :non_negative_integer,
124
+ ],
125
+ ) do |name: 'ℕ⁰', **options|
126
+ intersection \
127
+ int,
128
+ bounded( min: 0 ),
129
+ name: name,
130
+ **options
124
131
  end
125
132
 
126
- singleton_class.send :alias_method, :unsigned?, :non_neg_int?
127
-
128
133
 
129
134
  # Non-Positive Integer
130
135
  # --------------------
@@ -132,8 +137,40 @@ module NRSER::Types
132
137
  # negative integers and zero.
133
138
  #
134
139
 
135
- def self.non_pos_int **options
136
- intersection INT, bounded(max: 0), name: '{0}∪ℤ⁻', **options
140
+ def_factory(
141
+ :NonPositiveInteger,
142
+ aliases: [ :non_pos_int, :non_positive_int, :non_positive_integer ],
143
+ ) do |name: '{0}∪ℤ⁻', **options|
144
+ intersection \
145
+ int,
146
+ bounded( max: 0 ),
147
+ name: name,
148
+ **options
149
+ end
150
+
151
+
152
+ def_factory(
153
+ :Unsigned16BitInteger,
154
+ aliases: [ :uint16, :ushort ],
155
+ ) do |name: 'uint16', **options|
156
+ intersection \
157
+ int,
158
+ bounded( min: 0, max: ((2 ** 16) - 1) ),
159
+ name: name,
160
+ **options
137
161
  end
138
-
162
+
163
+
164
+ # TODO Move?
165
+ def_factory(
166
+ :UNIXPort,
167
+ aliases: [ :port, ],
168
+ ) do |name: 'port', **options|
169
+ intersection \
170
+ int,
171
+ bounded( min: 1, max: (2**16 - 1) ),
172
+ name: name,
173
+ **options
174
+ end
175
+
139
176
  end # NRSER::Types
@@ -9,7 +9,10 @@
9
9
 
10
10
  # Project / Package
11
11
  # -----------------------------------------------------------------------
12
+ require 'nrser/core_ext/hash'
13
+
12
14
  require_relative './combinators'
15
+ require_relative './tuples'
13
16
 
14
17
 
15
18
  # Refinements
@@ -27,83 +30,80 @@ module NRSER; end
27
30
 
28
31
  module NRSER::Types
29
32
 
30
-
31
- # @todo Document array_pair method.
32
- #
33
- # @param [type] arg_name
34
- # @todo Add name param description.
33
+ # Type for key/value pairs encoded as a {.tuple} (Array) of length 2.
35
34
  #
36
- # @return [return_type]
37
- # @todo Document return value.
38
- #
39
- def self.array_pair **options
40
- return ARRAY_PAIR if options.empty?
41
-
42
- key = options.delete(:key) || ANY
43
- value = options.delete(:value) || ANY
35
+ def_factory(
36
+ :array_pair,
37
+ ) do |name: 'ArrayPair', key: any, value: any, **options|
38
+ unless options.key? :name
39
+ options[:name] = if key == any && value == any
40
+ 'ArrayPair'
41
+ else
42
+ key = NRSER::Types.make key
43
+ value = NRSER::Types.make value
44
+
45
+ "ArrayPair<#{ key.name }, #{ value.name }>"
46
+ end
47
+ end
44
48
 
45
- tuple key, value, **options
49
+ tuple \
50
+ key,
51
+ value,
52
+ # name: name,
53
+ **options
46
54
  end # .array_pair
47
55
 
48
- ARRAY_PAIR = array_pair( name: 'ArrayPairType' ).freeze
49
56
 
50
-
51
- # Type for a {Hash} that consists of only a single key and value pair.
57
+ # Type for key/value pairs encoded as {Hash} with a single entry.
52
58
  #
53
59
  # @param [String] name:
54
60
  # Name to give the new type.
55
61
  #
56
62
  # @param [Hash] **options
57
- # Other options to pass to
58
- #
59
- # @return [NRSER::Types::Type]
63
+ # Other options to pass to
60
64
  #
61
- def self.hash_pair **options
62
- return HASH_PAIR if options.empty?
63
-
64
- hash_options = {}
65
- {key: :keys, value: :values}.each { |from_key, to_key|
66
- if options.key? from_key
67
- hash_options[to_key] = options.delete from_key
65
+ def_factory(
66
+ :hash_pair,
67
+ ) do |key: any, value: any, **options|
68
+ unless options.key? :name
69
+ options[:name] = if key == any && value == any
70
+ 'HashPair'
71
+ else
72
+ key = NRSER::Types.make key
73
+ value = NRSER::Types.make value
74
+
75
+ "HashPair<#{ key.name }, #{ value.name }>"
68
76
  end
69
- }
70
-
71
- if hash_options.empty?
72
- intersection is_a( Hash ), length( 1 ), **options
73
- else
74
- intersection \
75
- hash_type( **hash_options ),
76
- length( 1 ),
77
- **options
78
77
  end
79
78
 
79
+ intersection \
80
+ hash_type( keys: key, values: value ),
81
+ length( 1 ),
82
+ # name: name,
83
+ **options
80
84
  end # .hash_pair
81
85
 
82
- HASH_PAIR = hash_pair( name: 'HashPairType' ).freeze
83
-
84
86
 
85
- # @todo Document pair method.
86
- #
87
- # @param [type] arg_name
88
- # @todo Add name param description.
87
+ # A key/value pair, which can be encoded as an Array of length 2 or a
88
+ # Hash of length 1.
89
89
  #
90
- # @return [return_type]
91
- # @todo Document return value.
92
90
  #
93
- def self.pair **options
94
- if options.empty?
95
- PAIR
96
- else
97
- type_options = NRSER.slice_keys! options, :key, :value
98
-
99
- union \
100
- array_pair( **type_options ),
101
- hash_pair( **type_options ),
102
- **options
91
+ def_factory :pair do |key: any, value: any, **options|
92
+ unless options.key? :name
93
+ options[:name] = if key == any && value == any
94
+ 'Pair'
95
+ else
96
+ key = NRSER::Types.make key
97
+ value = NRSER::Types.make value
98
+
99
+ "Pair<#{ key.name }, #{ value.name }>"
100
+ end
103
101
  end
102
+
103
+ union \
104
+ array_pair( key: key, value: value ),
105
+ hash_pair( key: key, value: value ),
106
+ **options
104
107
  end # #pair
105
108
 
106
- PAIR = pair( name: 'PairType' ).freeze
107
-
108
109
  end # module NRSER::Types
109
-