Skip to content

Commit

Permalink
Fix Indexable.range_to_index_and_count to not raise IndexError (#10191)
Browse files Browse the repository at this point in the history
* Fix Indexable.range_to_index_and_count to not raise IndexError

* Let Indexable.range_to_index_and_count return nil
  • Loading branch information
straight-shoota authored Jan 7, 2021
1 parent cb09b0e commit 524c52e
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 18 deletions.
2 changes: 2 additions & 0 deletions spec/std/string_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ describe "String" do
it "gets with range" do
"hello"[1..2]?.should eq "el"
"hello"[6..-1]?.should be_nil
"hello"[-6..-1]?.should be_nil
"hello"[-6..]?.should be_nil
end

it "gets with start and count" do
Expand Down
14 changes: 7 additions & 7 deletions src/array.cr
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ class Array(T)
# a # => [1, 2, 6]
# ```
def []=(range : Range, value : T)
self[*Indexable.range_to_index_and_count(range, size)] = value
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] = value
end

# Replaces a subrange with the elements of the given array.
Expand Down Expand Up @@ -576,7 +576,7 @@ class Array(T)
# a # => [1, 2, 6, 7, 8, 9, 10]
# ```
def []=(range : Range, values : Array(T))
self[*Indexable.range_to_index_and_count(range, size)] = values
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new] = values
end

# Returns all elements that are within the given range.
Expand All @@ -597,7 +597,7 @@ class Array(T)
# a[2..] # => ["c", "d", "e"]
# ```
def [](range : Range)
self[*Indexable.range_to_index_and_count(range, size)]
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]
end

# Like `#[Range]`, but returns `nil` if the range's start is out of range.
Expand All @@ -608,7 +608,7 @@ class Array(T)
# a[6..]? # => nil
# ```
def []?(range : Range)
self[*Indexable.range_to_index_and_count(range, size)]?
self[*Indexable.range_to_index_and_count(range, size) || return nil]?
end

# Returns count or less (if there aren't enough) elements starting at the
Expand Down Expand Up @@ -813,7 +813,7 @@ class Array(T)
# a.delete_at(99..100) # raises IndexError
# ```
def delete_at(range : Range)
index, count = Indexable.range_to_index_and_count(range, self.size)
index, count = Indexable.range_to_index_and_count(range, self.size) || raise IndexError.new
delete_at(index, count)
end

Expand Down Expand Up @@ -932,7 +932,7 @@ class Array(T)
# a.fill(2..3) { |i| i * i } # => [1, 2, 4, 9, 5, 6]
# ```
def fill(range : Range)
fill(*Indexable.range_to_index_and_count(range, size)) do |i|
fill(*Indexable.range_to_index_and_count(range, size) || raise IndexError.new) do |i|
yield i
end
end
Expand Down Expand Up @@ -1020,7 +1020,7 @@ class Array(T)
def fill(value : T, range : Range)
{% if Int::Primitive.union_types.includes?(T) || Float::Primitive.union_types.includes?(T) %}
if value == 0
fill(value, *Indexable.range_to_index_and_count(range, size))
fill(value, *Indexable.range_to_index_and_count(range, size) || raise IndexError.new)

self
else
Expand Down
2 changes: 1 addition & 1 deletion src/bit_array.cr
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct BitArray
# ba[-2...-1] # => BitArray[0]
# ```
def [](range : Range)
self[*Indexable.range_to_index_and_count(range, size)]
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]
end

# Returns count or less (if there aren't enough) elements starting at the
Expand Down
6 changes: 4 additions & 2 deletions src/indexable.cr
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ module Indexable(T)
# b -- c -- d --
# ```
def each(*, within range : Range)
start, count = Indexable.range_to_index_and_count(range, size)
start, count = Indexable.range_to_index_and_count(range, size) || raise IndexError.new
each(start: start, count: count) { |element| yield element }
end

Expand Down Expand Up @@ -600,7 +600,9 @@ module Indexable(T)
start_index = 0
else
start_index += collection_size if start_index < 0
raise IndexError.new if start_index < 0
if start_index < 0
return nil
end
end

end_index = range.end
Expand Down
4 changes: 2 additions & 2 deletions src/regex/match_data.cr
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,12 @@ class Regex

# Returns all matches that are within the given range.
def [](range : Range)
self[*Indexable.range_to_index_and_count(range, size)]
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]
end

# Like `#[Range]`, but returns `nil` if the range's start is out of range.
def []?(range : Range)
self[*Indexable.range_to_index_and_count(range, size)]?
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]?
end

# Returns count or less (if there aren't enough) matches starting at the
Expand Down
4 changes: 2 additions & 2 deletions src/slice.cr
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ struct Slice(T)
# slice[1..33]? # => nil
# ```
def []?(range : Range)
start, count = Indexable.range_to_index_and_count(range, size)
start, count = Indexable.range_to_index_and_count(range, size) || raise IndexError.new
self[start, count]?
end

Expand All @@ -265,7 +265,7 @@ struct Slice(T)
# slice[1..33] # raises IndexError
# ```
def [](range : Range)
start, count = Indexable.range_to_index_and_count(range, size)
start, count = Indexable.range_to_index_and_count(range, size) || raise IndexError.new
self[start, count]
end

Expand Down
8 changes: 4 additions & 4 deletions src/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ class String
# "hello"[6..7] # raises IndexError
# ```
def [](range : Range)
self[*Indexable.range_to_index_and_count(range, size)]
self[*Indexable.range_to_index_and_count(range, size) || raise IndexError.new]
end

# Like `#[Range]`, but returns `nil` if the range's start is out of bounds.
Expand All @@ -770,7 +770,7 @@ class String
# "hello"[6..]? # => nil
# ```
def []?(range : Range)
self[*Indexable.range_to_index_and_count(range, size)]?
self[*Indexable.range_to_index_and_count(range, size) || return nil]?
end

# Returns a substring starting from the *start* character of size *count*.
Expand Down Expand Up @@ -902,7 +902,7 @@ class String
#
# Raises `IndexError` if any index is outside the bounds of this string.
def delete_at(range : Range)
delete_at(*Indexable.range_to_index_and_count(range, size))
delete_at(*Indexable.range_to_index_and_count(range, size) || raise IndexError.new)
end

# Returns a new string that results from deleting the character
Expand Down Expand Up @@ -2303,7 +2303,7 @@ class String
end

private def sub_range(range, replacement)
from, size = Indexable.range_to_index_and_count(range, self.size)
from, size = Indexable.range_to_index_and_count(range, self.size) || raise IndexError.new

from_index = char_index_to_byte_index(from)
raise IndexError.new unless from_index
Expand Down

0 comments on commit 524c52e

Please sign in to comment.