Improve range handling logic of `RepeatedField` (#9799)

Add support for negative start or ends and exclusive ends.

Includes regression tests contributed mostly by @lucthev. Fixes #9751.
pull/9621/head^2
Jason Lunn 3 years ago committed by GitHub
parent 81e5139679
commit 3a477b1952
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
  2. 45
      ruby/tests/repeated_field_test.rb

@ -141,12 +141,14 @@ public class RubyRepeatedField extends RubyObject {
} else if (arg instanceof RubyRange) {
RubyRange range = ((RubyRange) arg);
int beg = RubyNumeric.num2int(range.first(context));
int len = RubyNumeric.num2int(range.size(context));
int first = normalizeArrayIndex(range.first(context));
int last = normalizeArrayIndex(range.last(context));
if (len == 0) return context.runtime.newEmptyArray();
if (last - first < 0) {
return context.runtime.newEmptyArray();
}
return this.storage.subseq(beg, len);
return this.storage.subseq(first, last - first + (range.isExcludeEnd() ? 0 : 1));
}
}
/* assume 2 arguments */

@ -175,6 +175,51 @@ class RepeatedFieldTest < Test::Unit::TestCase
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0..2]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0..5]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0..-1]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0..-3]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0...-1] # Exclusive range
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[0...-3] # Exclusive range
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[-2..-1]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[-5..-1]
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
# Infinite range; introduce in Ruby 2.7.
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
eval "arr[0..]"
end
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
# Beginless range; introduced in Ruby 2.7.
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
eval "arr[..-1]"
end
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
# Infinite range; introduce in Ruby 2.7.
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
eval "arr[0...]" # Exclusive range
end
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
# Beginless range; introduced in Ruby 2.7.
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
eval "arr[...-1]" # Exclusive range
end
end
check_self_modifying_method(m.repeated_string, reference_arr) do |arr|
arr[-1, 1]
end

Loading…
Cancel
Save