Files
swift-mirror/stdlib/public/Concurrency/AsyncSequence.swift
Philippe Hausler 8578584f61 Implementations for operators and async functions on AsyncSequence per SE-0298 (#35740)
* Implementations for operators and async functions on AsyncSequence per SE-0298

* Add trailing new lines to AsyncSequence adopter files

* Remove extra // from preambles

* Transition sequence properties and sequence initializers to internal

* Rename Upstream to Base

* Rename "Failable" asynchronous sequences to "Throwing"

* Make iteration consistent with closure lifetimes and track failure via state

* Use for await syntax for async function extensions on AsyncSequence

* Work-around rethrows calculations being incorrect for conformance + closure rethrowing

* Update testing names to reflect Throwing versus Failable

* Incorperate runAsyncAndBlock into the test function for suite calls

* Remove @frozen from AsyncSequence operators

* Back out reduce family functions for now due to IRGen bug

* Additional corrections for throwing cases and fix up potential linux crasher

* Add a upstream and throwing tests and correct flatMap's throwing behavior

* Unify parameter names to count

* Add a more helpful precondition on prefix

* Add tests for throwing cases of non closure async functions on AsyncSequence

* Correct missing count transition in dropFirst

* Correct missing , in assertion

* [NFC] add commentary on optimization in dropFirst on dropFirst

* Disable collect tests for non macOS platforms for now

* Disable all async sequence tests for non macOS platforms for now
2021-02-12 14:43:59 -08:00

166 lines
4.2 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 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
//
//===----------------------------------------------------------------------===//
import Swift
@rethrows
public protocol AsyncSequence {
associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element == Element
associatedtype Element
__consuming func makeAsyncIterator() -> AsyncIterator
}
extension AsyncSequence {
@inlinable
public func reduce<Result>(
_ initialResult: Result,
_ nextPartialResult:
(_ partialResult: Result, Element) async throws -> Result
) async rethrows -> Result {
var accumulator = initialResult
var iterator = makeAsyncIterator()
while let element = try await iterator.next() {
accumulator = try await nextPartialResult(accumulator, element)
}
return accumulator
}
@inlinable
public func reduce<Result>(
into initialResult: __owned Result,
_ updateAccumulatingResult:
(_ partialResult: inout Result, Element) async throws -> Void
) async rethrows -> Result {
var accumulator = initialResult
var iterator = makeAsyncIterator()
while let element = try await iterator.next() {
try await updateAccumulatingResult(&accumulator, element)
}
return accumulator
}
}
@inlinable
@inline(__always)
func _contains<Source: AsyncSequence>(
_ self: Source,
where predicate: (Source.Element) async throws -> Bool
) async rethrows -> Bool {
for try await element in self {
if try await predicate(element) {
return true
}
}
return false
}
extension AsyncSequence {
@inlinable
public func contains(
where predicate: (Element) async throws -> Bool
) async rethrows -> Bool {
return try await _contains(self, where: predicate)
}
@inlinable
public func allSatisfy(
_ predicate: (Element) async throws -> Bool
) async rethrows -> Bool {
return try await !contains { try await !predicate($0) }
}
}
extension AsyncSequence where Element: Equatable {
@inlinable
public func contains(_ search: Element) async rethrows -> Bool {
for try await element in self {
if element == search {
return true
}
}
return false
}
}
@inlinable
@inline(__always)
func _first<Source: AsyncSequence>(
_ self: Source,
where predicate: (Source.Element) async throws -> Bool
) async rethrows -> Source.Element? {
for try await element in self {
if try await predicate(element) {
return element
}
}
return nil
}
extension AsyncSequence {
@inlinable
public func first(
where predicate: (Element) async throws -> Bool
) async rethrows -> Element? {
return try await _first(self, where: predicate)
}
}
extension AsyncSequence {
@inlinable
@warn_unqualified_access
public func min(
by areInIncreasingOrder: (Element, Element) async throws -> Bool
) async rethrows -> Element? {
var it = makeAsyncIterator()
guard var result = try await it.next() else {
return nil
}
while let e = try await it.next() {
if try await areInIncreasingOrder(e, result) {
result = e
}
}
return result
}
@inlinable
@warn_unqualified_access
public func max(
by areInIncreasingOrder: (Element, Element) async throws -> Bool
) async rethrows -> Element? {
var it = makeAsyncIterator()
guard var result = try await it.next() else {
return nil
}
while let e = try await it.next() {
if try await areInIncreasingOrder(result, e) {
result = e
}
}
return result
}
}
extension AsyncSequence where Element: Comparable {
@inlinable
@warn_unqualified_access
public func min() async rethrows -> Element? {
return try await self.min(by: <)
}
@inlinable
@warn_unqualified_access
public func max() async rethrows -> Element? {
return try await self.max(by: <)
}
}