Class: Janeway::AST::ArraySliceSelector
- Inherits:
-
Selector
- Object
- Expression
- Selector
- Janeway::AST::ArraySliceSelector
- Defined in:
- lib/janeway/ast/array_slice_selector.rb
Overview
An array slice selects a series of elements from an array.
It accepts a start and end positions, and a step value that define the range to select. All of these are optional.
ArraySliceSelector needs to store “default” arguments differently from “explicit” arguments, since they’re interpreted differently.
Instance Attribute Summary
Attributes inherited from Selector
Attributes inherited from Expression
Instance Method Summary collapse
-
#bounds(start, end_, step, len) ⇒ Object
IETF: Slice expression parameters start and end are used to derive slice bounds lower and upper.
-
#calculate_index_values(input_size) ⇒ Object
Assign lower and upper bounds to instance variables, based on the input array size.
-
#initialize(start = nil, end_ = nil, step = nil) ⇒ ArraySliceSelector
constructor
A new instance of ArraySliceSelector.
-
#lower_index(input_size) ⇒ Integer
Return the end index to use for stepping through the array, based on a specified array size End index is calculated to omit the final index value, as per the RFC.
-
#normalize(index, len) ⇒ Object
IETF: Slice expression parameters start and end are not directly usable as slice bounds and must first be normalized.
-
#step ⇒ Integer
Return the step size to use for stepping through the array.
- #to_s(brackets: true, **_ignored) ⇒ String
- #tree(level) ⇒ Array
-
#upper_index(input_size) ⇒ Integer
Return the start index to use for stepping through the array, based on a specified array size.
Methods inherited from Selector
Methods inherited from Expression
#indented, #literal?, #singular_query?, #type
Constructor Details
#initialize(start = nil, end_ = nil, step = nil) ⇒ ArraySliceSelector
Returns a new instance of ArraySliceSelector.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 28 def initialize(start = nil, end_ = nil, step = nil) super(nil) # Check arguments [start, end_, step].each do |arg| unless [NilClass, Integer].include?(arg.class) raise Error, "Array slice selector index must be integer or nothing, got #{arg.inspect}" end next unless arg # Check integer size limits raise Error, "Array slice selector value too small: #{arg.inspect}" if arg < INTEGER_MIN raise Error, "Array slice selector value too large: #{arg.inspect}" if arg > INTEGER_MAX end # Nil values are kept to indicate that the "default" values is to be used. # The interpreter selects the actual values. @start = start @end = end_ @step = step end |
Instance Method Details
#bounds(start, end_, step, len) ⇒ Object
IETF: Slice expression parameters start and end are used to derive slice bounds lower and upper. The direction of the iteration, defined by the sign of step, determines which of the parameters is the lower bound and which is the upper bound:¶
124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 124 def bounds(start, end_, step, len) n_start = normalize(start, len) n_end = normalize(end_, len) if step >= 0 lower = n_start.clamp(0, len) upper = n_end.clamp(0, len) else upper = n_start.clamp(-1, len - 1) lower = n_end.clamp(-1, len - 1) end [lower, upper] end |
#calculate_index_values(input_size) ⇒ Object
Assign lower and upper bounds to instance variables, based on the input array size.
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 86 def calculate_index_values(input_size) if step >= 0 start = @start || 0 end_ = @end || input_size else start = @start || (input_size - 1) end_ = @end || ((-1 * input_size) - 1) end bounds(start, end_, step, input_size) end |
#lower_index(input_size) ⇒ Integer
Return the end index to use for stepping through the array, based on a specified array size End index is calculated to omit the final index value, as per the RFC.
78 79 80 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 78 def lower_index(input_size) calculate_index_values(input_size).first end |
#normalize(index, len) ⇒ Object
IETF: Slice expression parameters start and end are not directly usable as slice bounds and must first be normalized.
109 110 111 112 113 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 109 def normalize(index, len) return index if index >= 0 len + index end |
#step ⇒ Integer
Return the step size to use for stepping through the array. Defaults to 1 if it was not given to the constructor.
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 54 def step # The iteration behavior of jsonpath does not match that of ruby Integer#step. # Support the behavior of Integer#step, which needs this: # 1. for stepping forward between positive numbers, use a positive number # 2. for stepping backward between positive numbers, use a negative number # 3. for stepping backward from positive to negative, use a negative number # 4. for stepping backward from negative to negative, use a positive number # Case #4 has to be detected and the sign of step inverted @step || 1 end |
#to_s(brackets: true, **_ignored) ⇒ String
141 142 143 144 145 146 147 148 149 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 141 def to_s(brackets: true, **_ignored) index_str = if @step "#{@start}:#{@end}:#{@step}" else "#{@start}:#{@end}" end brackets ? "[#{index_str}]" : index_str end |
#tree(level) ⇒ Array
153 154 155 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 153 def tree(level) [indented(level, to_s)] end |
#upper_index(input_size) ⇒ Integer
Return the start index to use for stepping through the array, based on a specified array size
69 70 71 |
# File 'lib/janeway/ast/array_slice_selector.rb', line 69 def upper_index(input_size) calculate_index_values(input_size).last end |