@@ -60,6 +60,11 @@ extension Stride: Collection {
60
60
self . base = base
61
61
}
62
62
63
+ init ? ( _ base: Base . Index ? ) {
64
+ guard let base = base else { return nil }
65
+ self . base = base
66
+ }
67
+
63
68
public static func < ( lhs: Index , rhs: Index ) -> Bool {
64
69
lhs. base < rhs. base
65
70
}
@@ -79,17 +84,34 @@ extension Stride: Collection {
79
84
80
85
public func index( after i: Index ) -> Index {
81
86
precondition ( i. base < base. endIndex, " Advancing past end index " )
82
- return base. index ( i. base, offsetBy: stride, limitedBy: base. endIndex)
83
- . map ( Index . init) ?? endIndex
87
+ return index ( i, offsetBy: 1 , limitedBy: endIndex) ?? endIndex
84
88
}
85
-
89
+
86
90
public func index(
87
91
_ i: Index ,
88
- offsetBy distance : Int ,
92
+ offsetBy n : Int ,
89
93
limitedBy limit: Index
90
94
) -> Index ? {
91
- base. index ( i. base, offsetBy: distance * stride, limitedBy: limit. base)
92
- . map ( Index . init)
95
+ guard n != 0 else { return i }
96
+ guard limit != i else { return nil }
97
+ switch ( i, n) {
98
+ case ( endIndex, ..< 0 ) :
99
+ let baseEnd = base. index ( base. endIndex, offsetBy: - ( ( base. count - 1 ) % stride + 1 ) )
100
+ return Index ( base. index ( baseEnd, offsetBy: ( n - n. signum ( ) ) * stride, limitedBy: limit. base) )
101
+ case ( _, 1 ... ) :
102
+ let max = limit < i ? endIndex. base : limit. base
103
+ let idx = base. index ( i. base, offsetBy: n * stride, limitedBy: max)
104
+ if let idx = idx {
105
+ return idx > max ? endIndex : Index ( idx)
106
+ }
107
+ guard i >= limit || limit == endIndex else {
108
+ return nil
109
+ }
110
+ let isToEnd = distance ( from: i, to: endIndex) == n
111
+ return isToEnd ? endIndex : nil
112
+ case _:
113
+ return Index ( base. index ( i. base, offsetBy: n * stride, limitedBy: limit. base) )
114
+ }
93
115
}
94
116
95
117
public var count : Int {
@@ -99,37 +121,25 @@ extension Stride: Collection {
99
121
100
122
public func distance( from start: Index , to end: Index ) -> Int {
101
123
let distance = base. distance ( from: start. base, to: end. base)
102
- return distance / stride + ( distance % stride > 0 ? 1 : 0 )
124
+ return distance / stride + ( abs ( distance % stride) > 0 ? distance . signum ( ) : 0 )
103
125
}
104
126
105
127
public func index( _ i: Index , offsetBy distance: Int ) -> Index {
106
128
precondition ( distance <= 0 || i. base < base. endIndex, " Advancing past end index " )
107
129
precondition ( distance >= 0 || i. base > base. startIndex, " Incrementing past start index " )
108
- return Index ( base. index ( i. base, offsetBy: distance * stride) )
130
+ let limit = distance > 0 ? endIndex : startIndex
131
+ let idx = index ( i, offsetBy: distance, limitedBy: limit)
132
+ precondition ( idx != nil , " The distance \( distance) is not valid for this collection " )
133
+ return idx!
109
134
}
110
135
}
111
136
112
137
extension Stride : BidirectionalCollection
113
138
where Base: RandomAccessCollection {
114
-
139
+
115
140
public func index( before i: Index ) -> Index {
116
141
precondition ( i. base > base. startIndex, " Incrementing past start index " )
117
- if i == endIndex {
118
- let count = base. count
119
- precondition ( count > 0 , " Can't move before the starting index " )
120
- return Index (
121
- base. index ( base. endIndex, offsetBy: - ( ( count - 1 ) % stride + 1 ) )
122
- )
123
- } else {
124
- guard let step = base. index (
125
- i. base,
126
- offsetBy: - stride,
127
- limitedBy: startIndex. base
128
- ) else {
129
- fatalError ( " Incrementing past start index " )
130
- }
131
- return Index ( step)
132
- }
142
+ return index ( i, offsetBy: - 1 )
133
143
}
134
144
}
135
145
0 commit comments