@@ -24,6 +24,7 @@ public struct LazySplitCollection<Base: Collection> {
24
24
internal let maxSplits : Int
25
25
internal let omittingEmptySubsequences : Bool
26
26
internal var _startIndex : Index
27
+ internal var _endIndex : Index
27
28
28
29
internal init (
29
30
base: Base ,
@@ -35,10 +36,28 @@ public struct LazySplitCollection<Base: Collection> {
35
36
self . isSeparator = isSeparator
36
37
self . maxSplits = maxSplits
37
38
self . omittingEmptySubsequences = omittingEmptySubsequences
38
- self . _startIndex = Index ( baseRange: base. startIndex..< base. startIndex)
39
+ self . _endIndex = Index (
40
+ baseRange: base. endIndex..< base. endIndex,
41
+ sequenceLength: Int . max,
42
+ separatorCount: Int . max
43
+ )
39
44
40
- if !base. isEmpty {
41
- // Precompute the start index.
45
+ /// We precalculate `startIndex`. There are three possibilities:
46
+ /// 1. `base` is empty and we're _not_ omitting empty subsequences, in which
47
+ /// case the following index describes the sole element of this collection;
48
+ self . _startIndex = Index (
49
+ baseRange: base. startIndex..< base. startIndex,
50
+ sequenceLength: 1 ,
51
+ separatorCount: 0
52
+ )
53
+ if base. isEmpty {
54
+ if omittingEmptySubsequences {
55
+ /// 2. `base` is empty and we _are_ omitting empty subsequences, so this
56
+ /// collection has no elements;
57
+ _startIndex = _endIndex
58
+ }
59
+ } else {
60
+ /// 3. `base` isn't empty, so we must iterate it to determine the start index.
42
61
_startIndex = indexForSubsequence ( atOrAfter: base. startIndex)
43
62
}
44
63
}
@@ -56,23 +75,22 @@ extension LazySplitCollection: LazyCollectionProtocol {
56
75
57
76
internal init (
58
77
baseRange: Range < Base . Index > ,
59
- sequenceLength: Int = 0 ,
60
- separatorCount: Int = 0
78
+ sequenceLength: Int ,
79
+ separatorCount: Int
61
80
) {
62
81
self . baseRange = baseRange
63
82
self . sequenceLength = sequenceLength
64
83
self . separatorCount = separatorCount
65
84
}
66
85
67
86
public static func == ( lhs: Index , rhs: Index ) -> Bool {
68
- // Since each index represents the range of a disparate subsequence, no
69
- // two unique indices will have the same lower bound .
70
- lhs. baseRange . lowerBound == rhs. baseRange . lowerBound
87
+ // `sequenceLength` is equivalent to the index's 1-based position in the
88
+ // collection of indices.
89
+ lhs. sequenceLength == rhs. sequenceLength
71
90
}
72
91
73
92
public static func < ( lhs: Index , rhs: Index ) -> Bool {
74
- // Only use the lower bound to test for ordering, as above.
75
- lhs. baseRange. lowerBound < rhs. baseRange. lowerBound
93
+ lhs. sequenceLength < rhs. sequenceLength
76
94
}
77
95
}
78
96
@@ -128,7 +146,7 @@ extension LazySplitCollection: LazyCollectionProtocol {
128
146
}
129
147
130
148
public var endIndex : Index {
131
- Index ( baseRange : base . endIndex ..< base . endIndex )
149
+ _endIndex
132
150
}
133
151
134
152
public func index( after i: Index ) -> Index {
@@ -147,10 +165,11 @@ extension LazySplitCollection: LazyCollectionProtocol {
147
165
&& i. sequenceLength < i. separatorCount + 1
148
166
{
149
167
/// The base collection ended with a separator, so we need to emit one
150
- /// more empty subsequence. Its range can't be equal to that of
151
- /// `endIndex`, else we'll terminate iteration prematurely.
168
+ /// more empty subsequence. This one differs from `endIndex` in its
169
+ /// `sequenceLength` (except in an extreme edge case!), which is the
170
+ /// sole property tested for equality and comparison.
152
171
return Index (
153
- baseRange: i . baseRange . upperBound ..< i . baseRange . upperBound ,
172
+ baseRange: base . endIndex ..< base . endIndex ,
154
173
sequenceLength: i. sequenceLength + 1 ,
155
174
separatorCount: i. separatorCount
156
175
)
0 commit comments