@@ -60,6 +60,11 @@ extension Stride: Collection {
6060 self . base = base
6161 }
6262
63+ init ? ( _ base: Base . Index ? ) {
64+ guard let base = base else { return nil }
65+ self . base = base
66+ }
67+
6368 public static func < ( lhs: Index , rhs: Index ) -> Bool {
6469 lhs. base < rhs. base
6570 }
@@ -79,17 +84,34 @@ extension Stride: Collection {
7984
8085 public func index( after i: Index ) -> Index {
8186 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
8488 }
85-
89+
8690 public func index(
8791 _ i: Index ,
88- offsetBy distance : Int ,
92+ offsetBy n : Int ,
8993 limitedBy limit: Index
9094 ) -> 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+ }
93115 }
94116
95117 public var count : Int {
@@ -99,37 +121,25 @@ extension Stride: Collection {
99121
100122 public func distance( from start: Index , to end: Index ) -> Int {
101123 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 )
103125 }
104126
105127 public func index( _ i: Index , offsetBy distance: Int ) -> Index {
106128 precondition ( distance <= 0 || i. base < base. endIndex, " Advancing past end index " )
107129 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!
109134 }
110135}
111136
112137extension Stride : BidirectionalCollection
113138 where Base: RandomAccessCollection {
114-
139+
115140 public func index( before i: Index ) -> Index {
116141 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 )
133143 }
134144}
135145
0 commit comments