@@ -32,7 +32,7 @@ public struct ClosedRangeIndex<Bound> : Comparable
32
32
// CountableClosedRange is not interchangeable with CountableRange in all
33
33
// contexts.
34
34
Bound : protocol < _Strideable , Comparable > ,
35
- Bound. Stride : Integer {
35
+ Bound. Stride : SignedInteger {
36
36
/// Creates the "past the end" position.
37
37
internal init ( ) { _value = . pastEnd }
38
38
@@ -47,26 +47,64 @@ public struct ClosedRangeIndex<Bound> : Comparable
47
47
}
48
48
}
49
49
50
- internal func _predecessor( upperBound limit: Bound ) -> ClosedRangeIndex {
50
+ internal func _predecessor(
51
+ lowerBound: Bound , upperBound limit: Bound
52
+ ) -> ClosedRangeIndex {
51
53
switch _value {
52
- case . inRange( let x) : return ClosedRangeIndex ( x. advanced ( by: - 1 ) )
53
- case . pastEnd: return ClosedRangeIndex ( limit)
54
+ case . inRange( let x) :
55
+ _precondition ( x > lowerBound, " Incrementing past start index " )
56
+ return ClosedRangeIndex ( x. advanced ( by: - 1 ) )
57
+ case . pastEnd:
58
+ _precondition ( limit >= lowerBound, " Incrementing past start index " )
59
+ return ClosedRangeIndex ( limit)
54
60
}
55
61
}
56
62
57
63
internal func _advanced(
58
- by n: Bound . Stride , upperBound limit: Bound
64
+ by n: Bound . Stride , lowerBound : Bound , upperBound limit: Bound
59
65
) -> ClosedRangeIndex {
60
66
switch _value {
61
67
case . inRange( let x) :
62
68
let d = x. distance ( to: limit)
63
- if n <= d { return ClosedRangeIndex ( x. advanced ( by: n) ) }
69
+ if n <= d {
70
+ let newPosition = x. advanced ( by: n)
71
+ _precondition ( newPosition >= lowerBound,
72
+ " Advancing past start index " )
73
+ return ClosedRangeIndex ( newPosition)
74
+ }
64
75
if d - - 1 == n { return ClosedRangeIndex ( ) }
65
76
_preconditionFailure ( " Advancing past end index " )
66
77
case . pastEnd:
67
- return n == 0
68
- ? self :
69
- ClosedRangeIndex ( limit) . _advanced ( by: n, upperBound: limit)
78
+ if n == 0 {
79
+ return self
80
+ } else if n > 0 {
81
+ _preconditionFailure ( " Advancing past end index " )
82
+ } else {
83
+ return ClosedRangeIndex ( limit) . _advanced (
84
+ by: ( n + 1 ) ,
85
+ lowerBound: lowerBound,
86
+ upperBound: limit
87
+ )
88
+ }
89
+ }
90
+ }
91
+
92
+ internal func _distance(
93
+ to: ClosedRangeIndex < Bound > , upperBound limit: Bound
94
+ ) -> Bound . Stride {
95
+ switch ( _value, to. _value) {
96
+ case let ( . inRange( left) , . inRange( right) ) :
97
+ // in range <--> in range
98
+ return left. distance ( to: right)
99
+ case let ( . inRange( left) , . pastEnd) :
100
+ // in range --> end
101
+ return 1 + left. distance ( to: limit)
102
+ case let ( . pastEnd, . inRange( right) ) :
103
+ // in range <-- end
104
+ return limit. distance ( to: right) - 1
105
+ case ( . pastEnd, . pastEnd) :
106
+ // end <--> end
107
+ return 0
70
108
}
71
109
}
72
110
@@ -220,17 +258,20 @@ public struct CountableClosedRange<Bound> : RandomAccessCollection
220
258
}
221
259
222
260
public func index( after i: Index ) -> Index {
223
- // FIXME: swift-3-indexing-model: range checks and tests.
224
261
return i. _successor ( upperBound: upperBound)
225
262
}
226
263
227
264
public func index( before i: Index ) -> Index {
228
- // FIXME: swift-3-indexing-model: range checks and tests.
229
- return i. _predecessor ( upperBound: upperBound)
265
+ return i. _predecessor ( lowerBound: lowerBound, upperBound: upperBound)
230
266
}
231
267
232
- // FIXME: swift-3-indexing-model: implement O(1) `index(_:offsetBy:)`
233
- // and `distance(from:to:)`, and write tests for them.
268
+ public func index( _ i: Index , offsetBy n: IndexDistance ) -> Index {
269
+ return i. _advanced ( by: n, lowerBound: lowerBound, upperBound: upperBound)
270
+ }
271
+
272
+ public func distance( from start: Index , to end: Index ) -> IndexDistance {
273
+ return start. _distance ( to: end, upperBound: upperBound)
274
+ }
234
275
235
276
/// Accesses the element at specified position.
236
277
///
0 commit comments