nrser 0.3.9 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
  3. data/lib/nrser/char/special.rb +5 -5
  4. data/lib/nrser/core_ext/array.rb +36 -13
  5. data/lib/nrser/core_ext/enumerable.rb +1 -0
  6. data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
  7. data/lib/nrser/core_ext/hash/bury.rb +3 -0
  8. data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
  9. data/lib/nrser/core_ext/method/full_name.rb +1 -1
  10. data/lib/nrser/core_ext/module/method_objects.rb +1 -1
  11. data/lib/nrser/core_ext/module/source_locations.rb +27 -15
  12. data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
  13. data/lib/nrser/core_ext/pathname.rb +67 -12
  14. data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
  15. data/lib/nrser/core_ext/string.rb +28 -1
  16. data/lib/nrser/core_ext/symbol.rb +11 -12
  17. data/lib/nrser/errors/README.md +154 -0
  18. data/lib/nrser/errors/attr_error.rb +146 -53
  19. data/lib/nrser/errors/count_error.rb +61 -12
  20. data/lib/nrser/errors/nicer_error.rb +42 -71
  21. data/lib/nrser/errors/value_error.rb +53 -58
  22. data/lib/nrser/functions.rb +0 -2
  23. data/lib/nrser/functions/enumerable.rb +5 -17
  24. data/lib/nrser/functions/enumerable/associate.rb +14 -5
  25. data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
  26. data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
  27. data/lib/nrser/functions/hash/bury.rb +2 -12
  28. data/lib/nrser/functions/merge_by.rb +2 -2
  29. data/lib/nrser/functions/module/method_objects.rb +2 -2
  30. data/lib/nrser/functions/path.rb +185 -165
  31. data/lib/nrser/functions/path/normalized.rb +84 -0
  32. data/lib/nrser/functions/string.rb +4 -4
  33. data/lib/nrser/functions/text/README.md +4 -0
  34. data/lib/nrser/functions/text/format.rb +53 -0
  35. data/lib/nrser/functions/text/indentation.rb +6 -6
  36. data/lib/nrser/functions/text/word_wrap.rb +2 -2
  37. data/lib/nrser/functions/tree/map_leaves.rb +3 -3
  38. data/lib/nrser/functions/tree/map_tree.rb +2 -2
  39. data/lib/nrser/functions/tree/transform.rb +1 -18
  40. data/lib/nrser/gem_ext/README.md +4 -0
  41. data/lib/nrser/labs/README.md +8 -0
  42. data/lib/nrser/labs/config.rb +163 -0
  43. data/lib/nrser/labs/i8.rb +49 -159
  44. data/lib/nrser/labs/i8/struct.rb +167 -0
  45. data/lib/nrser/labs/i8/struct/hash.rb +140 -0
  46. data/lib/nrser/labs/i8/struct/vector.rb +149 -0
  47. data/lib/nrser/labs/i8/surjection.rb +211 -0
  48. data/lib/nrser/labs/lots/consumer.rb +19 -0
  49. data/lib/nrser/labs/lots/parser.rb +21 -1
  50. data/lib/nrser/labs/stash.rb +4 -4
  51. data/lib/nrser/log.rb +25 -21
  52. data/lib/nrser/log/appender/sync.rb +15 -11
  53. data/lib/nrser/log/formatters/color.rb +0 -3
  54. data/lib/nrser/log/formatters/mixin.rb +4 -4
  55. data/lib/nrser/log/logger.rb +54 -6
  56. data/lib/nrser/log/mixin.rb +2 -1
  57. data/lib/nrser/log/plugin.rb +6 -6
  58. data/lib/nrser/log/types.rb +46 -29
  59. data/lib/nrser/mean_streak.rb +0 -8
  60. data/lib/nrser/mean_streak/document.rb +1 -4
  61. data/lib/nrser/message.rb +3 -3
  62. data/lib/nrser/meta/README.md +4 -0
  63. data/lib/nrser/meta/lazy_attr.rb +2 -2
  64. data/lib/nrser/meta/source/location.rb +1 -1
  65. data/lib/nrser/props.rb +34 -3
  66. data/lib/nrser/props/class_methods.rb +2 -1
  67. data/lib/nrser/props/instance_methods.rb +9 -9
  68. data/lib/nrser/props/metadata.rb +4 -12
  69. data/lib/nrser/props/mutable/stash.rb +5 -2
  70. data/lib/nrser/props/prop.rb +10 -19
  71. data/lib/nrser/rspex.rb +1 -20
  72. data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
  73. data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
  74. data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
  75. data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
  76. data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
  77. data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
  78. data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
  79. data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
  80. data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
  81. data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
  82. data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
  83. data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
  84. data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
  85. data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
  86. data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
  87. data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
  88. data/lib/nrser/rspex/format.rb +0 -15
  89. data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
  90. data/lib/nrser/sys/env/path.rb +2 -28
  91. data/lib/nrser/types.rb +63 -12
  92. data/lib/nrser/types/README.md +76 -0
  93. data/lib/nrser/types/arrays.rb +192 -137
  94. data/lib/nrser/types/attributes.rb +269 -0
  95. data/lib/nrser/types/booleans.rb +134 -83
  96. data/lib/nrser/types/bounded.rb +110 -47
  97. data/lib/nrser/types/collections.rb +119 -0
  98. data/lib/nrser/types/combinators.rb +283 -196
  99. data/lib/nrser/types/doc/display_table.md +66 -0
  100. data/lib/nrser/types/eqiuvalent.rb +91 -0
  101. data/lib/nrser/types/errors/check_error.rb +5 -11
  102. data/lib/nrser/types/errors/from_string_error.rb +3 -3
  103. data/lib/nrser/types/factory.rb +287 -20
  104. data/lib/nrser/types/hashes.rb +227 -179
  105. data/lib/nrser/types/in.rb +73 -36
  106. data/lib/nrser/types/is.rb +67 -60
  107. data/lib/nrser/types/is_a.rb +141 -84
  108. data/lib/nrser/types/labels.rb +45 -16
  109. data/lib/nrser/types/maybe.rb +6 -3
  110. data/lib/nrser/types/nil.rb +64 -27
  111. data/lib/nrser/types/not.rb +92 -34
  112. data/lib/nrser/types/numbers.rb +224 -169
  113. data/lib/nrser/types/pairs.rb +113 -89
  114. data/lib/nrser/types/paths.rb +250 -137
  115. data/lib/nrser/types/responds.rb +167 -89
  116. data/lib/nrser/types/selector.rb +234 -0
  117. data/lib/nrser/types/shape.rb +136 -65
  118. data/lib/nrser/types/strings.rb +189 -63
  119. data/lib/nrser/types/symbols.rb +83 -33
  120. data/lib/nrser/types/top.rb +89 -0
  121. data/lib/nrser/types/tuples.rb +134 -98
  122. data/lib/nrser/types/type.rb +617 -505
  123. data/lib/nrser/types/when.rb +123 -98
  124. data/lib/nrser/types/where.rb +182 -91
  125. data/lib/nrser/version.rb +1 -1
  126. data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
  127. data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
  128. data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
  129. data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
  130. data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
  131. data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
  132. data/spec/lib/nrser/labs/config_spec.rb +22 -0
  133. data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
  134. data/spec/lib/nrser/types/display_spec.rb +50 -0
  135. data/spec/lib/nrser/types/paths_spec.rb +16 -10
  136. data/spec/lib/nrser/types/selector_spec.rb +125 -0
  137. data/spec/spec_helper.rb +4 -5
  138. metadata +105 -22
  139. data/lib/nrser/types/any.rb +0 -41
  140. data/lib/nrser/types/attrs.rb +0 -213
  141. data/lib/nrser/types/trees.rb +0 -42
@@ -112,7 +112,7 @@ module NRSER
112
112
  # @param [Fixnum] max
113
113
  # Max length to allow for the output string.
114
114
  #
115
- # @param [String] omission:
115
+ # @param [String] omission
116
116
  # The string to stick in the middle where original contents were
117
117
  # removed. Defaults to the unicode ellipsis since I'm targeting the CLI
118
118
  # at the moment and it saves precious characters.
@@ -128,7 +128,7 @@ module NRSER
128
128
  def self.ellipsis source, max, omission: UNICODE_ELLIPSIS
129
129
  return source unless source.length > max
130
130
 
131
- trim_to = max - omission.length
131
+ trim_to = max - ( String === source ? omission.length : 1 )
132
132
  middle = trim_to / 2
133
133
  remainder = trim_to % 2
134
134
 
@@ -175,12 +175,12 @@ module NRSER
175
175
  # Max length to allow for the output string. Result will usually be
176
176
  # *less* than this unless the fallback to {NRSER.ellipsis} kicks in.
177
177
  #
178
- # @param [String] omission:
178
+ # @param [String] omission
179
179
  # The string to stick in the middle where original contents were
180
180
  # removed. Defaults to the unicode ellipsis since I'm targeting the CLI
181
181
  # at the moment and it saves precious characters.
182
182
  #
183
- # @param [String] split:
183
+ # @param [String] split
184
184
  # The string to tokenize the `string` parameter by. If you pass a
185
185
  # {Regexp} here it might work, it might loop out, maybe.
186
186
  #
@@ -0,0 +1,4 @@
1
+ NRSER Gem `nrser/text` Directory
2
+ ========================================================================
3
+
4
+ Function for working with strings that are blocks of text.
@@ -0,0 +1,53 @@
1
+ module NRSER
2
+
3
+ # Format a segment of a message.
4
+ #
5
+ # If `segment` responds to `#to_summary`, it will be called and the
6
+ # result will be returned.
7
+ #
8
+ # Strings are simply returned. Other things are inspected (for now).
9
+ #
10
+ # @param [Object] segment
11
+ # The segment.
12
+ #
13
+ # @return [String]
14
+ # The formatted string for the segment.
15
+ #
16
+ def self.fmt_msg_segment segment
17
+ return segment.to_summary.to_s if segment.respond_to?( :to_summary )
18
+
19
+ return segment if String === segment
20
+
21
+ # TODO Do better!
22
+ segment.inspect
23
+ end
24
+
25
+
26
+ # Provides simple formatting for messages constructed as a list of
27
+ # segments.
28
+ #
29
+ # Allows you to do this sort of thing:
30
+ #
31
+ # NRSER.fmt_msg "Some stuff went wrong with the", thing,
32
+ # "and we're figuring it out, sorry. Maybe take a look at",
33
+ # something_else
34
+ #
35
+ # Which I find easier than interpolation since you quite often have to split
36
+ # across lines anyways.
37
+ #
38
+ # See {.fmt_msg_segment} for info about how each segment is formatted.
39
+ #
40
+ # This methods joins the results together
41
+ #
42
+ # @param [Array] segments
43
+ # Message segments.
44
+ #
45
+ # @return [String]
46
+ # Formatted and joined message ready to pass up to the built-in
47
+ # exception's `#initialize`.
48
+ #
49
+ def self.fmt_msg *segments
50
+ segments.map { |segment| fmt_msg_segment segment }.join( ' ' )
51
+ end # .words
52
+
53
+ end # module NRSER
@@ -120,11 +120,11 @@ module NRSER
120
120
  # @param [String] text
121
121
  # String text to indent tag.
122
122
  #
123
- # @param [String] marker:
123
+ # @param [String] marker
124
124
  # Special string to mark the start of tagged lines. If interpolated text
125
125
  # lines start with this string you're going to have a bad time.
126
126
  #
127
- # @param [String] separator:
127
+ # @param [String] separator
128
128
  # Special string to separate the leading indent from the rest of the line.
129
129
  #
130
130
  # @return [String]
@@ -151,10 +151,10 @@ module NRSER
151
151
  # @param [String] text
152
152
  # Tagged text string.
153
153
  #
154
- # @param [String] marker:
154
+ # @param [String] marker
155
155
  # Must be the marker used to tag the text.
156
156
  #
157
- # @param [String] separator:
157
+ # @param [String] separator
158
158
  # Must be the separator used to tag the text.
159
159
  #
160
160
  # @return [String]
@@ -182,11 +182,11 @@ module NRSER
182
182
  # Indent tag a some text via {NRSER.indent_tag}, call the block with it,
183
183
  # then pass the result through {NRSER.indent_untag} and return that.
184
184
  #
185
- # @param [String] marker:
185
+ # @param [String] marker
186
186
  # Special string to mark the start of tagged lines. If interpolated text
187
187
  # lines start with this string you're going to have a bad time.
188
188
  #
189
- # @param [String] separator:
189
+ # @param [String] separator
190
190
  # Must be the separator used to tag the text.
191
191
  #
192
192
  # @return [String]
@@ -9,10 +9,10 @@ module NRSER
9
9
  # @param [String] text
10
10
  # Text to word wrap.
11
11
  #
12
- # @param [Fixnum] line_width:
12
+ # @param [Fixnum] line_width
13
13
  # Line with in number of character to wrap at.
14
14
  #
15
- # @param [String] break_sequence:
15
+ # @param [String] break_sequence
16
16
  # String to join lines with.
17
17
  #
18
18
  # @return [String]
@@ -14,11 +14,11 @@ module NRSER
14
14
  # @param [#each_pair | (#each_index & #each_with_index)] tree
15
15
  # Tree to walk.
16
16
  #
17
- # @param [Array] path
17
+ # @param [Array] key_path
18
18
  # Key path down to `tree`.
19
19
  #
20
- # @param [Hash<Array, Object>] results
21
- # New hash to stick results in.
20
+ # @param [Proc] block
21
+ # Called with each `(key_path, value)` pair.
22
22
  #
23
23
  # @return [nil]
24
24
  #
@@ -23,7 +23,7 @@ module NRSER
23
23
  #
24
24
  # @param tree (see NRSER.each_branch)
25
25
  #
26
- # @param [Boolean] prune:
26
+ # @param [Boolean] prune
27
27
  # When `true`, prunes out values whose labels end with `?` and values are
28
28
  # `nil`.
29
29
  #
@@ -57,7 +57,7 @@ module NRSER
57
57
  pruned = {}
58
58
 
59
59
  mapped.each { |key, value|
60
- if Types.label.test( key ) &&
60
+ if Types.Label.test( key ) &&
61
61
  key.to_s.end_with?( '?' )
62
62
  unless value.nil?
63
63
  new_key = key.to_s[0..-2]
@@ -1,13 +1,6 @@
1
1
  module NRSER
2
2
 
3
- # @todo Document transform method.
4
- #
5
- # @param [type] arg_name
6
- # @todo Add name param description.
7
- #
8
- # @return [return_type]
9
- # @todo Document return value.
10
- #
3
+
11
4
  def self.transform tree, source
12
5
  map_tree( tree, prune: true ) { |value|
13
6
  if value.is_a? Proc
@@ -39,15 +32,6 @@ module NRSER
39
32
  end
40
33
 
41
34
 
42
-
43
- # @todo Document transformer method.
44
- #
45
- # @param [type] arg_name
46
- # @todo Add name param description.
47
- #
48
- # @return [return_type]
49
- # @todo Document return value.
50
- #
51
35
  def self.transformer &block
52
36
  map_tree( block.call SendSerializer.new ) { |value|
53
37
  if value.is_a? SendSerializer
@@ -59,5 +43,4 @@ module NRSER
59
43
  end # .transformer
60
44
 
61
45
 
62
-
63
46
  end # module NRSER
@@ -0,0 +1,4 @@
1
+ Gem Extensions
2
+ ==============================================================================
3
+
4
+ Monkey-patches to gem dependencies.
@@ -0,0 +1,8 @@
1
+ `lib/nrser/labs` Directory
2
+ ========================================================================
3
+
4
+ Ideas I'm trying out. No consideration for stability at all. Anything in here may be completely changed or totally disappear at any time with no warning.
5
+
6
+ **_Don't use if you want any sort of stability._**
7
+
8
+ Stuff that makes it over the "Ok, this seems like not the worst idea, I'm willing to go with it at least for now" hump will be moved out of here.
@@ -0,0 +1,163 @@
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
+ # Namespace
22
+ # =======================================================================
23
+
24
+ module NRSER
25
+
26
+
27
+ # Definitions
28
+ # =======================================================================
29
+
30
+ # @todo document Config class.
31
+ class Config
32
+
33
+ # Constants
34
+ # ========================================================================
35
+
36
+
37
+ # Mixins
38
+ # ========================================================================
39
+
40
+ include Hamster::Immutable
41
+ include Hamster::Enumerable
42
+ include Hamster::Associable
43
+
44
+
45
+ # Class Methods
46
+ # ========================================================================
47
+
48
+ def self.deep_trie_merge trie, source, &block
49
+ to_put = {}
50
+
51
+ source.each_pair do |key, source_value|
52
+ _, trie_value = trie.get key
53
+
54
+ to_put[ key ] = if [ trie_value, source_value ].all? { |value|
55
+ NRSER.hash_like?( value ) && value.respond_to?( :deep_merge )
56
+ }
57
+ trie_value.deep_merge source_value, &block
58
+ elsif block
59
+ block.call key, trie_value, source_value
60
+ else
61
+ source_value
62
+ end
63
+ end
64
+
65
+ trie.bulk_put to_put
66
+ end # .deep_trie_merge
67
+
68
+
69
+ # Attributes
70
+ # ========================================================================
71
+
72
+
73
+ # Construction
74
+ # ========================================================================
75
+
76
+ # Instantiate a new `Config`.
77
+ def initialize *sources
78
+ @sources = sources
79
+ @trie = sources.reduce( Hamster::EmptyTrie ) { |trie, source|
80
+ self.class.deep_trie_merge trie, source
81
+ }
82
+
83
+ end # #initialize
84
+
85
+
86
+ # Instance Methods
87
+ # ========================================================================
88
+
89
+ # Retrieve the value corresponding to the provided key object. If not found,
90
+ # and this `Hash` has a default block, the default block is called to provide
91
+ # the value. Otherwise, return `nil`.
92
+ #
93
+ # @example
94
+ # h = Hamster::Hash["A" => 1, "B" => 2, "C" => 3]
95
+ # h["B"] # => 2
96
+ # h.get("B") # => 2
97
+ # h.get("Elephant") # => nil
98
+ #
99
+ # # Hamster Hash with a default proc:
100
+ # h = Hamster::Hash.new("A" => 1, "B" => 2, "C" => 3) { |key| key.size }
101
+ # h.get("B") # => 2
102
+ # h.get("Elephant") # => 8
103
+ #
104
+ # @param [Array<Object>] key_path
105
+ # The key to look up
106
+ # @return [Object]
107
+ #
108
+ def get *key_path, type: nil, default: nil
109
+ first, *rest = key_path
110
+ entry = @trie.get first
111
+
112
+ value = if entry
113
+ current = entry[ 1 ]
114
+
115
+ while !current.nil? && !rest.empty?
116
+ first, *rest = rest
117
+
118
+ current = if current.respond_to? :dig
119
+ rest = [] # Short-circuit
120
+ current.dig *rest
121
+
122
+ elsif current.respond_to? :[]
123
+ current[ first ]
124
+
125
+ elsif current.respond_to? :get
126
+ current.get first
127
+
128
+ else
129
+ rest = []
130
+ default
131
+
132
+ end
133
+ end
134
+
135
+ current
136
+
137
+ else
138
+ default
139
+ end
140
+
141
+ parse_and_check key_path, value, type: type
142
+
143
+ end
144
+ alias :[] :get
145
+ alias :dig :get
146
+
147
+
148
+ def parse_and_check key_path, value, type: nil
149
+ return value if type.nil?
150
+ end
151
+
152
+
153
+ def each *args, &block
154
+ @trie.each *args, &block
155
+ end
156
+
157
+
158
+ end # class Config
159
+
160
+ # /Namespace
161
+ # =======================================================================
162
+
163
+ end # module NRSER
data/lib/nrser/labs/i8.rb CHANGED
@@ -15,8 +15,6 @@ require 'hamster'
15
15
  # Project / Package
16
16
  # -----------------------------------------------------------------------
17
17
  require 'nrser/errors/type_error'
18
- require 'nrser/props/immutable/hash'
19
- require 'nrser/props/immutable/vector'
20
18
 
21
19
  require 'nrser/refinements/types'
22
20
  using NRSER::Types
@@ -33,171 +31,63 @@ module I8
33
31
 
34
32
  # Easy way to get the class names shorter..?
35
33
  class Vector < Hamster::Vector; end
34
+
35
+
36
36
  class Hash < Hamster::Hash; end
37
- class Set < Hamster::Set; end
38
- class SortedSet < Hamster::SortedSet; end
39
- # class List < Hamster::List; end # Not a class! Ugh...
40
-
41
-
42
- module Struct
43
-
44
- def self.check_new_args! vector_prop_defs, hash_prop_defs
45
-
46
- unless (vector_prop_defs.empty? && !hash_prop_defs.empty?) ||
47
- (!vector_prop_defs.empty? && hash_prop_defs.empty?)
48
-
49
- raise NRSER::ArgumentError.new \
50
- "Exactly one of *args or **kwds must be empty",
51
-
52
- args: vector_prop_defs,
53
-
54
- kwds: hash_prop_defs,
55
-
56
- details: -> {%{
57
- {I8::Struct.define} proxies to either
58
-
59
- 1. {I8::Struct::Vector.define}
60
- 2. {I8::Struct::Hash.define}
61
-
62
- depending on *where* the property definitions are passed:
63
-
64
- 1. Positionally in `*args` -> {I8::Struct::Vector.new}
65
- 2. By name in `**kwds` -> {I8::Struct::Hash.new}
66
-
67
- Examples:
68
-
69
- 1. Create a Point struct backed by an {I8::Vector}:
70
-
71
- Point = I8::Struct.define [x: t.int], [y: t.int]
72
-
73
- 2. Create a Point struct backed by an {I8::Hash}:
74
-
75
- Point = I8::Struct.define x: t.int, y: t.int
76
-
77
- }}
78
-
79
- end # unless vector_prop_defs.empty? XOR hash_prop_defs.empty?
80
-
81
- end # .check_new_args!
82
-
83
- private_class_method :check_new_args!
84
-
85
-
86
- def self.define *vector_prop_defs, **hash_prop_defs, &body
87
- check_new_args! vector_prop_defs, hash_prop_defs
88
-
89
- if !vector_prop_defs.empty?
90
- raise "not implemented"
91
- # I8::Struct::Vector.new
92
- else
93
- I8::Struct::Hash.new **hash_prop_defs, &body
94
- end
95
- end
96
-
97
- singleton_class.send :alias_method, :new, :define
98
-
99
-
100
- end # module Struct
101
-
37
+
102
38
 
103
- class Struct::Hash < I8::Hash
104
- include I8::Struct
105
- include NRSER::Props::Immutable::Hash
106
-
107
- def self.define **prop_defs, &body
108
- Class.new( I8::Struct::Hash ) do
109
- prop_defs.each do |name, settings|
110
- kwds = t.match settings,
111
- t.type, ->( type ) {{ type: type }},
112
- t.hash_, settings
113
-
114
- prop name, **kwds
115
- end
116
-
117
- class_exec &body if body
118
- end
119
- end
120
-
121
- def self.new *args, **kwds, &block
122
- if self == I8::Struct::Hash
123
- define *args, **kwds, &block
39
+ class Set < Hamster::Set
40
+
41
+ # Get a {I8::Set} containing `items`.
42
+ #
43
+ # Overridden to...
44
+ #
45
+ # 1. Return `items` if items is already a {I8::Set}... sort of like a copy
46
+ # constructor that doesn't actually copy because the instances are
47
+ # immutable.
48
+ #
49
+ # 2. Return an instance of `self` pointing to `items`'s {Hamster::Trie}
50
+ # if `items` is a {Hamster::Set}; this way you get an instance of
51
+ # the correct class but don't do any additional instantiation.
52
+ #
53
+ # 3. Returns {.empty} if `items` responds to `#empty?` truthfully.
54
+ #
55
+ # Otherwise, defers to `super`.
56
+ #
57
+ # @param [#each] items
58
+ # Items for the new set to contain.
59
+ #
60
+ # @return [I8::Set]
61
+ #
62
+ def self.new items = []
63
+ case items
64
+ when self
65
+ items
66
+ when Hamster::Set
67
+ alloc items.instance_variable_get( :@trie )
124
68
  else
125
- # See NOTE in {I8::Struct::Vector.new}
126
- if kwds.empty?
127
- super( *args, &block )
69
+ if items.respond_to?( :empty? ) && items.empty?
70
+ self.empty
128
71
  else
129
- super( *args, **kwds, &block )
72
+ super items
130
73
  end
131
74
  end
132
75
  end
133
- end
134
-
135
-
136
- class Struct::Vector < I8::Vector
137
- include I8::Struct
138
- include NRSER::Props::Immutable::Vector
139
-
140
- def self.define *prop_defs, &body
141
- # Unwrap `[name: type]` format
142
- prop_defs.map! { |prop_def|
143
- if ::Array === prop_def &&
144
- prop_def.length == 1 &&
145
- ::Hash === prop_def[0]
146
- prop_def[0]
147
- else
148
- prop_def
149
- end
150
- }
151
-
152
- # Check we have a list of pairs with label keys
153
- t.array( t.pair( key: t.label ) ).check! prop_defs
154
-
155
- Class.new( I8::Struct::Vector ) do
156
- prop_defs.each_with_index do |pair, index|
157
- name, settings = pair.first
158
-
159
- kwds = t.match settings,
160
- t.type, ->( type ) {{ type: type }},
161
- t.hash_, settings
162
-
163
- prop name, **kwds, index: index
164
- end
165
-
166
- class_exec &body if body
167
- end
168
- end
169
-
170
-
171
- def self.new *args, **kwds, &block
172
- if self == I8::Struct::Vector
173
- unless kwds.empty?
174
- raise NRSER::ArgumentError.new \
175
- "Can not supply keyword args",
176
- args: args,
177
- kwds: kwds
178
- end
179
-
180
- define *args, &block
181
- else
182
- # NOTE This is... weird. Just doing the normal
183
- #
184
- # super( *args, **kwds, &block )
185
- #
186
- # results in `*args` becoming `[*args, {}]` up the super chain
187
- # when `kwds` is empty.
188
- #
189
- # I can't say I can understand it, but I seem to be able to fix
190
- # it.
191
- #
192
- if kwds.empty?
193
- super( *args, &block )
194
- else
195
- super( *args, **kwds, &block )
196
- end
197
- end
76
+
77
+ # Override to build our empty set through {.alloc} so that we can return
78
+ # it in {.new}.
79
+ #
80
+ # @return [I8::Set]
81
+ #
82
+ def self.empty
83
+ @empty ||= alloc Hamster::Trie.new( 0 )
198
84
  end
199
-
200
- end # class Struct::Vector
85
+
86
+ end # class Set
87
+
88
+
89
+ class SortedSet < Hamster::SortedSet; end
90
+ # class List < Hamster::List; end # Not a class! Ugh...
201
91
 
202
92
 
203
93
  def self.[] value