Fix IndexSet.RangeView indexing with subranges

On initialization, IndexSet.RangeView made the erroneous assumption that given an intersection range, a nil _indexOfRange(containing: bound) indicated that the bound was beyond the beginning or end of the index set. Instead, the index could simply not exist.

We now calculate the actual intersection of the parent index set with the given intersection range and use that as the index set to view.

This also makes the unit tests for testing range views more comprehensive.
This commit is contained in:
Itai Ferber
2017-07-24 15:32:03 -07:00
parent 1a0544450f
commit b05866a92f
2 changed files with 66 additions and 90 deletions

View File

@@ -58,42 +58,16 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
fileprivate var indexSet: IndexSet
// Range of element values
private var intersectingRange : Range<IndexSet.Element>?
fileprivate init(indexSet : IndexSet, intersecting range : Range<IndexSet.Element>?) {
self.indexSet = indexSet
self.intersectingRange = range
if let r = range {
if r.lowerBound == r.upperBound {
startIndex = 0
endIndex = 0
} else {
let minIndex = indexSet._indexOfRange(containing: r.lowerBound)
let maxIndex = indexSet._indexOfRange(containing: r.upperBound)
switch (minIndex, maxIndex) {
case (nil, nil):
startIndex = 0
endIndex = 0
case (nil, .some(let max)):
// Start is before our first range
startIndex = 0
endIndex = max + 1
case (.some(let min), nil):
// End is after our last range
startIndex = min
endIndex = indexSet._rangeCount
case (.some(let min), .some(let max)):
startIndex = min
endIndex = max + 1
}
}
let otherIndexes = IndexSet(integersIn: r)
self.indexSet = indexSet.intersection(otherIndexes)
} else {
startIndex = 0
endIndex = indexSet._rangeCount
self.indexSet = indexSet
}
self.startIndex = 0
self.endIndex = self.indexSet._rangeCount
}
public func makeIterator() -> IndexingIterator<RangeView> {
@@ -102,11 +76,7 @@ public struct IndexSet : ReferenceConvertible, Equatable, BidirectionalCollectio
public subscript(index : Index) -> CountableRange<IndexSet.Element> {
let indexSetRange = indexSet._range(at: index)
if let intersectingRange = intersectingRange {
return Swift.max(intersectingRange.lowerBound, indexSetRange.lowerBound)..<Swift.min(intersectingRange.upperBound, indexSetRange.upperBound)
} else {
return indexSetRange.lowerBound..<indexSetRange.upperBound
}
return indexSetRange.lowerBound..<indexSetRange.upperBound
}
public subscript(bounds: Range<Index>) -> BidirectionalSlice<RangeView> {