blob: f150c80ef27d007eb89582a8aa8af20e453c207d [file] [log] [blame]
//===--- SentinelCollection.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
//
//===----------------------------------------------------------------------===//
public // @testable
protocol _Function {
associatedtype Input
associatedtype Output
func apply(_: Input) -> Output
}
protocol _Predicate : _Function where Output == Bool { }
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct _SentinelIterator<
Base: IteratorProtocol,
IsSentinel : _Predicate
> : IteratorProtocol, Sequence
where IsSentinel.Input == Base.Element {
@_versioned // FIXME(sil-serialize-all)
internal var _base: Base
@_versioned // FIXME(sil-serialize-all)
internal var _isSentinel: IsSentinel
@_versioned // FIXME(sil-serialize-all)
internal var _expired: Bool = false
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(_ base: Base, until condition: IsSentinel) {
_base = base
_isSentinel = condition
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal mutating func next() -> Base.Element? {
guard _fastPath(!_expired) else { return nil }
let x = _base.next()
// We don't need this check if it's a precondition that the sentinel will be
// found
// guard _fastPath(x != nil), let y = x else { return x }
guard _fastPath(!_isSentinel.apply(x!)) else { _expired = true; return nil }
return x
}
}
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct _SentinelCollection<
Base: Collection,
IsSentinel : _Predicate
> : Collection
where IsSentinel.Input == Base.Iterator.Element {
@_versioned // FIXME(sil-serialize-all)
internal let _isSentinel: IsSentinel
@_versioned // FIXME(sil-serialize-all)
internal var _base : Base
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func makeIterator() -> _SentinelIterator<Base.Iterator, IsSentinel> {
return _SentinelIterator(_base.makeIterator(), until: _isSentinel)
}
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct Index : Comparable {
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(
_impl: (position: Base.Index, element: Base.Iterator.Element)?
) {
self._impl = _impl
}
@_versioned // FIXME(sil-serialize-all)
internal var _impl: (position: Base.Index, element: Base.Iterator.Element)?
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal static func == (lhs: Index, rhs: Index) -> Bool {
if rhs._impl == nil { return lhs._impl == nil }
return lhs._impl != nil && rhs._impl!.position == lhs._impl!.position
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal static func < (lhs: Index, rhs: Index) -> Bool {
if rhs._impl == nil { return lhs._impl != nil }
return lhs._impl != nil && rhs._impl!.position < lhs._impl!.position
}
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var startIndex : Index {
return _index(at: _base.startIndex)
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var endIndex : Index {
return Index(_impl: nil)
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal subscript(i: Index) -> Base.Iterator.Element {
return i._impl!.element
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func index(after i: Index) -> Index {
return _index(at: _base.index(after: i._impl!.position))
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func _index(at i: Base.Index) -> Index {
// We don't need this check if it's a precondition that the sentinel will be
// found
// guard _fastPath(i != _base.endIndex) else { return endIndex }
let e = _base[i]
guard _fastPath(!_isSentinel.apply(e)) else { return endIndex }
return Index(_impl: (position: i, element: e))
}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init(_ base: Base, until condition: IsSentinel) {
_base = base
_isSentinel = condition
}
}
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal struct _IsZero<T : BinaryInteger> : _Predicate {
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal init() {}
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal func apply(_ x: T) -> Bool {
return x == 0
}
}