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
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Async Algorithms open source project
//
// Copyright (c) 2022 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
//
//===----------------------------------------------------------------------===//
extension AsyncSequence {
func violatingSpecification(returningPastEndIteration element: Element) -> SpecificationViolatingSequence<Self> {
SpecificationViolatingSequence(self, kind: .producing(element))
}
func violatingSpecification(throwingPastEndIteration error: Error) -> SpecificationViolatingSequence<Self> {
SpecificationViolatingSequence(self, kind: .throwing(error))
}
}
struct SpecificationViolatingSequence<Base: AsyncSequence> {
enum Kind {
case producing(Base.Element)
case throwing(Error)
}
let base: Base
let kind: Kind
init(_ base: Base, kind: Kind) {
self.base = base
self.kind = kind
}
}
extension SpecificationViolatingSequence: AsyncSequence {
typealias Element = Base.Element
struct Iterator: AsyncIteratorProtocol {
var iterator: Base.AsyncIterator
let kind: Kind
var finished = false
var violated = false
mutating func next() async throws -> Element? {
if finished {
if violated {
return nil
}
violated = true
switch kind {
case .producing(let element): return element
case .throwing(let error): throw error
}
}
do {
if let value = try await iterator.next() {
return value
}
finished = true
return nil
} catch {
finished = true
throw error
}
}
}
func makeAsyncIterator() -> Iterator {
Iterator(iterator: base.makeAsyncIterator(), kind: kind)
}
}
|