Module: JSI::Base::ArrayNode

Includes:
Util::Arraylike
Defined in:
lib/jsi/base/node.rb

Overview

Included on JSI::Base subclasses for instances that are Array or #to_ary.

Dynamically defines most methods of Array to make the JSI duck-type like an Array.

Constant Summary

Constants included from Util::Arraylike

Util::Arraylike::DESTRUCTIVE_METHODS, Util::Arraylike::SAFE_INDEX_ELEMENT_METHODS, Util::Arraylike::SAFE_INDEX_ONLY_METHODS, Util::Arraylike::SAFE_METHODS

Instance Method Summary collapse

Methods included from Util::Arraylike

#assoc, #pretty_print, #rassoc

Instance Method Details

#[](token, as_jsi: jsi_child_as_jsi_default, use_default: jsi_child_use_default_default) ⇒ Object

Raises:



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/jsi/base/node.rb', line 211

def [](token, as_jsi: jsi_child_as_jsi_default, use_default: jsi_child_use_default_default)
  raise(BlockGivenError) if block_given?
  token = token.jsi_node_content if token.is_a?(Schema::SchemaAncestorNode)
  size = jsi_node_content_ary_pubsend(:size)
  if token.is_a?(Integer)
    if token < 0
      if token < -size
        nil
      else
        jsi_child(token + size, as_jsi: as_jsi)
      end
    else
      if token < size
        jsi_child(token, as_jsi: as_jsi)
      else
        if use_default
          jsi_default_child(token, as_jsi: as_jsi)
        else
          nil
        end
      end
    end
  elsif token.is_a?(Range)
    type_err = proc do
      raise(TypeError, [
        "given range does not contain Integers",
        "range: #{token.inspect}",
      ].join("\n"))
    end

    start_idx = token.begin
    if start_idx.is_a?(Integer)
      start_idx += size if start_idx < 0
      return Util::EMPTY_ARY if start_idx == size
      return nil if start_idx < 0 || start_idx > size
    elsif start_idx.nil?
      start_idx = 0
    else
      type_err.call
    end

    end_idx = token.end
    if end_idx.is_a?(Integer)
      end_idx += size if end_idx < 0
      end_idx += 1 unless token.exclude_end?
      end_idx = size if end_idx > size
      return Util::EMPTY_ARY if start_idx >= end_idx
    elsif end_idx.nil?
      end_idx = size
    else
      type_err.call
    end

    (start_idx...end_idx).map { |i| jsi_child(i, as_jsi: as_jsi) }.freeze
  else
    raise(TypeError, [
      "expected `token` param to be an Integer or Range",
      "token: #{token.inspect}",
    ].join("\n"))
  end
end

#as_json(options = {}) ⇒ Object



300
301
302
# File 'lib/jsi/base/node.rb', line 300

def as_json(options = {})
  each_index.map { |i| jsi_child_node(i).as_json(**options) }
end

#each(**kw) {|Object| ... } ⇒ self, Enumerator

yields each array element of this node.

each yielded element is the result of JSI::Base#[] for each index of the instance array.

Parameters:

Yields:

  • (Object)

    each element of this array node

Returns:

  • (self, Enumerator)

    an Enumerator if invoked without a block; otherwise self



285
286
287
288
289
# File 'lib/jsi/base/node.rb', line 285

def each(**kw, &block)
  return to_enum(__method__, **kw) { jsi_node_content_ary_pubsend(:size) } unless block
  jsi_node_content_ary_pubsend(:each_index) { |i| yield(self[i, **kw]) }
  self
end

#jsi_array?Boolean

See JSI::Base#jsi_array?. Always true for ArrayNode.

Returns:

  • (Boolean)


183
184
185
# File 'lib/jsi/base/node.rb', line 183

def jsi_array?
  true
end

#jsi_as_child_default_as_jsiObject

See JSI::Base#jsi_as_child_default_as_jsi. true for ArrayNode.



274
275
276
# File 'lib/jsi/base/node.rb', line 274

def jsi_as_child_default_as_jsi
  true
end

#jsi_child_token_present?(token) ⇒ Boolean

Returns:

  • (Boolean)


195
196
197
# File 'lib/jsi/base/node.rb', line 195

def jsi_child_token_present?(token)
  token.is_a?(Integer) && token >= 0 && token < jsi_node_content_ary_pubsend(:size)
end

#jsi_each_child_token(&block) ⇒ Object

Yields each index - see JSI::Base#jsi_each_child_token



188
189
190
191
192
# File 'lib/jsi/base/node.rb', line 188

def jsi_each_child_token(&block)
  return to_enum(__method__) { jsi_node_content_ary_pubsend(:size) } unless block
  jsi_node_content_ary_pubsend(:each_index, &block)
  nil
end

#jsi_node_content_ary_pubsend(method_name, *a, **kw, &b) ⇒ Object

invokes the method with the given name on the jsi_node_content (if defined) or its #to_ary

Parameters:

  • method_name (String, Symbol)
  • a

    positional arguments are passed to the invocation of method_name

  • kw

    keyword arguments are passed to the invocation of method_name

  • b

    block is passed to the invocation of method_name

Returns:

  • (Object)

    the result of calling method method_name on the jsi_node_content or its #to_ary



312
313
314
315
316
317
318
# File 'lib/jsi/base/node.rb', line 312

def jsi_node_content_ary_pubsend(method_name, *a, &b)
  if jsi_node_content.respond_to?(method_name)
    jsi_node_content.public_send(method_name, *a, &b)
  else
    jsi_node_content.to_ary.public_send(method_name, *a, &b)
  end
end

#jsi_node_content_child(token) ⇒ Object



200
201
202
203
204
205
206
207
208
# File 'lib/jsi/base/node.rb', line 200

def jsi_node_content_child(token)
  # we check token_present? here (unlike HashNode) because we do not want to pass
  # negative indices, Ranges, or non-Integers to Array#[]
  if jsi_child_token_present?(token)
    jsi_node_content_ary_pubsend(:[], token)
  else
    nil
  end
end

#to_ary(**kw) ⇒ Array

an array, the same size as the instance array, in which the element at each index is the result of JSI::Base#[].

Parameters:

Returns:

  • (Array)


295
296
297
# File 'lib/jsi/base/node.rb', line 295

def to_ary(**kw)
  to_a(**kw)
end