diff --git a/Piper/Sources/Logic/Extensions/Pipe+AsyncAvailableData.swift b/Piper/Sources/Logic/Extensions/Pipe+AsyncAvailableData.swift new file mode 100644 index 0000000..853c653 --- /dev/null +++ b/Piper/Sources/Logic/Extensions/Pipe+AsyncAvailableData.swift @@ -0,0 +1,70 @@ +// +// Pipe+AsyncAvailableData.swift +// Piper ~ App +// +// Created by Javier Cicchelli on 05/10/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import Foundation + +extension Pipe { + struct AsyncAvailableData { + + // MARK: Properties + + private let pipe: Pipe + + // MARK: Initialisers + + init(_ pipe: Pipe) { + self.pipe = pipe + } + + // MARK: Functions + + func append() async -> Data { + var data = Data() + + for await availableData in self { + data.append(availableData) + } + + return data + } + + } +} + +// MARK: - AsyncSequence + +extension Pipe.AsyncAvailableData: AsyncSequence { + + // MARK: Type aliases + + typealias AsyncIterator = AsyncStream.Iterator + typealias Element = Data + + // MARK: Functions + + func makeAsyncIterator() -> AsyncIterator { + AsyncStream { continuation in + pipe.fileHandleForReading.readabilityHandler = { @Sendable handler in + let data = handler.availableData + + guard !data.isEmpty else { + continuation.finish() + return + } + + continuation.yield(data) + } + + continuation.onTermination = { _ in + pipe.fileHandleForReading.readabilityHandler = nil + } + } + .makeAsyncIterator() + } + +}