This PR contains the work done to run terminal processes within the context of the app, conforming to Swift concurrency. Reviewed-on: #3 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
71 lines
1.5 KiB
Swift
71 lines
1.5 KiB
Swift
//
|
|
// 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<Data>.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()
|
|
}
|
|
|
|
}
|