1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
//===--- DropWhile.swift - Lazy views for drop(while:) --------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// A sequence whose elements consist of the elements that follow the initial
/// consecutive elements of some base sequence that satisfy a given predicate.
@frozen // lazy-performance
public struct LazyDropWhileSequence<Base: Sequence> {
public typealias Element = Base.Element
@usableFromInline // lazy-performance
internal var _base: Base
@usableFromInline // lazy-performance
internal let _predicate: (Element) -> Bool
/// Create an instance with elements `transform(x)` for each element
/// `x` of base.
@inlinable // lazy-performance
internal init(_base: Base, predicate: @escaping (Element) -> Bool) {
self._base = _base
self._predicate = predicate
}
}
@available(*, unavailable)
extension LazyDropWhileSequence: Sendable {}
extension LazyDropWhileSequence {
/// An iterator over the elements traversed by a base iterator that follow the
/// initial consecutive elements that satisfy a given predicate.
///
/// This is the associated iterator for the `LazyDropWhileSequence`,
/// `LazyDropWhileCollection`, and `LazyDropWhileBidirectionalCollection`
/// types.
@frozen // lazy-performance
public struct Iterator {
public typealias Element = Base.Element
@usableFromInline // lazy-performance
internal var _predicateHasFailed = false
@usableFromInline // lazy-performance
internal var _base: Base.Iterator
@usableFromInline // lazy-performance
internal let _predicate: (Element) -> Bool
@inlinable // lazy-performance
internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) {
self._base = _base
self._predicate = predicate
}
}
}
@available(*, unavailable)
extension LazyDropWhileSequence.Iterator: Sendable {}
extension LazyDropWhileSequence.Iterator: IteratorProtocol {
@inlinable // lazy-performance
public mutating func next() -> Element? {
// Once the predicate has failed for the first time, the base iterator
// can be used for the rest of the elements.
if _predicateHasFailed {
return _base.next()
}
// Retrieve and discard elements from the base iterator until one fails
// the predicate.
while let nextElement = _base.next() {
if !_predicate(nextElement) {
_predicateHasFailed = true
return nextElement
}
}
return nil
}
}
extension LazyDropWhileSequence: Sequence {
/// Returns an iterator over the elements of this sequence.
///
/// - Complexity: O(1).
@inlinable // lazy-performance
public __consuming func makeIterator() -> Iterator {
return Iterator(_base: _base.makeIterator(), predicate: _predicate)
}
}
extension LazyDropWhileSequence: LazySequenceProtocol {
public typealias Elements = LazyDropWhileSequence
}
extension LazySequenceProtocol {
/// Returns a lazy sequence that skips any initial elements that satisfy
/// `predicate`.
///
/// - Parameter predicate: A closure that takes an element of the sequence as
/// its argument and returns `true` if the element should be skipped or
/// `false` otherwise. Once `predicate` returns `false` it will not be
/// called again.
@inlinable // lazy-performance
public __consuming func drop(
while predicate: @escaping (Elements.Element) -> Bool
) -> LazyDropWhileSequence<Self.Elements> {
return LazyDropWhileSequence(_base: self.elements, predicate: predicate)
}
}
/// A lazy wrapper that includes the elements of an underlying
/// collection after any initial consecutive elements that satisfy a
/// predicate.
///
/// - Note: The performance of accessing `startIndex`, `first`, or any methods
/// that depend on `startIndex` depends on how many elements satisfy the
/// predicate at the start of the collection, and may not offer the usual
/// performance given by the `Collection` protocol. Be aware, therefore,
/// that general operations on lazy collections may not have the
/// documented complexity.
public typealias LazyDropWhileCollection<T: Collection> = LazyDropWhileSequence<T>
extension LazyDropWhileCollection: Collection {
public typealias SubSequence = Slice<LazyDropWhileCollection<Base>>
public typealias Index = Base.Index
@inlinable // lazy-performance
public var startIndex: Index {
var index = _base.startIndex
while index != _base.endIndex && _predicate(_base[index]) {
_base.formIndex(after: &index)
}
return index
}
@inlinable // lazy-performance
public var endIndex: Index {
return _base.endIndex
}
@inlinable // lazy-performance
public func index(after i: Index) -> Index {
_precondition(i < _base.endIndex, "Can't advance past endIndex")
return _base.index(after: i)
}
@inlinable // lazy-performance
public subscript(position: Index) -> Element {
return _base[position]
}
}
extension LazyDropWhileCollection: BidirectionalCollection
where Base: BidirectionalCollection {
@inlinable // lazy-performance
public func index(before i: Index) -> Index {
_precondition(i > startIndex, "Can't move before startIndex")
return _base.index(before: i)
}
}
extension LazyDropWhileCollection: LazyCollectionProtocol { }
|