From 89b14d44137f566bf29bf3ed12a64683a0e617f4 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Sat, 5 Oct 2024 09:44:36 +0200 Subject: [PATCH] Implemented the Pipe+AsyncAvailableData struct in the app target, to handle asynchronous stream data coming from a pipe. --- .../Extensions/Pipe+AsyncAvailableData.swift | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Piper/Sources/Logic/Extensions/Pipe+AsyncAvailableData.swift 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() + } + +}