| //===--- 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. |
| @_fixed_layout // FIXME(sil-serialize-all) |
| public struct LazyDropWhileSequence<Base: Sequence> { |
| public typealias Element = Base.Element |
| |
| /// Create an instance with elements `transform(x)` for each element |
| /// `x` of base. |
| @inlinable // FIXME(sil-serialize-all) |
| internal init(_base: Base, predicate: @escaping (Element) -> Bool) { |
| self._base = _base |
| self._predicate = predicate |
| } |
| |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal var _base: Base |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal let _predicate: (Element) -> Bool |
| } |
| |
| 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. |
| @_fixed_layout // FIXME(sil-serialize-all) |
| public struct Iterator { |
| public typealias Element = Base.Element |
| |
| @inlinable // FIXME(sil-serialize-all) |
| internal init(_base: Base.Iterator, predicate: @escaping (Element) -> Bool) { |
| self._base = _base |
| self._predicate = predicate |
| } |
| |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal var _predicateHasFailed = false |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal var _base: Base.Iterator |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal let _predicate: (Element) -> Bool |
| } |
| } |
| |
| extension LazyDropWhileSequence.Iterator: IteratorProtocol { |
| @inlinable // FIXME(sil-serialize-all) |
| 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 { |
| public typealias SubSequence = AnySequence<Element> // >:( |
| |
| /// Returns an iterator over the elements of this sequence. |
| /// |
| /// - Complexity: O(1). |
| @inlinable // FIXME(sil-serialize-all) |
| public 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 // FIXME(sil-serialize-all) |
| public 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. |
| @_fixed_layout // FIXME(sil-serialize-all) |
| public struct LazyDropWhileCollection<Base: Collection> { |
| public typealias Element = Base.Element |
| |
| @inlinable // FIXME(sil-serialize-all) |
| internal init(_base: Base, predicate: @escaping (Element) -> Bool) { |
| self._base = _base |
| self._predicate = predicate |
| } |
| |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal var _base: Base |
| @usableFromInline // FIXME(sil-serialize-all) |
| internal let _predicate: (Element) -> Bool |
| } |
| |
| extension LazyDropWhileCollection: Sequence { |
| public typealias Iterator = LazyDropWhileSequence<Base>.Iterator |
| |
| /// Returns an iterator over the elements of this sequence. |
| /// |
| /// - Complexity: O(1). |
| @inlinable // FIXME(sil-serialize-all) |
| public func makeIterator() -> Iterator { |
| return Iterator(_base: _base.makeIterator(), predicate: _predicate) |
| } |
| } |
| |
| extension LazyDropWhileCollection { |
| public typealias SubSequence = Slice<LazyDropWhileCollection<Base>> |
| |
| /// A position in a `LazyDropWhileCollection` or |
| /// `LazyDropWhileBidirectionalCollection` instance. |
| @_fixed_layout // FIXME(sil-serialize-all) |
| public struct Index { |
| /// The position corresponding to `self` in the underlying collection. |
| public let base: Base.Index |
| |
| @inlinable // FIXME(sil-serialize-all) |
| internal init(_base: Base.Index) { |
| self.base = _base |
| } |
| } |
| } |
| |
| extension LazyDropWhileCollection.Index: Equatable, Comparable { |
| @inlinable // FIXME(sil-serialize-all) |
| public static func == ( |
| lhs: LazyDropWhileCollection<Base>.Index, |
| rhs: LazyDropWhileCollection<Base>.Index |
| ) -> Bool { |
| return lhs.base == rhs.base |
| } |
| |
| @inlinable // FIXME(sil-serialize-all) |
| public static func < ( |
| lhs: LazyDropWhileCollection<Base>.Index, |
| rhs: LazyDropWhileCollection<Base>.Index |
| ) -> Bool { |
| return lhs.base < rhs.base |
| } |
| } |
| |
| extension LazyDropWhileCollection.Index: Hashable where Base.Index: Hashable { |
| /// The hash value. |
| @inlinable // FIXME(sil-serialize-all) |
| public var hashValue: Int { |
| return base.hashValue |
| } |
| |
| /// Hashes the essential components of this value by feeding them into the |
| /// given hasher. |
| /// |
| /// - Parameter hasher: The hasher to use when combining the components |
| /// of this instance. |
| @inlinable // FIXME(sil-serialize-all) |
| public func hash(into hasher: inout Hasher) { |
| hasher.combine(base) |
| } |
| } |
| |
| extension LazyDropWhileCollection: Collection { |
| @inlinable // FIXME(sil-serialize-all) |
| public var startIndex: Index { |
| var index = _base.startIndex |
| while index != _base.endIndex && _predicate(_base[index]) { |
| _base.formIndex(after: &index) |
| } |
| return Index(_base: index) |
| } |
| |
| @inlinable // FIXME(sil-serialize-all) |
| public var endIndex: Index { |
| return Index(_base: _base.endIndex) |
| } |
| |
| @inlinable // FIXME(sil-serialize-all) |
| public func index(after i: Index) -> Index { |
| _precondition(i.base < _base.endIndex, "Can't advance past endIndex") |
| return Index(_base: _base.index(after: i.base)) |
| } |
| |
| |
| @inlinable // FIXME(sil-serialize-all) |
| public subscript(position: Index) -> Element { |
| return _base[position.base] |
| } |
| } |
| |
| extension LazyDropWhileCollection: LazyCollectionProtocol { } |
| |
| extension LazyDropWhileCollection: BidirectionalCollection |
| where Base: BidirectionalCollection { |
| @inlinable // FIXME(sil-serialize-all) |
| public func index(before i: Index) -> Index { |
| _precondition(i > startIndex, "Can't move before startIndex") |
| return Index(_base: _base.index(before: i.base)) |
| } |
| } |
| |
| extension LazyCollectionProtocol { |
| /// Returns a lazy collection that skips any initial elements that satisfy |
| /// `predicate`. |
| /// |
| /// - Parameter predicate: A closure that takes an element of the collection |
| /// 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 // FIXME(sil-serialize-all) |
| public func drop( |
| while predicate: @escaping (Elements.Element) -> Bool |
| ) -> LazyDropWhileCollection<Self.Elements> { |
| return LazyDropWhileCollection( |
| _base: self.elements, predicate: predicate) |
| } |
| } |
| |
| @available(*, deprecated, renamed: "LazyDropWhileSequence.Iterator") |
| public typealias LazyDropWhileIterator<T> = LazyDropWhileSequence<T>.Iterator where T: Sequence |
| @available(*, deprecated, renamed: "LazyDropWhileCollection.Index") |
| public typealias LazyDropWhileIndex<T> = LazyDropWhileCollection<T>.Index where T: Collection |
| @available(*, deprecated, renamed: "LazyDropWhileCollection") |
| public typealias LazyDropWhileBidirectionalCollection<T> = LazyDropWhileCollection<T> where T: BidirectionalCollection |
| |