@@ -126,17 +126,11 @@ public typealias LazyFilterIndex<Base : Collection> = Base.Index
126
126
/// general operations on `LazyFilterCollection` instances may not have the
127
127
/// documented complexity.
128
128
@_fixed_layout // FIXME(sil-serialize-all)
129
- public struct LazyFilterCollection <
130
- Base : Collection
131
- > : LazyCollectionProtocol , Collection {
132
-
133
- /// A type that represents a valid position in the collection.
134
- ///
135
- /// Valid indices consist of the position of every element and a
136
- /// "past the end" position that's not valid for use as a subscript.
137
- public typealias Index = Base . Index
138
- public typealias Element = Base . Element
139
-
129
+ public struct LazyFilterCollection < Base : Collection > {
130
+ @_versioned // FIXME(sil-serialize-all)
131
+ internal var _base : Base
132
+ @_versioned // FIXME(sil-serialize-all)
133
+ internal let _predicate : ( Base . Element ) -> Bool
140
134
141
135
/// Creates an instance containing the elements of `base` that
142
136
/// satisfy `isIncluded`.
@@ -149,6 +143,38 @@ public struct LazyFilterCollection<
149
143
self . _base = _base
150
144
self . _predicate = isIncluded
151
145
}
146
+ }
147
+
148
+ extension LazyFilterCollection : Sequence {
149
+ public typealias SubSequence = LazyFilterCollection < Base . SubSequence >
150
+ public typealias Element = Base . Element
151
+
152
+ // Any estimate of the number of elements that pass `_predicate` requires
153
+ // iterating the collection and evaluating each element, which can be costly,
154
+ // is unexpected, and usually doesn't pay for itself in saving time through
155
+ // preventing intermediate reallocations. (SR-4164)
156
+ @_inlineable // FIXME(sil-serialize-all)
157
+ public var underestimatedCount : Int { return 0 }
158
+
159
+ @_inlineable // FIXME(sil-serialize-all)
160
+ public func _copyToContiguousArray( )
161
+ -> ContiguousArray < Base . Iterator . Element > {
162
+
163
+ // The default implementation of `_copyToContiguousArray` queries the
164
+ // `count` property, which evaluates `_predicate` for every element --
165
+ // see the note above `underestimatedCount`. Here we treat `self` as a
166
+ // sequence and only rely on underestimated count.
167
+ return _copySequenceToContiguousArray ( self )
168
+ }
169
+
170
+ /// Returns an iterator over the elements of this sequence.
171
+ ///
172
+ /// - Complexity: O(1).
173
+ @_inlineable // FIXME(sil-serialize-all)
174
+ public func makeIterator( ) -> LazyFilterIterator < Base . Iterator > {
175
+ return LazyFilterIterator (
176
+ _base: _base. makeIterator ( ) , _predicate)
177
+ }
152
178
153
179
@_inlineable
154
180
public func _customContainsEquatableElement(
@@ -162,6 +188,14 @@ public struct LazyFilterCollection<
162
188
}
163
189
return nil
164
190
}
191
+ }
192
+
193
+ extension LazyFilterCollection : LazyCollectionProtocol , Collection {
194
+ /// A type that represents a valid position in the collection.
195
+ ///
196
+ /// Valid indices consist of the position of every element and a
197
+ /// "past the end" position that's not valid for use as a subscript.
198
+ public typealias Index = Base . Index
165
199
166
200
/// The position of the first element in a non-empty collection.
167
201
///
@@ -207,53 +241,96 @@ public struct LazyFilterCollection<
207
241
i = index
208
242
}
209
243
210
- /// Accesses the element at `position`.
211
- ///
212
- /// - Precondition: `position` is a valid position in `self` and
213
- /// `position != endIndex`.
214
244
@_inlineable // FIXME(sil-serialize-all)
215
- public subscript( position: Index ) -> Base . Element {
216
- return _base [ position]
245
+ // FIXME(conditional-conformances): this is a copy of a default
246
+ // implementation. Can be removed once teh default one allows negative
247
+ // results to be returned.
248
+ public func distance( from start: Index , to end: Index ) -> Int {
249
+ var _start : Index
250
+ let _end : Index
251
+ let step : Int
252
+ if start > end {
253
+ _start = end
254
+ _end = start
255
+ step = - 1
256
+ }
257
+ else {
258
+ _start = start
259
+ _end = end
260
+ step = 1
261
+ }
262
+ var count = 0
263
+ while _start != _end {
264
+ count += step
265
+ formIndex ( after: & _start)
266
+ }
267
+ return count
217
268
}
218
269
219
- public typealias SubSequence = LazyFilterCollection < Base . SubSequence >
270
+ @inline ( __always)
271
+ @_inlineable // FIXME(sil-serialize-all)
272
+ @_versioned // FIXME(sil-serialize-all)
273
+ internal func _advanceIndex( _ i: inout Index , step: Int ) {
274
+ repeat {
275
+ _base. formIndex ( & i, offsetBy: step)
276
+ } while i != _base. endIndex && !_predicate( _base [ i] )
277
+ }
220
278
221
279
@_inlineable // FIXME(sil-serialize-all)
222
- public subscript( bounds: Range < Index > ) -> SubSequence {
223
- return SubSequence ( _base: _base [ bounds] , _predicate)
280
+ public func index( _ i: Index , offsetBy n: Int ) -> Index {
281
+ var i = i
282
+ let step = n. signum ( )
283
+ for _ in 0 ..< abs ( numericCast ( n) ) {
284
+ _advanceIndex ( & i, step: step)
285
+ }
286
+ return i
224
287
}
225
288
226
- // Any estimate of the number of elements that pass `_predicate` requires
227
- // iterating the collection and evaluating each element, which can be costly,
228
- // is unexpected, and usually doesn't pay for itself in saving time through
229
- // preventing intermediate reallocations. (SR-4164)
230
289
@_inlineable // FIXME(sil-serialize-all)
231
- public var underestimatedCount : Int { return 0 }
290
+ public func formIndex( _ i: inout Index , offsetBy n: Int ) {
291
+ i = index ( i, offsetBy: n)
292
+ }
232
293
233
294
@_inlineable // FIXME(sil-serialize-all)
234
- public func _copyToContiguousArray( )
235
- -> ContiguousArray < Base . Iterator . Element > {
295
+ public func index(
296
+ _ i: Index , offsetBy n: Int , limitedBy limit: Index
297
+ ) -> Index ? {
298
+ var i = i
299
+ let step = n. signum ( )
300
+ for _ in 0 ..< abs ( numericCast ( n) ) {
301
+ if i == limit {
302
+ return nil
303
+ }
304
+ _advanceIndex ( & i, step: step)
305
+ }
306
+ return i
307
+ }
236
308
237
- // The default implementation of `_copyToContiguousArray` queries the
238
- // `count` property, which evaluates `_predicate` for every element --
239
- // see the note above `underestimatedCount`. Here we treat `self` as a
240
- // sequence and only rely on underestimated count.
241
- return _copySequenceToContiguousArray ( self )
309
+ @_inlineable // FIXME(sil-serialize-all)
310
+ public func formIndex(
311
+ _ i: inout Index , offsetBy n: Int , limitedBy limit: Index
312
+ ) -> Bool {
313
+ if let advancedIndex = index ( i, offsetBy: n, limitedBy: limit) {
314
+ i = advancedIndex
315
+ return true
316
+ }
317
+ i = limit
318
+ return false
242
319
}
243
320
244
- /// Returns an iterator over the elements of this sequence .
321
+ /// Accesses the element at `position` .
245
322
///
246
- /// - Complexity: O(1).
323
+ /// - Precondition: `position` is a valid position in `self` and
324
+ /// `position != endIndex`.
247
325
@_inlineable // FIXME(sil-serialize-all)
248
- public func makeIterator( ) -> LazyFilterIterator < Base . Iterator > {
249
- return LazyFilterIterator (
250
- _base: _base. makeIterator ( ) , _predicate)
326
+ public subscript( position: Index ) -> Base . Element {
327
+ return _base [ position]
251
328
}
252
329
253
- @_versioned // FIXME(sil-serialize-all)
254
- internal var _base : Base
255
- @ _versioned // FIXME(sil-serialize-all )
256
- internal let _predicate : ( Base . Element ) -> Bool
330
+ @_inlineable // FIXME(sil-serialize-all)
331
+ public subscript ( bounds : Range < Index > ) -> SubSequence {
332
+ return SubSequence ( _base : _base [ bounds ] , _predicate )
333
+ }
257
334
}
258
335
259
336
extension LazyFilterCollection : BidirectionalCollection
0 commit comments