Gemini/GeminiProtocol/GeminiDataTask.swift

83 lines
2.3 KiB
Swift

//
// GeminiDataTask.swift
// GeminiProtocol
//
// Created by Shadowfacts on 7/14/20.
//
import Foundation
import Network
public class GeminiDataTask {
public let request: GeminiRequest
private let completion: (Result<GeminiResponse, Error>) -> Void
private let connection: GeminiConnection
public private(set) var completed: Bool = false
public init(request: GeminiRequest, completion: @escaping (Result<GeminiResponse, Error>) -> Void) {
self.request = request
self.completion = completion
self.connection = GeminiConnection(endpoint: .url(request.url))
self.connection.delegate = self
}
public convenience init(url: URL, completion: @escaping (Result<GeminiResponse, Error>) -> Void) throws {
self.init(request: try GeminiRequest(url: url), completion: completion)
}
deinit {
self.cancel()
}
public func resume() {
self.connection.startConnection()
}
public func cancel() {
connection.cancelConnection()
}
}
public extension GeminiDataTask {
enum Error: Swift.Error {
case noData
case connectionError(NWError)
}
}
extension GeminiDataTask: GeminiConnectionDelegate {
public func connectionReady(_ connection: GeminiConnection) {
connection.sendRequest(self.request)
}
public func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader) {
guard !completed else {
print("GeminiRequestTask(\(self)) has already completed, shouldn't be receiving any data")
return
}
completed = true
if let data = data {
let response = GeminiResponse(header: header, body: data)
self.completion(.success(response))
} else {
self.completion(.failure(.noData))
}
}
public func connection(_ connection: GeminiConnection, handleError error: GeminiConnection.Error) {
guard !completed else {
print("GeminiRequestTask(\(self)) has already completed, shouldn't be receiving any data")
return
}
completed = true
self.completion(.failure(.connectionError(error)))
}
public func connectionCompleted(_ connection: GeminiConnection) {
}
}